From 11162d43cd734be50dc1f7ac62d9aab14e87e400 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 10 Dec 2012 15:19:29 +0000 Subject: [PATCH 001/831] SECOAUTH-365: Fix ordering issue in current uri calculation --- .../oauth2/client/filter/OAuth2ClientContextFilter.java | 8 +++++--- .../client/filter/TestOAuth2ClientContextFilter.java | 9 +++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilter.java index 433f1a3d6..074c4572c 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilter.java @@ -124,12 +124,17 @@ protected void redirectUser(UserRedirectRequiredException e, HttpServletRequest * @return The current uri. */ protected String calculateCurrentUri(HttpServletRequest request) throws UnsupportedEncodingException { + StringBuilder queryBuilder = new StringBuilder(); + @SuppressWarnings("unchecked") Enumeration paramNames = request.getParameterNames(); while (paramNames.hasMoreElements()) { String name = (String) paramNames.nextElement(); if (!"code".equals(name)) { + if (queryBuilder.length() > 0) { + queryBuilder.append('&'); + } String[] parameterValues = request.getParameterValues(name); if (parameterValues.length == 0) { queryBuilder.append(URLEncoder.encode(name, "UTF-8")); @@ -146,9 +151,6 @@ protected String calculateCurrentUri(HttpServletRequest request) throws Unsuppor } } - if (paramNames.hasMoreElements() && queryBuilder.length() > 0) { - queryBuilder.append('&'); - } } return UrlUtils.buildFullRequestUrl(request.getScheme(), request.getServerName(), diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/TestOAuth2ClientContextFilter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/TestOAuth2ClientContextFilter.java index ce9f9260c..53633cd79 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/TestOAuth2ClientContextFilter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/TestOAuth2ClientContextFilter.java @@ -27,4 +27,13 @@ public void testCurrentUriRemovingCode() throws Exception { assertEquals("http://localhost/?foo=bar", filter.calculateCurrentUri(request)); } + @Test + public void testCurrentUriRemovingCodeInSecond() throws Exception { + OAuth2ClientContextFilter filter = new OAuth2ClientContextFilter(); + MockHttpServletRequest request = new MockHttpServletRequest(); + request.addParameter("foo", "bar"); + request.addParameter("code", "XXXX"); + assertEquals("http://localhost/?foo=bar", filter.calculateCurrentUri(request)); + } + } From b9974875ef23e79ac31514db60fee4843eb9aea2 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 10 Dec 2012 15:20:18 +0000 Subject: [PATCH 002/831] Javadocs corrections --- .../security/oauth2/provider/ClientDetailsService.java | 9 ++++----- .../provider/error/DefaultOAuth2ExceptionRenderer.java | 5 +++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientDetailsService.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientDetailsService.java index 93730bea7..76c6632ef 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientDetailsService.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientDetailsService.java @@ -16,22 +16,21 @@ package org.springframework.security.oauth2.provider; -import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; /** - * A service that provides the details about an oauth 2client. + * A service that provides the details about an OAuth2 client. * * @author Ryan Heaton */ public interface ClientDetailsService { /** - * Load a client by the client id. This method must NOT return null. + * Load a client by the client id. This method must not return null. * * @param clientId The client id. * @return The client details. - * @throws OAuth2Exception If the client account is locked, expired, disabled, or for any other reason. + * @throws ClientRegistrationException If the client account is locked, expired, disabled, or for any other reason. */ - ClientDetails loadClientByClientId(String clientId) throws OAuth2Exception; + ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException; } \ No newline at end of file diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/DefaultOAuth2ExceptionRenderer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/DefaultOAuth2ExceptionRenderer.java index f5b7b33bb..917ea5675 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/DefaultOAuth2ExceptionRenderer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/DefaultOAuth2ExceptionRenderer.java @@ -39,8 +39,9 @@ import org.springframework.web.context.request.ServletWebRequest; /** - * Default implementation of {@link OAuth2ExceptionRenderer} that can render the exceptions as JSON. If the caller only - * accepts a specific media type (like XML) then this implementation will not handle it. + * Default implementation of {@link OAuth2ExceptionRenderer} that can render the exceptions using message converters + * (just like regular Spring MVC endpoints). If the caller sends an appropriate Accept header he should get the right + * result as long as an appropriate message converter is provided. * * @author Dave Syer * From 5161576ac58ad8edd110282ebf0f4f2490e92440 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 12 Dec 2012 11:35:44 +0000 Subject: [PATCH 003/831] SECOAUTH-372: use authentication key for comparison instead of complete authentication --- .../provider/token/InMemoryTokenStore.java | 7 ++-- .../oauth2/provider/token/JdbcTokenStore.java | 38 ++++++++++++------- .../provider/token/TestTokenStoreBase.java | 32 ++++++++++++---- 3 files changed, 52 insertions(+), 25 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStore.java index 14226ac4d..0f4c76e8c 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStore.java @@ -112,9 +112,10 @@ public int getExpiryTokenCount() { } public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) { - OAuth2AccessToken accessToken = authenticationToAccessTokenStore.get(authenticationKeyGenerator - .extractKey(authentication)); - if (accessToken != null && !authentication.equals(readAuthentication(accessToken.getValue()))) { + String key = authenticationKeyGenerator.extractKey(authentication); + OAuth2AccessToken accessToken = authenticationToAccessTokenStore.get(key); + if (accessToken != null + && !key.equals(authenticationKeyGenerator.extractKey(readAuthentication(accessToken.getValue())))) { // Keep the stores consistent (maybe the same user is represented by this authentication but the details // have changed) storeAccessToken(accessToken, authentication); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JdbcTokenStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JdbcTokenStore.java index 58174a4a3..e2766bb34 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JdbcTokenStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JdbcTokenStore.java @@ -100,23 +100,26 @@ public void setAuthenticationKeyGenerator(AuthenticationKeyGenerator authenticat public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) { OAuth2AccessToken accessToken = null; + String key = authenticationKeyGenerator.extractKey(authentication); try { accessToken = jdbcTemplate.queryForObject(selectAccessTokenFromAuthenticationSql, new RowMapper() { public OAuth2AccessToken mapRow(ResultSet rs, int rowNum) throws SQLException { return deserializeAccessToken(rs.getBytes(2)); } - }, authenticationKeyGenerator.extractKey(authentication)); + }, key); } catch (EmptyResultDataAccessException e) { if (LOG.isInfoEnabled()) { LOG.debug("Failed to find access token for authentication " + authentication); } - } catch (IllegalArgumentException e) { + } + catch (IllegalArgumentException e) { LOG.error("Could not extract access token for authentication " + authentication); } - if (accessToken != null && !authentication.equals(readAuthentication(accessToken.getValue()))) { + if (accessToken != null + && !key.equals(authenticationKeyGenerator.extractKey(readAuthentication(accessToken.getValue())))) { removeAccessToken(accessToken.getValue()); // Keep the store consistent (maybe the same user is represented by this authentication but the details have // changed) @@ -135,8 +138,8 @@ public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authe new SqlLobValue(serializeAccessToken(token)), authenticationKeyGenerator.extractKey(authentication), authentication.isClientOnly() ? null : authentication.getName(), authentication.getAuthorizationRequest().getClientId(), - new SqlLobValue(serializeAuthentication(authentication)), extractTokenKey(refreshToken) }, new int[] { Types.VARCHAR, - Types.BLOB, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.BLOB, Types.VARCHAR }); + new SqlLobValue(serializeAuthentication(authentication)), extractTokenKey(refreshToken) }, new int[] { + Types.VARCHAR, Types.BLOB, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.BLOB, Types.VARCHAR }); } public OAuth2AccessToken readAccessToken(String tokenValue) { @@ -153,7 +156,8 @@ public OAuth2AccessToken mapRow(ResultSet rs, int rowNum) throws SQLException { if (LOG.isInfoEnabled()) { LOG.info("Failed to find access token for token " + tokenValue); } - } catch (IllegalArgumentException e) { + } + catch (IllegalArgumentException e) { LOG.warn("Failed to deserialize access token for " + tokenValue); removeAccessToken(tokenValue); } @@ -188,7 +192,8 @@ public OAuth2Authentication mapRow(ResultSet rs, int rowNum) throws SQLException if (LOG.isInfoEnabled()) { LOG.info("Failed to find access token for token " + token); } - } catch (IllegalArgumentException e) { + } + catch (IllegalArgumentException e) { LOG.warn("Failed to deserialize authentication for " + token); removeAccessToken(token); } @@ -217,7 +222,8 @@ public OAuth2RefreshToken mapRow(ResultSet rs, int rowNum) throws SQLException { if (LOG.isInfoEnabled()) { LOG.info("Failed to find refresh token for token " + token); } - } catch (IllegalArgumentException e) { + } + catch (IllegalArgumentException e) { LOG.warn("Failed to deserialize refresh token for token " + token); removeRefreshToken(token); } @@ -252,7 +258,8 @@ public OAuth2Authentication mapRow(ResultSet rs, int rowNum) throws SQLException if (LOG.isInfoEnabled()) { LOG.info("Failed to find access token for token " + value); } - } catch (IllegalArgumentException e) { + } + catch (IllegalArgumentException e) { LOG.warn("Failed to deserialize access token for " + value); removeRefreshToken(value); } @@ -273,7 +280,8 @@ public Collection findTokensByClientId(String clientId) { List accessTokens = new ArrayList(); try { - accessTokens = jdbcTemplate.query(selectAccessTokensFromClientIdSql, new SafeAccessTokenRowMapper(), clientId); + accessTokens = jdbcTemplate.query(selectAccessTokensFromClientIdSql, new SafeAccessTokenRowMapper(), + clientId); } catch (EmptyResultDataAccessException e) { if (LOG.isInfoEnabled()) { @@ -289,7 +297,8 @@ public Collection findTokensByUserName(String userName) { List accessTokens = new ArrayList(); try { - accessTokens = jdbcTemplate.query(selectAccessTokensFromUserNameSql, new SafeAccessTokenRowMapper(), userName); + accessTokens = jdbcTemplate.query(selectAccessTokensFromUserNameSql, new SafeAccessTokenRowMapper(), + userName); } catch (EmptyResultDataAccessException e) { if (LOG.isInfoEnabled()) { @@ -304,7 +313,7 @@ public Collection findTokensByUserName(String userName) { private List removeNulls(List accessTokens) { List tokens = new ArrayList(); for (OAuth2AccessToken token : accessTokens) { - if (token!=null) { + if (token != null) { tokens.add(token); } } @@ -312,7 +321,7 @@ private List removeNulls(List accessTokens } protected String extractTokenKey(String value) { - if (value==null) { + if (value == null) { return null; } MessageDigest digest; @@ -336,7 +345,8 @@ private final class SafeAccessTokenRowMapper implements RowMapper Date: Wed, 5 Dec 2012 11:06:17 +0100 Subject: [PATCH 004/831] changed calculateCurrentUri to use ServleturiComponentsBuilder to keep parameters in order --- .../filter/OAuth2ClientContextFilter.java | 36 ++----------------- 1 file changed, 2 insertions(+), 34 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilter.java index 074c4572c..2f552154c 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilter.java @@ -3,7 +3,6 @@ import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; -import java.util.Enumeration; import java.util.Map; import javax.servlet.Filter; @@ -23,8 +22,8 @@ import org.springframework.security.web.PortResolverImpl; import org.springframework.security.web.RedirectStrategy; import org.springframework.security.web.util.ThrowableAnalyzer; -import org.springframework.security.web.util.UrlUtils; import org.springframework.util.Assert; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; import org.springframework.web.util.NestedServletException; /** @@ -124,38 +123,7 @@ protected void redirectUser(UserRedirectRequiredException e, HttpServletRequest * @return The current uri. */ protected String calculateCurrentUri(HttpServletRequest request) throws UnsupportedEncodingException { - - StringBuilder queryBuilder = new StringBuilder(); - - @SuppressWarnings("unchecked") - Enumeration paramNames = request.getParameterNames(); - while (paramNames.hasMoreElements()) { - String name = (String) paramNames.nextElement(); - if (!"code".equals(name)) { - if (queryBuilder.length() > 0) { - queryBuilder.append('&'); - } - String[] parameterValues = request.getParameterValues(name); - if (parameterValues.length == 0) { - queryBuilder.append(URLEncoder.encode(name, "UTF-8")); - } - else { - for (int i = 0; i < parameterValues.length; i++) { - String parameterValue = parameterValues[i]; - queryBuilder.append(URLEncoder.encode(name, "UTF-8")).append('=') - .append(URLEncoder.encode(parameterValue, "UTF-8")); - if (i + 1 < parameterValues.length) { - queryBuilder.append('&'); - } - } - } - } - - } - - return UrlUtils.buildFullRequestUrl(request.getScheme(), request.getServerName(), - portResolver.getServerPort(request), request.getRequestURI(), - queryBuilder.length() > 0 ? queryBuilder.toString() : null); + return ServletUriComponentsBuilder.fromRequest(request).replaceQueryParam("code").build(true).toUriString(); } public void init(FilterConfig filterConfig) throws ServletException { From 0e729754fd24acd155104126dbd3e54fc9ce4069 Mon Sep 17 00:00:00 2001 From: bimsapi Date: Sun, 2 Dec 2012 22:47:33 -0500 Subject: [PATCH 005/831] Add support for handling AccountStatus exceptions (expired, locked). --- .../password/ResourceOwnerPasswordTokenGranter.java | 5 +++++ .../TestResourceOwnerPasswordTokenGranter.java | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java index 616a4ec5e..8423327e2 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java @@ -19,6 +19,7 @@ import java.util.Map; +import org.springframework.security.authentication.AccountStatusException; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; @@ -57,6 +58,10 @@ protected OAuth2Authentication getOAuth2Authentication(AuthorizationRequest clie try { userAuth = authenticationManager.authenticate(userAuth); } + catch (AccountStatusException ase) { + //covers expired, locked, disabled cases (mentioned in section 5.2, draft 31) + throw new InvalidGrantException(ase.getMessage()); + } catch (BadCredentialsException e) { // If the username/password are wrong the spec says we should send 400/bad grant throw new InvalidGrantException(e.getMessage()); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/TestResourceOwnerPasswordTokenGranter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/TestResourceOwnerPasswordTokenGranter.java index c1d15e421..747e353d1 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/TestResourceOwnerPasswordTokenGranter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/TestResourceOwnerPasswordTokenGranter.java @@ -21,6 +21,7 @@ import org.junit.Test; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.LockedException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; @@ -89,6 +90,16 @@ public Authentication authenticate(Authentication authentication) throws Authent }, providerTokenServices, clientDetailsService); granter.grant("password", authorizationRequest); } + + @Test(expected = InvalidGrantException.class) + public void testAccountLocked() { + ResourceOwnerPasswordTokenGranter granter = new ResourceOwnerPasswordTokenGranter(new AuthenticationManager() { + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + throw new LockedException("test"); + } + }, providerTokenServices, clientDetailsService); + granter.grant("password", authorizationRequest); + } @Test(expected = InvalidGrantException.class) public void testUnauthenticated() { From 12585c2654dbd50737648d3995ef64744f9c34e6 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 13 Dec 2012 10:07:49 +0000 Subject: [PATCH 006/831] SECOAUTH-371: handle all client registration exceptions the same way --- .../oauth2/provider/endpoint/AuthorizationEndpoint.java | 8 ++++---- .../security/oauth2/provider/endpoint/TokenEndpoint.java | 9 +++++---- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java index 61b3599c1..085e174d5 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java @@ -42,8 +42,8 @@ import org.springframework.security.oauth2.common.exceptions.UserDeniedAuthorizationException; import org.springframework.security.oauth2.common.util.OAuth2Utils; import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.ClientRegistrationException; import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; -import org.springframework.security.oauth2.provider.NoSuchClientException; import org.springframework.security.oauth2.provider.approval.DefaultUserApprovalHandler; import org.springframework.security.oauth2.provider.approval.UserApprovalHandler; import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; @@ -436,9 +436,9 @@ public void setUserApprovalHandler(UserApprovalHandler userApprovalHandler) { this.userApprovalHandler = userApprovalHandler; } - @ExceptionHandler(NoSuchClientException.class) - public ModelAndView handleNoSuchClientException(Exception e, ServletWebRequest webRequest) throws Exception { - logger.info("Handling NoSuchClientException error: " + e.getMessage()); + @ExceptionHandler(ClientRegistrationException.class) + public ModelAndView handleClientRegistrationException(Exception e, ServletWebRequest webRequest) throws Exception { + logger.info("Handling ClientRegistrationException error: " + e.getMessage()); return handleException(new BadClientCredentialsException(), webRequest); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java index 2afa4221c..9740480c8 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java @@ -32,8 +32,8 @@ import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.common.exceptions.UnsupportedGrantTypeException; import org.springframework.security.oauth2.common.util.OAuth2Utils; +import org.springframework.security.oauth2.provider.ClientRegistrationException; import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; -import org.springframework.security.oauth2.provider.NoSuchClientException; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; @@ -107,9 +107,10 @@ public ResponseEntity getAccessToken(Principal principal, } - @ExceptionHandler(NoSuchClientException.class) - public ResponseEntity handleNoSuchClientException(Exception e) throws Exception { - return handleException(new BadClientCredentialsException()); + @ExceptionHandler(ClientRegistrationException.class) + public ResponseEntity handleClientRegistrationException(Exception e) throws Exception { + logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage()); + return getExceptionTranslator().translate(new BadClientCredentialsException()); } @ExceptionHandler(OAuth2Exception.class) From f4842d9585b85e90a0ca7c5043d350c39d8c0165 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 14 Dec 2012 16:33:07 +0000 Subject: [PATCH 007/831] SECOAUTH-363: add old-style Pragma: no-cache to error responses --- .../provider/error/DefaultWebResponseExceptionTranslator.java | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/DefaultWebResponseExceptionTranslator.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/DefaultWebResponseExceptionTranslator.java index 24ca56287..8015ad1f5 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/DefaultWebResponseExceptionTranslator.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/DefaultWebResponseExceptionTranslator.java @@ -68,6 +68,7 @@ private ResponseEntity handleOAuth2Exception(OAuth2Exception e) int status = e.getHttpErrorCode(); HttpHeaders headers = new HttpHeaders(); headers.set("Cache-Control", "no-store"); + headers.set("Pragma", "no-cache"); if (status == HttpStatus.UNAUTHORIZED.value() || (e instanceof InsufficientScopeException)) { headers.set("WWW-Authenticate", String.format("%s %s", OAuth2AccessToken.BEARER_TYPE, e.getSummary())); } From 23dfbfded837c9913b593237c32d1ce68c1c0b7b Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 14 Dec 2012 16:47:37 +0000 Subject: [PATCH 008/831] SECOAUTH-360: Add Basic prefix to auth errors from token endpoint --- .../oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml index f6a00c0d6..6ce98cae4 100644 --- a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml +++ b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml @@ -77,8 +77,9 @@ - + + From a6febe6c035fe71c335a0ac2ba9ff5bb09141999 Mon Sep 17 00:00:00 2001 From: Ali Moghadam Date: Fri, 21 Dec 2012 17:41:46 -0800 Subject: [PATCH 009/831] SECOAUTH-361: Allow user to inject AuthenticationDetailsSource into Also fixed TestOAuth2ClientContextFilter test case --- .../config/ResourceServerBeanDefinitionParser.java | 10 ++++++++++ .../security/oauth2/spring-security-oauth2-1.0.xsd | 8 ++++++++ .../client/filter/TestOAuth2ClientContextFilter.java | 9 +++------ .../config/TestResourceServerBeanDefinitionParser.java | 5 +++-- .../TestResourceServerBeanDefinitionParser-context.xml | 10 ++++++---- 5 files changed, 30 insertions(+), 12 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/ResourceServerBeanDefinitionParser.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/ResourceServerBeanDefinitionParser.java index 1c934d981..645bdbd1a 100755 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/ResourceServerBeanDefinitionParser.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/ResourceServerBeanDefinitionParser.java @@ -36,22 +36,32 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P String resourceId = element.getAttribute("resource-id"); String entryPointRef = element.getAttribute("entry-point-ref"); + String entryAuthDetailsSource = element.getAttribute("auth-details-source-ref"); // configure the protected resource filter BeanDefinitionBuilder protectedResourceFilterBean = BeanDefinitionBuilder .rootBeanDefinition(OAuth2AuthenticationProcessingFilter.class); + BeanDefinitionBuilder authenticationManagerBean = BeanDefinitionBuilder .rootBeanDefinition(OAuth2AuthenticationManager.class); + authenticationManagerBean.addPropertyReference("tokenServices", tokenServicesRef); + if (StringUtils.hasText(resourceId)) { authenticationManagerBean.addPropertyValue("resourceId", resourceId); } + protectedResourceFilterBean.addPropertyValue("authenticationManager", authenticationManagerBean.getBeanDefinition()); + if (StringUtils.hasText(entryPointRef)) { protectedResourceFilterBean.addPropertyReference("authenticationEntryPoint", entryPointRef); } + if (StringUtils.hasText(entryAuthDetailsSource)) { + protectedResourceFilterBean.addPropertyReference("authenticationDetailsSource", entryAuthDetailsSource); + } + return protectedResourceFilterBean.getBeanDefinition(); } diff --git a/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.0.xsd b/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.0.xsd index d0ed3906f..2e12bca5a 100644 --- a/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.0.xsd +++ b/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.0.xsd @@ -370,6 +370,14 @@ + + + + + The reference to the bean that defines the AuthenticationDetailsSource. + + + diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/TestOAuth2ClientContextFilter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/TestOAuth2ClientContextFilter.java index 53633cd79..1e257513b 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/TestOAuth2ClientContextFilter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/TestOAuth2ClientContextFilter.java @@ -14,7 +14,7 @@ public class TestOAuth2ClientContextFilter { public void testVanillaCurrentUri() throws Exception { OAuth2ClientContextFilter filter = new OAuth2ClientContextFilter(); MockHttpServletRequest request = new MockHttpServletRequest(); - request.addParameter("foo", "bar"); + request.setQueryString("foo=bar"); assertEquals("http://localhost/?foo=bar", filter.calculateCurrentUri(request)); } @@ -22,8 +22,7 @@ public void testVanillaCurrentUri() throws Exception { public void testCurrentUriRemovingCode() throws Exception { OAuth2ClientContextFilter filter = new OAuth2ClientContextFilter(); MockHttpServletRequest request = new MockHttpServletRequest(); - request.addParameter("code", "XXXX"); - request.addParameter("foo", "bar"); + request.setQueryString("code=XXXX&foo=bar"); assertEquals("http://localhost/?foo=bar", filter.calculateCurrentUri(request)); } @@ -31,9 +30,7 @@ public void testCurrentUriRemovingCode() throws Exception { public void testCurrentUriRemovingCodeInSecond() throws Exception { OAuth2ClientContextFilter filter = new OAuth2ClientContextFilter(); MockHttpServletRequest request = new MockHttpServletRequest(); - request.addParameter("foo", "bar"); - request.addParameter("code", "XXXX"); + request.setQueryString("foo=bar&code=XXXX"); assertEquals("http://localhost/?foo=bar", filter.calculateCurrentUri(request)); } - } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/TestResourceServerBeanDefinitionParser.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/TestResourceServerBeanDefinitionParser.java index b0a7d6d80..330766b2c 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/TestResourceServerBeanDefinitionParser.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/TestResourceServerBeanDefinitionParser.java @@ -28,6 +28,7 @@ public void testDefaults() { GenericXmlApplicationContext context = new GenericXmlApplicationContext(getClass(), getClass().getSimpleName()+"-context.xml"); // System.err.println(Arrays.asList(context.getBeanDefinitionNames())); assertTrue(context.containsBeanDefinition("oauth2ProviderFilter")); + assertTrue(context.containsBeanDefinition("anotherProviderFilter")); + assertTrue(context.containsBeanDefinition("thirdProviderFilter")); } - -} +} \ No newline at end of file diff --git a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/TestResourceServerBeanDefinitionParser-context.xml b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/TestResourceServerBeanDefinitionParser-context.xml index cef710285..4c6aca764 100644 --- a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/TestResourceServerBeanDefinitionParser-context.xml +++ b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/TestResourceServerBeanDefinitionParser-context.xml @@ -14,17 +14,19 @@ - + + + + + - - + \ No newline at end of file From 2e1eb036261ede6d29ff33c0ee2fa24e6bca9ca6 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 24 Dec 2012 08:39:26 +0000 Subject: [PATCH 010/831] SECOAUTH-318: Add denyAll() catch all to token admin endpoints --- .../oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml | 1 + .../oauth2/provider/TestResourceOwnerPasswordProvider.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml index 6ce98cae4..66f21088f 100644 --- a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml +++ b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml @@ -34,6 +34,7 @@ method="GET" /> + diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestResourceOwnerPasswordProvider.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestResourceOwnerPasswordProvider.java index be0cffb96..76caad8bb 100644 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestResourceOwnerPasswordProvider.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestResourceOwnerPasswordProvider.java @@ -132,7 +132,7 @@ public void testTokenNotGrantedIfSecretNotProvided() throws Exception { assertEquals(HttpStatus.UNAUTHORIZED, e.getStatusCode()); List values = tokenEndpointResponse.getHeaders().get("WWW-Authenticate"); assertEquals(1, values.size()); - assertEquals("Basic realm=\"sparklr2/client\"", values.get(0)); + assertTrue(values.get(0).contains("Basic realm=\"sparklr2/client\"")); } } From 19ed2323467bcea6d89366de0075d256af93b8f5 Mon Sep 17 00:00:00 2001 From: Alex Rau Date: Mon, 24 Dec 2012 18:36:16 +0100 Subject: [PATCH 011/831] SECOAUTH-142: make session peristed tokens optional --- .../HttpSessionOAuthRememberMeServices.java | 63 +++++--- ...estHttpSessionOAuthRememberMeServices.java | 136 ++++++++++++++++++ 2 files changed, 179 insertions(+), 20 deletions(-) create mode 100644 spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/rememberme/TestHttpSessionOAuthRememberMeServices.java diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/rememberme/HttpSessionOAuthRememberMeServices.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/rememberme/HttpSessionOAuthRememberMeServices.java index ddf698688..bc218993d 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/rememberme/HttpSessionOAuthRememberMeServices.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/rememberme/HttpSessionOAuthRememberMeServices.java @@ -1,34 +1,57 @@ package org.springframework.security.oauth.consumer.rememberme; -import org.springframework.security.oauth.consumer.OAuthConsumerToken; +import java.util.HashMap; +import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; -import java.util.Map; + +import org.springframework.security.oauth.consumer.OAuthConsumerToken; /** - * Default implementation of the OAuth2 rememberme services. Just stores everything in the session. + * Default implementation of the OAuth2 rememberme services. Just stores everything in the session by default. Storing + * access token can be suppressed to reduce long-term expose of these tokens in the underlying HTTP session. * * @author Ryan Heaton + * @author Alex Rau */ public class HttpSessionOAuthRememberMeServices implements OAuthRememberMeServices { - public static final String REMEMBERED_TOKENS_KEY = HttpSessionOAuthRememberMeServices.class.getName() + "#REMEMBERED_TOKENS"; - - public Map loadRememberedTokens(HttpServletRequest request, HttpServletResponse response) { - HttpSession session = request.getSession(false); - Map rememberedTokens = null; - if (session != null) { - rememberedTokens = (Map) session.getAttribute(REMEMBERED_TOKENS_KEY); - } - return rememberedTokens; - } - - public void rememberTokens(Map tokens, HttpServletRequest request, HttpServletResponse response) { - HttpSession session = request.getSession(false); - if (session != null) { - session.setAttribute(REMEMBERED_TOKENS_KEY, tokens); - } - } + public static final String REMEMBERED_TOKENS_KEY = HttpSessionOAuthRememberMeServices.class.getName() + + "#REMEMBERED_TOKENS"; + + private boolean storeAccessTokens = true; + + @SuppressWarnings("unchecked") + public Map loadRememberedTokens(HttpServletRequest request, HttpServletResponse response) { + + HttpSession session = request.getSession(false); + + if (session != null) { + return (Map) session.getAttribute(REMEMBERED_TOKENS_KEY); + } + + return null; + } + + public void rememberTokens(Map tokens, HttpServletRequest request, + HttpServletResponse response) { + + HttpSession session = request.getSession(false); + + if (session == null) { + return; + } + + Map requestTokensOnly = new HashMap(); + + for (Map.Entry token : tokens.entrySet()) { + if (storeAccessTokens && !token.getValue().isAccessToken()) + requestTokensOnly.put(token.getKey(), token.getValue()); + + } + + session.setAttribute(REMEMBERED_TOKENS_KEY, requestTokensOnly); + } } diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/rememberme/TestHttpSessionOAuthRememberMeServices.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/rememberme/TestHttpSessionOAuthRememberMeServices.java new file mode 100644 index 000000000..e4290a1d3 --- /dev/null +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/rememberme/TestHttpSessionOAuthRememberMeServices.java @@ -0,0 +1,136 @@ +/* + * Copyright 2008 Web Cohesion + * + * 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.oauth.consumer.rememberme; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.mock.web.MockHttpSession; +import org.springframework.security.oauth.consumer.OAuthConsumerToken; + +/** + * @author Alex Rau + */ +public class TestHttpSessionOAuthRememberMeServices { + + @Test + public void testEmptySession() { + + MockHttpSession mockHttpSession = new MockHttpSession(); + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + + request.setSession(mockHttpSession); + + HttpSessionOAuthRememberMeServices oAuthRememberMeService = new HttpSessionOAuthRememberMeServices(); + + Map tokens = oAuthRememberMeService.loadRememberedTokens(request, response); + + Assert.assertNull(tokens); + + } + + @Test + public void testNoTokensRemembered() { + + MockHttpSession mockHttpSession = new MockHttpSession(); + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + + request.setSession(mockHttpSession); + + HttpSessionOAuthRememberMeServices oAuthRememberMeService = new HttpSessionOAuthRememberMeServices(); + + Map tokens = new HashMap(); + + oAuthRememberMeService.rememberTokens(tokens, request, response); + + Assert.assertEquals(0, oAuthRememberMeService.loadRememberedTokens(request, response).size()); + + } + + @Test + public void testStoreEverything() { + + MockHttpSession mockHttpSession = new MockHttpSession(); + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + + request.setSession(mockHttpSession); + + HttpSessionOAuthRememberMeServices oAuthRememberMeService = new HttpSessionOAuthRememberMeServices(); + + Map tokens = new HashMap(); + + { + OAuthConsumerToken token = new OAuthConsumerToken(); + token.setAccessToken(false); + tokens.put("resourceID1", token); + } + + { + OAuthConsumerToken token = new OAuthConsumerToken(); + token.setAccessToken(true); + tokens.put("resourceID2", token); + } + + oAuthRememberMeService.rememberTokens(tokens, request, response); + + Assert.assertEquals(1, oAuthRememberMeService.loadRememberedTokens(request, response).size()); + + } + + @Test + public void testStoreRequestTokensOnly() { + + MockHttpSession mockHttpSession = new MockHttpSession(); + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + + request.setSession(mockHttpSession); + + HttpSessionOAuthRememberMeServices oAuthRememberMeService = new HttpSessionOAuthRememberMeServices(); + + Map tokens = new HashMap(); + + { + OAuthConsumerToken token = new OAuthConsumerToken(); + token.setAccessToken(false); + tokens.put("resourceID1", token); + } + + { + OAuthConsumerToken token = new OAuthConsumerToken(); + token.setAccessToken(true); + tokens.put("resourceID2", token); + } + + oAuthRememberMeService.rememberTokens(tokens, request, response); + + Map storedTokens = oAuthRememberMeService.loadRememberedTokens(request, response); + + Assert.assertEquals(1, storedTokens.size()); + + Assert.assertNotNull(storedTokens.get("resourceID1")); + + } + +} From 11a214ebc567c242a49ccfb4aea6faf80969e903 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 10 Jan 2013 16:31:32 +0000 Subject: [PATCH 012/831] SECOAUTH-383: fix iterator logic for multi-valued parameters --- .travis.yml | 5 ++ .../client/CoreOAuthConsumerSupport.java | 9 +-- .../client/TestCoreOAuthConsumerSupport.java | 56 ++++++++++++++++--- 3 files changed, 58 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index dff5f3a5d..53ebd0ee7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1 +1,6 @@ language: java + +install: mvn -U install --quiet -DskipTests=true -P bootstrap +script: mvn clean test -P bootstrap + + diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/client/CoreOAuthConsumerSupport.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/client/CoreOAuthConsumerSupport.java index 3852a8203..36ab3b822 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/client/CoreOAuthConsumerSupport.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/client/CoreOAuthConsumerSupport.java @@ -647,16 +647,17 @@ protected String getSignatureBaseString(Map> oauthPara Iterator>> sortedIt = sortedParameters.entrySet().iterator(); while (sortedIt.hasNext()) { Map.Entry> sortedParameter = sortedIt.next(); - for (String parameterValue : sortedParameter.getValue()) { - if (parameterValue == null) { + for (Iterator sortedParametersIterator = sortedParameter.getValue().iterator(); sortedParametersIterator.hasNext();) { + String parameterValue = sortedParametersIterator.next(); + if (parameterValue == null) { parameterValue = ""; } queryString.append(sortedParameter.getKey()).append('=').append(parameterValue); - if (sortedIt.hasNext()) { + if (sortedIt.hasNext() || sortedParametersIterator.hasNext()) { queryString.append('&'); } - } + } } StringBuilder url = new StringBuilder(requestURL.getProtocol().toLowerCase()).append("://").append(requestURL.getHost().toLowerCase()); diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/client/TestCoreOAuthConsumerSupport.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/client/TestCoreOAuthConsumerSupport.java index 8a2fddd6e..05e898f6f 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/client/TestCoreOAuthConsumerSupport.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/client/TestCoreOAuthConsumerSupport.java @@ -38,8 +38,10 @@ import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import java.util.TreeMap; @@ -79,7 +81,8 @@ public void testAfterPropertiesSet() throws Exception { try { new CoreOAuthConsumerSupport().afterPropertiesSet(); fail("should required a protected resource details service."); - } catch (IllegalArgumentException e) { + } + catch (IllegalArgumentException e) { } } @@ -146,7 +149,8 @@ public URL configureURLForProtectedAccess(URL url, OAuthConsumerToken accessToke try { return new URL(url.getProtocol(), url.getHost(), url.getPort(), url.getFile(), new StreamHandlerForTestingPurposes(connectionMock)); - } catch (MalformedURLException e) { + } + catch (MalformedURLException e) { throw new RuntimeException(e); } } @@ -165,7 +169,8 @@ public String getOAuthQueryString(ProtectedResourceDetails details, OAuthConsume try { support.readResource(details, url, "POST", token, null, null); fail("shouldn't have been a valid response code."); - } catch (OAuthRequestFailedException e) { + } + catch (OAuthRequestFailedException e) { // fall through... } assertFalse(connectionProps.doOutput); @@ -181,7 +186,8 @@ public String getOAuthQueryString(ProtectedResourceDetails details, OAuthConsume try { support.readResource(details, url, "POST", token, null, null); fail("shouldn't have been a valid response code."); - } catch (OAuthRequestFailedException e) { + } + catch (OAuthRequestFailedException e) { // fall through... } assertFalse(connectionProps.doOutput); @@ -198,7 +204,8 @@ public String getOAuthQueryString(ProtectedResourceDetails details, OAuthConsume try { support.readResource(details, url, "POST", token, null, null); fail("shouldn't have been a valid response code."); - } catch (InvalidOAuthRealmException e) { + } + catch (InvalidOAuthRealmException e) { // fall through... } assertFalse(connectionProps.doOutput); @@ -400,8 +407,8 @@ protected String getSignatureBaseString(Map> oauthPara when(details.getSignatureMethod()).thenReturn(HMAC_SHA1SignatureMethod.SIGNATURE_NAME); SharedConsumerSecret secret = new SharedConsumerSecretImpl("shh!!!"); when(details.getSharedSecret()).thenReturn(secret); - when(sigFactory.getSignatureMethod(HMAC_SHA1SignatureMethod.SIGNATURE_NAME, secret, null)).thenReturn( - sigMethod); + when(sigFactory.getSignatureMethod(HMAC_SHA1SignatureMethod.SIGNATURE_NAME, secret, null)) + .thenReturn(sigMethod); when(sigMethod.sign("MYSIGBASESTRING")).thenReturn("MYSIGNATURE"); Map> params = support.loadOAuthParameters(details, url, token, "POST", null); @@ -446,6 +453,33 @@ public void testGetSignatureBaseString() throws Exception { baseString); } + @Test + public void testGetSignatureBaseStringSimple() throws Exception { + Map> oauthParams = new HashMap>(); + oauthParams.put("foo", Collections.singleton((CharSequence) "bar")); + oauthParams.put("bar", new LinkedHashSet(Arrays. asList("120", "24"))); + + CoreOAuthConsumerSupport support = new CoreOAuthConsumerSupport(); + + String baseString = support.getSignatureBaseString(oauthParams, new URL("http://photos.example.net/photos"), + "get"); + assertEquals("GET&http%3A%2F%2Fphotos.example.net%2Fphotos&bar%3D120%26bar%3D24%26foo%3Dbar", baseString); + } + + // See SECOAUTH-383 + @Test + public void testGetSignatureBaseStringMultivaluedLast() throws Exception { + Map> oauthParams = new HashMap>(); + oauthParams.put("foo", Collections.singleton((CharSequence) "bar")); + oauthParams.put("pin", new LinkedHashSet(Arrays. asList("2", "1"))); + + CoreOAuthConsumerSupport support = new CoreOAuthConsumerSupport(); + + String baseString = support.getSignatureBaseString(oauthParams, new URL("http://photos.example.net/photos"), + "get"); + assertEquals("GET&http%3A%2F%2Fphotos.example.net%2Fphotos&foo%3Dbar%26pin%3D1%26pin%3D2", baseString); + } + static class StreamHandlerForTestingPurposes extends Handler { private final HttpURLConnectionForTestingPurposes connection; @@ -469,7 +503,7 @@ static class HttpURLConnectionForTestingPurposes extends HttpURLConnection { /** * Constructor for the HttpURLConnection. - * + * * @param u the URL */ public HttpURLConnectionForTestingPurposes(URL u) { @@ -490,11 +524,17 @@ public void connect() throws IOException { static class ConnectionProps { public int responseCode; + public String responseMessage; + public String method; + public Boolean doOutput; + public Boolean connected; + public OutputStream outputStream; + public final Map headerFields = new TreeMap(); public void reset() { From cc3d28c134e8e839a8f181b804857eebec521a63 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 10 Jan 2013 17:08:08 +0000 Subject: [PATCH 013/831] [maven-release-plugin] prepare release 1.0.1.RELEASE --- pom.xml | 4 ++-- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index 67c09375a..a47722598 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ OAuth for Spring Security Parent Project for OAuth Support for Spring Security pom - 1.0.1.BUILD-SNAPSHOT + 1.0.1.RELEASE http://static.springframework.org/spring-security/oauth @@ -26,7 +26,7 @@ http://github.com/SpringSource/spring-security-oauth scm:git:git://github.com/SpringSource/spring-security-oauth.git scm:git:ssh://git@github.com/SpringSource/spring-security-oauth.git - HEAD + 1.0.1.RELEASE JIRA diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index 854d11474..7769005c9 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 - 1.0.1.BUILD-SNAPSHOT + 1.0.1.RELEASE ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index 7bf73de03..9ae4c5050 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 - 1.0.1.BUILD-SNAPSHOT + 1.0.1.RELEASE ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index c371ea3fc..82bf80bfe 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 - 1.0.1.BUILD-SNAPSHOT + 1.0.1.RELEASE ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 63c7ff191..8b3c4f3b9 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 1.0.1.BUILD-SNAPSHOT + 1.0.1.RELEASE ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index dc727a154..d7aebdaeb 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 1.0.1.BUILD-SNAPSHOT + 1.0.1.RELEASE spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index 99e45724b..2b108e7c9 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 - 1.0.1.BUILD-SNAPSHOT + 1.0.1.RELEASE spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index ceda1ae6a..eb502df1a 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 - 1.0.1.BUILD-SNAPSHOT + 1.0.1.RELEASE spring-security-oauth2 From b93364a3a5cd64115b7b96dd53616c986c09b87f Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 11 Jan 2013 10:12:59 +0000 Subject: [PATCH 014/831] Add javadocs for central release --- pom.xml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pom.xml b/pom.xml index a47722598..0af571d21 100644 --- a/pom.xml +++ b/pom.xml @@ -187,6 +187,18 @@ + + maven-javadoc-plugin + + + javadoc + package + + jar + + + + org.codehaus.mojo animal-sniffer-maven-plugin From f50bf5cfddce29853cffdcc901b3fffeaa24290a Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 10 Jan 2013 17:08:08 +0000 Subject: [PATCH 015/831] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index 0af571d21..1f89c7fff 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ OAuth for Spring Security Parent Project for OAuth Support for Spring Security pom - 1.0.1.RELEASE + 1.0.2.BUILD-SNAPSHOT http://static.springframework.org/spring-security/oauth @@ -26,7 +26,7 @@ http://github.com/SpringSource/spring-security-oauth scm:git:git://github.com/SpringSource/spring-security-oauth.git scm:git:ssh://git@github.com/SpringSource/spring-security-oauth.git - 1.0.1.RELEASE + HEAD JIRA diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index 7769005c9..59c921274 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 - 1.0.1.RELEASE + 1.0.2.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index 9ae4c5050..e4f21725d 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 - 1.0.1.RELEASE + 1.0.2.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 82bf80bfe..6c0a7c7db 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 - 1.0.1.RELEASE + 1.0.2.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 8b3c4f3b9..65f4e7604 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 1.0.1.RELEASE + 1.0.2.BUILD-SNAPSHOT ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index d7aebdaeb..659208f5f 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 1.0.1.RELEASE + 1.0.2.BUILD-SNAPSHOT spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index 2b108e7c9..36be444ac 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 - 1.0.1.RELEASE + 1.0.2.BUILD-SNAPSHOT spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index eb502df1a..f0877d494 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 - 1.0.1.RELEASE + 1.0.2.BUILD-SNAPSHOT spring-security-oauth2 From 59a6eae63b952063c62a5cb8427b23031f3c9f49 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 14 Jan 2013 09:33:26 +0000 Subject: [PATCH 016/831] SECOAUTH-385: fix broken URI query string parsing --- .../client/filter/OAuth2ClientContextFilter.java | 13 ++++--------- .../filter/TestOAuth2ClientContextFilter.java | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilter.java index 2f552154c..5f80b2361 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilter.java @@ -18,13 +18,12 @@ import org.springframework.security.oauth2.client.resource.UserRedirectRequiredException; import org.springframework.security.oauth2.common.DefaultThrowableAnalyzer; import org.springframework.security.web.DefaultRedirectStrategy; -import org.springframework.security.web.PortResolver; -import org.springframework.security.web.PortResolverImpl; import org.springframework.security.web.RedirectStrategy; import org.springframework.security.web.util.ThrowableAnalyzer; import org.springframework.util.Assert; import org.springframework.web.servlet.support.ServletUriComponentsBuilder; import org.springframework.web.util.NestedServletException; +import org.springframework.web.util.UriComponents; /** * Security filter for an OAuth2 client. @@ -40,8 +39,6 @@ public class OAuth2ClientContextFilter implements Filter, InitializingBean { */ public static final String CURRENT_URI = "currentUri"; - private PortResolver portResolver = new PortResolverImpl(); - private ThrowableAnalyzer throwableAnalyzer = new DefaultThrowableAnalyzer(); private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); @@ -123,7 +120,9 @@ protected void redirectUser(UserRedirectRequiredException e, HttpServletRequest * @return The current uri. */ protected String calculateCurrentUri(HttpServletRequest request) throws UnsupportedEncodingException { - return ServletUriComponentsBuilder.fromRequest(request).replaceQueryParam("code").build(true).toUriString(); + UriComponents uri = ServletUriComponentsBuilder.fromRequest(request).replaceQuery(request.getQueryString().replace("+", "%20")).replaceQueryParam("code").build(true); + String query = uri.getQuery().replace("%20", "+"); + return ServletUriComponentsBuilder.fromUri(uri.toUri()).replaceQuery(query).build().toString(); } public void init(FilterConfig filterConfig) throws ServletException { @@ -136,10 +135,6 @@ public void setThrowableAnalyzer(ThrowableAnalyzer throwableAnalyzer) { this.throwableAnalyzer = throwableAnalyzer; } - public void setPortResolver(PortResolver portResolver) { - this.portResolver = portResolver; - } - public void setRedirectStrategy(RedirectStrategy redirectStrategy) { this.redirectStrategy = redirectStrategy; } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/TestOAuth2ClientContextFilter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/TestOAuth2ClientContextFilter.java index 1e257513b..8d1f00287 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/TestOAuth2ClientContextFilter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/TestOAuth2ClientContextFilter.java @@ -18,6 +18,22 @@ public void testVanillaCurrentUri() throws Exception { assertEquals("http://localhost/?foo=bar", filter.calculateCurrentUri(request)); } + @Test + public void testCurrentUriWithLegalSpaces() throws Exception { + OAuth2ClientContextFilter filter = new OAuth2ClientContextFilter(); + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setQueryString("foo=bar%20spam"); + assertEquals("http://localhost/?foo=bar+spam", filter.calculateCurrentUri(request)); + } + + @Test + public void testCurrentUriWithIllegalSpaces() throws Exception { + OAuth2ClientContextFilter filter = new OAuth2ClientContextFilter(); + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setQueryString("foo=bar+spam"); + assertEquals("http://localhost/?foo=bar+spam", filter.calculateCurrentUri(request)); + } + @Test public void testCurrentUriRemovingCode() throws Exception { OAuth2ClientContextFilter filter = new OAuth2ClientContextFilter(); From 617675708b5ddac0b76f78eaaeec677990099190 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 14 Jan 2013 09:33:26 +0000 Subject: [PATCH 017/831] SECOAUTH-385: add null check for safety --- .../client/filter/OAuth2ClientContextFilter.java | 14 ++++++++++++-- .../filter/TestOAuth2ClientContextFilter.java | 9 ++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilter.java index 5f80b2361..079a62b8d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilter.java @@ -120,8 +120,18 @@ protected void redirectUser(UserRedirectRequiredException e, HttpServletRequest * @return The current uri. */ protected String calculateCurrentUri(HttpServletRequest request) throws UnsupportedEncodingException { - UriComponents uri = ServletUriComponentsBuilder.fromRequest(request).replaceQuery(request.getQueryString().replace("+", "%20")).replaceQueryParam("code").build(true); - String query = uri.getQuery().replace("%20", "+"); + ServletUriComponentsBuilder builder = ServletUriComponentsBuilder.fromRequest(request); + // Now work around SPR-10172... + String queryString = request.getQueryString(); + boolean legalSpaces = queryString != null && queryString.contains("+"); + if (legalSpaces) { + builder.replaceQuery(queryString.replace("+", "%20")); + } + UriComponents uri = builder.replaceQueryParam("code").build(true); + String query = uri.getQuery(); + if (legalSpaces) { + query = query.replace("%20", "+"); + } return ServletUriComponentsBuilder.fromUri(uri.toUri()).replaceQuery(query).build().toString(); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/TestOAuth2ClientContextFilter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/TestOAuth2ClientContextFilter.java index 8d1f00287..c17505639 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/TestOAuth2ClientContextFilter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/TestOAuth2ClientContextFilter.java @@ -23,7 +23,14 @@ public void testCurrentUriWithLegalSpaces() throws Exception { OAuth2ClientContextFilter filter = new OAuth2ClientContextFilter(); MockHttpServletRequest request = new MockHttpServletRequest(); request.setQueryString("foo=bar%20spam"); - assertEquals("http://localhost/?foo=bar+spam", filter.calculateCurrentUri(request)); + assertEquals("http://localhost/?foo=bar%20spam", filter.calculateCurrentUri(request)); + } + + @Test + public void testCurrentUriWithNoQuery() throws Exception { + OAuth2ClientContextFilter filter = new OAuth2ClientContextFilter(); + MockHttpServletRequest request = new MockHttpServletRequest(); + assertEquals("http://localhost/", filter.calculateCurrentUri(request)); } @Test From 41be0b69c97a9cd6929e01a4f1afdb72678ae99b Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 31 Jan 2013 07:19:34 -0500 Subject: [PATCH 018/831] SECOAUTH-388: apply ClientCredentialsTokenEndpointFilter only if not already authenticated --- .../src/main/webapp/WEB-INF/spring-servlet.xml | 2 +- .../ClientCredentialsTokenEndpointFilter.java | 15 +++++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml index 66f21088f..83e2b0d4c 100644 --- a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml +++ b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml @@ -17,7 +17,7 @@ - + diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenEndpointFilter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenEndpointFilter.java index 95f114876..ffe1955bc 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenEndpointFilter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenEndpointFilter.java @@ -23,6 +23,7 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.oauth2.common.exceptions.BadClientCredentialsException; import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint; import org.springframework.security.web.AuthenticationEntryPoint; @@ -40,17 +41,17 @@ * */ public class ClientCredentialsTokenEndpointFilter extends AbstractAuthenticationProcessingFilter { - + private AuthenticationEntryPoint authenticationEntryPoint = new OAuth2AuthenticationEntryPoint(); public ClientCredentialsTokenEndpointFilter() { this("/oauth/token"); } - + public ClientCredentialsTokenEndpointFilter(String path) { super(path); } - + /** * @param authenticationEntryPoint the authentication entry point to set */ @@ -85,8 +86,14 @@ public Authentication attemptAuthentication(HttpServletRequest request, HttpServ String clientId = request.getParameter("client_id"); String clientSecret = request.getParameter("client_secret"); + // If the request is already authenticated we can assume that this filter is not needed + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + if (authentication != null && authentication.isAuthenticated()) { + return authentication; + } + if (clientId == null) { - return null; + throw new BadCredentialsException("No client credentials presented"); } if (clientSecret == null) { From bd402e78d1736a74902152bdeab0db3a7a934f9e Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Sat, 9 Feb 2013 14:47:56 +0000 Subject: [PATCH 019/831] Allow whitespace padding in private keys --- .../jwt/crypto/sign/RsaKeyHelper.java | 2 +- .../jwt/crypto/cipher/RsaTestKeyData.java | 104 +++++++++++------- .../jwt/crypto/sign/RsaSigningTests.java | 9 ++ 3 files changed, 75 insertions(+), 40 deletions(-) diff --git a/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/RsaKeyHelper.java b/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/RsaKeyHelper.java index 1c03ba397..84a35771d 100644 --- a/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/RsaKeyHelper.java +++ b/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/RsaKeyHelper.java @@ -43,7 +43,7 @@ class RsaKeyHelper { private static Pattern PEM_DATA = Pattern.compile("-----BEGIN (.*)-----(.*)-----END (.*)-----", Pattern.DOTALL); static KeyPair parseKeyPair(String pemData) { - Matcher m = PEM_DATA.matcher(pemData); + Matcher m = PEM_DATA.matcher(pemData.trim()); if (!m.matches()) { throw new IllegalArgumentException("String is not PEM encoded data"); diff --git a/spring-security-jwt/src/test/java/org/springframework/security/jwt/crypto/cipher/RsaTestKeyData.java b/spring-security-jwt/src/test/java/org/springframework/security/jwt/crypto/cipher/RsaTestKeyData.java index cd46dc505..be567fadc 100644 --- a/spring-security-jwt/src/test/java/org/springframework/security/jwt/crypto/cipher/RsaTestKeyData.java +++ b/spring-security-jwt/src/test/java/org/springframework/security/jwt/crypto/cipher/RsaTestKeyData.java @@ -19,56 +19,82 @@ */ public class RsaTestKeyData { static final byte[] nBytes; + static final byte[] dBytes; static { - int[] nInts = new int[] {161, 248, 22, 10, 226, 227, 201, 180, 101, 206, 141, 45, 101, 98, 99, 54, 43, 146, 125, 190, 41, 225, 240, 36, 119, 252, 22, 37, 204, 144, 161, 54, 227, 139, 217, 52, 151, 197, 182, 234, 99, 221, 119, 17, 230, 124, 116, 41, 249, 86, 176, 251, 138, 143, 8, 154, 220, 75, 105, 137, 60, 193, 51, 63, 83, 237, 208, 25, 184, 119, 132, 37, 47, 236, 145, 79, 228, 133, 119, 105, 89, 75, 234, 66, 128, 211, 44, 15, 85, 191, 98, 148, 79, 19, 3, 150, 188, 110, 155, 223, 110, 189, 210, 189, 163, 103, 142, 236, 160, 198, 104, 247, 1, 179, 141, 191, 251, 56, 200, 52, 44, 226, 254, 109, 39, 250, 222, 74, 90, 72, 116, 151, 157, 212, 185, 207, 154, 222, 196, 199, 91, 5, 133, 44, 44, 15, 94, 248, 165, 193, 117, 3, 146, 249, 68, 232, 237, 100, 193, 16, 198, 182, 71, 96, 154, 164, 120, 58, 235, 156, 108, 154, 215, 85, 49, 48, 80, 99, 139, 131, 102, 92, 111, 111, 122, 130, 163, 150, 112, 42, 31, 100, 27, 130, 211, 235, 242, 57, 34, 25, 73, 31, 182, 134, 135, 44, 87, 22, 245, 10, 248, 53, 141, 154, 139, 157, 23, 195, 64, 114, 143, 127, 135, 216, 154, 24, 216, 252, 171, 103, 173, 132, 89, 12, 46, 207, 117, 147, 57, 54, 60, 7, 3, 77, 111, 96, 111, 158, 33, 224, 84, 86, 202, 229, 233, 161}; - int[] dInts = new int[] {18, 174, 113, 164, 105, 205, 10, 43, 195, 126, 82, 108, 69, 0, 87, 31, 29, 97, 117, 29, 100, 233, 73, 112, 123, 98, 89, 15, 157, 11, 165, 124, 150, 60, 64, 30, 63, 207, 47, 44, 211, 189, 236, 136, 229, 3, 191, 198, 67, 155, 11, 40, 200, 47, 125, 55, 151, 103, 31, 82, 19, 238, 216, 193, 90, 37, 216, 213, 206, 160, 2, 94, 227, 171, 46, 139, 127, 121, 33, 111, 198, 59, 234, 86, 39, 83, 180, 6, 68, 198, 161, 81, 39, 217, 178, 149, 69, 64, 160, 187, 225, 163, 5, 86, 152, 45, 78, 159, 222, 95, 100, 37, 241, 77, 75, 113, 52, 65, 181, 93, 199, 59, 155, 74, 237, 204, 146, 172, 227, 146, 126, 55, 245, 125, 12, 253, 94, 117, 129, 250, 81, 44, 143, 73, 97, 169, 235, 11, 128, 248, 168, 7, 70, 114, 138, 85, 255, 70, 71, 31, 52, 37, 6, 59, 157, 83, 100, 47, 94, 222, 30, 132, 214, 19, 8, 26, 250, 92, 34, 208, 81, 40, 91, 214, 59, 148, 59, 86, 93, 137, 138, 5, 104, 84, 19, 229, 60, 60, 108, 101, 37, 255, 31, 227, 78, 61, 220, 112, 240, 213, 100, 80, 253, 164, 139, 161, 46, 16, 78, 157, 235, 159, 184, 24, 129, 225, 196, 189, 242, 93, 146, 71, 244, 80, 200, 101, 146, 121, 104, 231, 115, 52, 244, 65, 79, 117, 167, 80, 225, 57, 84, 110, 58, 138, 115, 157}; + int[] nInts = new int[] { 161, 248, 22, 10, 226, 227, 201, 180, 101, 206, 141, 45, 101, 98, 99, 54, 43, 146, + 125, 190, 41, 225, 240, 36, 119, 252, 22, 37, 204, 144, 161, 54, 227, 139, 217, 52, 151, 197, 182, 234, + 99, 221, 119, 17, 230, 124, 116, 41, 249, 86, 176, 251, 138, 143, 8, 154, 220, 75, 105, 137, 60, 193, + 51, 63, 83, 237, 208, 25, 184, 119, 132, 37, 47, 236, 145, 79, 228, 133, 119, 105, 89, 75, 234, 66, + 128, 211, 44, 15, 85, 191, 98, 148, 79, 19, 3, 150, 188, 110, 155, 223, 110, 189, 210, 189, 163, 103, + 142, 236, 160, 198, 104, 247, 1, 179, 141, 191, 251, 56, 200, 52, 44, 226, 254, 109, 39, 250, 222, 74, + 90, 72, 116, 151, 157, 212, 185, 207, 154, 222, 196, 199, 91, 5, 133, 44, 44, 15, 94, 248, 165, 193, + 117, 3, 146, 249, 68, 232, 237, 100, 193, 16, 198, 182, 71, 96, 154, 164, 120, 58, 235, 156, 108, 154, + 215, 85, 49, 48, 80, 99, 139, 131, 102, 92, 111, 111, 122, 130, 163, 150, 112, 42, 31, 100, 27, 130, + 211, 235, 242, 57, 34, 25, 73, 31, 182, 134, 135, 44, 87, 22, 245, 10, 248, 53, 141, 154, 139, 157, 23, + 195, 64, 114, 143, 127, 135, 216, 154, 24, 216, 252, 171, 103, 173, 132, 89, 12, 46, 207, 117, 147, 57, + 54, 60, 7, 3, 77, 111, 96, 111, 158, 33, 224, 84, 86, 202, 229, 233, 161 }; + int[] dInts = new int[] { 18, 174, 113, 164, 105, 205, 10, 43, 195, 126, 82, 108, 69, 0, 87, 31, 29, 97, 117, + 29, 100, 233, 73, 112, 123, 98, 89, 15, 157, 11, 165, 124, 150, 60, 64, 30, 63, 207, 47, 44, 211, 189, + 236, 136, 229, 3, 191, 198, 67, 155, 11, 40, 200, 47, 125, 55, 151, 103, 31, 82, 19, 238, 216, 193, 90, + 37, 216, 213, 206, 160, 2, 94, 227, 171, 46, 139, 127, 121, 33, 111, 198, 59, 234, 86, 39, 83, 180, 6, + 68, 198, 161, 81, 39, 217, 178, 149, 69, 64, 160, 187, 225, 163, 5, 86, 152, 45, 78, 159, 222, 95, 100, + 37, 241, 77, 75, 113, 52, 65, 181, 93, 199, 59, 155, 74, 237, 204, 146, 172, 227, 146, 126, 55, 245, + 125, 12, 253, 94, 117, 129, 250, 81, 44, 143, 73, 97, 169, 235, 11, 128, 248, 168, 7, 70, 114, 138, 85, + 255, 70, 71, 31, 52, 37, 6, 59, 157, 83, 100, 47, 94, 222, 30, 132, 214, 19, 8, 26, 250, 92, 34, 208, + 81, 40, 91, 214, 59, 148, 59, 86, 93, 137, 138, 5, 104, 84, 19, 229, 60, 60, 108, 101, 37, 255, 31, + 227, 78, 61, 220, 112, 240, 213, 100, 80, 253, 164, 139, 161, 46, 16, 78, 157, 235, 159, 184, 24, 129, + 225, 196, 189, 242, 93, 146, 71, 244, 80, 200, 101, 146, 121, 104, 231, 115, 52, 244, 65, 79, 117, 167, + 80, 225, 57, 84, 110, 58, 138, 115, 157 }; nBytes = new byte[nInts.length]; dBytes = new byte[dInts.length]; - for (int i=0; i < nInts.length; i++) - nBytes[i] = (byte)nInts[i]; - for (int i=0; i < dInts.length; i++) - dBytes[i] = (byte)dInts[i]; + for (int i = 0; i < nInts.length; i++) + nBytes[i] = (byte) nInts[i]; + for (int i = 0; i < dInts.length; i++) + dBytes[i] = (byte) dInts[i]; } public final static BigInteger N = new BigInteger(1, nBytes); - public final static BigInteger E = new BigInteger(1, new byte[]{1,0,1}); + + public final static BigInteger E = new BigInteger(1, new byte[] { 1, 0, 1 }); + public final static BigInteger D = new BigInteger(1, dBytes); - public final static String SSH_PRIVATE_KEY_STRING = "-----BEGIN RSA PRIVATE KEY-----\n" + - " MIIEowIBAAKCAQEAwARN4S7Z0asSEj61+SIvtUUuHopd/ffne1CbaHXNxj/cI4rY\n " + - "0k5ELZ2SGCFVgmx9XADJJhYoQImO+vMxFAqbWxyO45B1rZR1q0ChEFWLGPmNB+fY \n" + - "8TrFHIjJb873s0d2FTYDOwst6HdKPjXkLdgGHO4K1fLnO1cQHKGglBKvc4ZSVniU\n" + - "OJ1EdKZHxGnkVjps1hP98AvQx6EpmKExewd4MMj77gRYAeSo0pPhugLrmy5DLPox\n" + - " SUGSZEHCPlCfOfTAt9NuE4YwbpCwDfDmQb+9neq7Q0PwmtP6jFrV4VZ3ir2cWYOT\n" + - "F6FcL7ZIncG3aCvXxp8pUQ7NPimYd70dEPuu1QIDAQABAoIBAFbcG5a3qNTNu/kA\n" + - "4TR3oHkxeDFcijQuhkokJojUcWcy0BRL5NUNjo3L76B2w8Wh6ftKZ7OQ5lh7YXBn\n" + - " vlXAjpJiksiiOnlw5OG49KL871U23fMrj9lfqnbD8ctgJnC07NeffUqiPfwgqjcG\n" + - " DdgnFmzTyZcKsEsJkUJCYu9YnIF3AwEwOxlstdE1YXmjbXmbXlfqUynWEaZUxnAW\n" + - "/jLqHuQ9Dq9x8/i3vY+z8vzGVWY4ND8HSOMxLoQnoeA4Z0IWveaulVP0sZxbZTPo\n" + - "PvZu8yDFgdS6tCTRBw/WyzQeIcaktgoF1Mfv+YgiP7/GxiuFocyR21lykvWasvCb\n" + - "kWUadoECgYEA4Jdc2crrm30L+jgGzK7T4OMV2E1IvxloV1q3RBN8W5Gf0ba6ZtFh\n" + - "aW3008sUyZDPoQfpeq4AlwaYZDlOp7kK2Ur15qQ/w4AjnUjGAFFVE3hcBWkj0+3z\n" + - "1sQQXe87LIGG9iaTct+bhbav7cLnZKBKHJNkhgsk/XEHvub5kIvXWjECgYEA2t68\n" + - "tCUgCsU/v311Jc6HNJ5hB0FzGBEx/ic1QjQF2sicP0yCO0qPHCqHGCazzyM1P9So\n" + - "eDRE/bzWejk2v/UgaN9P/1+TeQdj9VR/9wfwlWPYtYWZZRgvHl6HIXKJFRON5Mfh\n" + - "KaaHqhY0hRS4u5e3VpA7wtUNMgRQdUgr91CW0eUCgYA6ILLVY6GrMqgg8NNBspYA\n" + - "BIYo34fOfgL1aPM52Vk8UeptWr/P0K1Hnj/ZeRw+Nw6l/Og+6j4Y2Ioklnh3DHt0\n" + - "VeRi92vRa57MHIOynVpJmcMnW1j8hv+vPDuINFy6XiPSHZXYC2uzJd9OyD0fXCUS\n" + - "VEuWLdg7CEAa9qjs8mSgYQKBgHmfgHkSkEWr6oq8apbBt3xT7lMb2ZssIv26R+ws\n" + - "AHzdMYYzO8M64V+jekK/bvfR9ssrnxp84UGm6AAvPu9YhdQBE/Ey6T4+DxvLAvkB\n" + - "Hn3FaC0mumDlGXnkyW6auPZPUXAqakK82XJ4uGKjayxDWIvvxmW0AosivpsNqfDa\n" + - "hZTJAoGBAL6qCOit9K/mHIBFcQuwBl2FbQ8TVosnim1ey1iVOkLVqoMGeNxIQooy\n" + - "croHabgtkH1IatCZyvTqgq4uCeya4kSRz0kzS86UehMr14ZXcoK+fS+JaAJrbce6\n" + - " 1iX3/15AzMUG3DOrUHpY/Ye/9MDMvBOtLNRNzthGY0rhUGP53j9D\n" + - "-----END RSA PRIVATE KEY-----"; + public final static String SSH_PRIVATE_KEY_STRING = "-----BEGIN RSA PRIVATE KEY-----\n" + + " MIIEowIBAAKCAQEAwARN4S7Z0asSEj61+SIvtUUuHopd/ffne1CbaHXNxj/cI4rY\n " + + "0k5ELZ2SGCFVgmx9XADJJhYoQImO+vMxFAqbWxyO45B1rZR1q0ChEFWLGPmNB+fY \n" + + "8TrFHIjJb873s0d2FTYDOwst6HdKPjXkLdgGHO4K1fLnO1cQHKGglBKvc4ZSVniU\n" + + "OJ1EdKZHxGnkVjps1hP98AvQx6EpmKExewd4MMj77gRYAeSo0pPhugLrmy5DLPox\n" + + " SUGSZEHCPlCfOfTAt9NuE4YwbpCwDfDmQb+9neq7Q0PwmtP6jFrV4VZ3ir2cWYOT\n" + + "F6FcL7ZIncG3aCvXxp8pUQ7NPimYd70dEPuu1QIDAQABAoIBAFbcG5a3qNTNu/kA\n" + + "4TR3oHkxeDFcijQuhkokJojUcWcy0BRL5NUNjo3L76B2w8Wh6ftKZ7OQ5lh7YXBn\n" + + " vlXAjpJiksiiOnlw5OG49KL871U23fMrj9lfqnbD8ctgJnC07NeffUqiPfwgqjcG\n" + + " DdgnFmzTyZcKsEsJkUJCYu9YnIF3AwEwOxlstdE1YXmjbXmbXlfqUynWEaZUxnAW\n" + + "/jLqHuQ9Dq9x8/i3vY+z8vzGVWY4ND8HSOMxLoQnoeA4Z0IWveaulVP0sZxbZTPo\n" + + "PvZu8yDFgdS6tCTRBw/WyzQeIcaktgoF1Mfv+YgiP7/GxiuFocyR21lykvWasvCb\n" + + "kWUadoECgYEA4Jdc2crrm30L+jgGzK7T4OMV2E1IvxloV1q3RBN8W5Gf0ba6ZtFh\n" + + "aW3008sUyZDPoQfpeq4AlwaYZDlOp7kK2Ur15qQ/w4AjnUjGAFFVE3hcBWkj0+3z\n" + + "1sQQXe87LIGG9iaTct+bhbav7cLnZKBKHJNkhgsk/XEHvub5kIvXWjECgYEA2t68\n" + + "tCUgCsU/v311Jc6HNJ5hB0FzGBEx/ic1QjQF2sicP0yCO0qPHCqHGCazzyM1P9So\n" + + "eDRE/bzWejk2v/UgaN9P/1+TeQdj9VR/9wfwlWPYtYWZZRgvHl6HIXKJFRON5Mfh\n" + + "KaaHqhY0hRS4u5e3VpA7wtUNMgRQdUgr91CW0eUCgYA6ILLVY6GrMqgg8NNBspYA\n" + + "BIYo34fOfgL1aPM52Vk8UeptWr/P0K1Hnj/ZeRw+Nw6l/Og+6j4Y2Ioklnh3DHt0\n" + + "VeRi92vRa57MHIOynVpJmcMnW1j8hv+vPDuINFy6XiPSHZXYC2uzJd9OyD0fXCUS\n" + + "VEuWLdg7CEAa9qjs8mSgYQKBgHmfgHkSkEWr6oq8apbBt3xT7lMb2ZssIv26R+ws\n" + + "AHzdMYYzO8M64V+jekK/bvfR9ssrnxp84UGm6AAvPu9YhdQBE/Ey6T4+DxvLAvkB\n" + + "Hn3FaC0mumDlGXnkyW6auPZPUXAqakK82XJ4uGKjayxDWIvvxmW0AosivpsNqfDa\n" + + "hZTJAoGBAL6qCOit9K/mHIBFcQuwBl2FbQ8TVosnim1ey1iVOkLVqoMGeNxIQooy\n" + + "croHabgtkH1IatCZyvTqgq4uCeya4kSRz0kzS86UehMr14ZXcoK+fS+JaAJrbce6\n" + + " 1iX3/15AzMUG3DOrUHpY/Ye/9MDMvBOtLNRNzthGY0rhUGP53j9D\n" + "-----END RSA PRIVATE KEY-----"; + + public final static String SSH_PRIVATE_KEY_STRING_WITH_WHITESPACE = SSH_PRIVATE_KEY_STRING + " "; - public static final String SSH_PUBLIC_KEY_STRING = "ssh-rsa " + - "AAAAB3NzaC1yc2EAAAADAQABAAABAQDABE3hLtnRqxISPrX5Ii+1RS4eil399+d7UJtodc3GP9wjitjSTkQtnZIYIVWCbH1cAMkmFi" + - "hAiY768zEUCptbHI7jkHWtlHWrQKEQVYsY+Y0H59jxOsUciMlvzvezR3YVNgM7Cy3od0o+NeQt2AYc7grV8uc7VxAcoaCUEq9zhlJW" + - "eJQ4nUR0pkfEaeRWOmzWE/3wC9DHoSmYoTF7B3gwyPvuBFgB5KjSk+G6AuubLkMs+jFJQZJkQcI+UJ859MC3024ThjBukLAN8OZBv7" + - "2d6rtDQ/Ca0/qMWtXhVneKvZxZg5MXoVwvtkidwbdoK9fGnylRDs0+KZh3vR0Q+67V blah@blah.local"; + public static final String SSH_PUBLIC_KEY_STRING = "ssh-rsa " + + "AAAAB3NzaC1yc2EAAAADAQABAAABAQDABE3hLtnRqxISPrX5Ii+1RS4eil399+d7UJtodc3GP9wjitjSTkQtnZIYIVWCbH1cAMkmFi" + + "hAiY768zEUCptbHI7jkHWtlHWrQKEQVYsY+Y0H59jxOsUciMlvzvezR3YVNgM7Cy3od0o+NeQt2AYc7grV8uc7VxAcoaCUEq9zhlJW" + + "eJQ4nUR0pkfEaeRWOmzWE/3wC9DHoSmYoTF7B3gwyPvuBFgB5KjSk+G6AuubLkMs+jFJQZJkQcI+UJ859MC3024ThjBukLAN8OZBv7" + + "2d6rtDQ/Ca0/qMWtXhVneKvZxZg5MXoVwvtkidwbdoK9fGnylRDs0+KZh3vR0Q+67V blah@blah.local"; } diff --git a/spring-security-jwt/src/test/java/org/springframework/security/jwt/crypto/sign/RsaSigningTests.java b/spring-security-jwt/src/test/java/org/springframework/security/jwt/crypto/sign/RsaSigningTests.java index 7b41c46d4..7cb7639e6 100644 --- a/spring-security-jwt/src/test/java/org/springframework/security/jwt/crypto/sign/RsaSigningTests.java +++ b/spring-security-jwt/src/test/java/org/springframework/security/jwt/crypto/sign/RsaSigningTests.java @@ -12,6 +12,8 @@ */ package org.springframework.security.jwt.crypto.sign; +import static org.junit.Assert.assertNotNull; + import org.junit.Test; import org.springframework.security.jwt.codec.Codecs; import org.springframework.security.jwt.crypto.cipher.RsaTestKeyData; @@ -24,6 +26,13 @@ public class RsaSigningTests { @Test(expected = IllegalArgumentException.class) public void rsaSignerRejectsInvalidKey() throws Exception { RsaSigner signer = new RsaSigner(RsaTestKeyData.SSH_PUBLIC_KEY_STRING); + assertNotNull(signer); + } + + @Test + public void rsaSignerValidKeyWithWhitespace() throws Exception { + RsaSigner signer = new RsaSigner(RsaTestKeyData.SSH_PRIVATE_KEY_STRING_WITH_WHITESPACE); + assertNotNull(signer); } @Test From 7c059043325d92d429be621fd47322c9f44d57dc Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 13 Feb 2013 11:09:00 +0000 Subject: [PATCH 020/831] Fix broken integration test Recent changes to the sparklr sample mean that it is using a vanilla basic auth entry point for the token endpoint. --- .../oauth2/provider/TestClientCredentialsProvider.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestClientCredentialsProvider.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestClientCredentialsProvider.java index daa0205aa..49c44a845 100644 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestClientCredentialsProvider.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestClientCredentialsProvider.java @@ -94,7 +94,7 @@ public void handleError(ClientHttpResponse response) throws IOException { } // System.err.println(responseHeaders); String header = responseHeaders.getFirst("WWW-Authenticate"); - assertTrue("Wrong header: " + header, header.contains("error=\"invalid_client\"")); + assertTrue("Wrong header: " + header, header.contains("Basic realm")); assertEquals(HttpStatus.UNAUTHORIZED, responseStatus); } @@ -122,7 +122,7 @@ public void handleError(ClientHttpResponse response) throws IOException { } // System.err.println(responseHeaders); String header = responseHeaders.getFirst("WWW-Authenticate"); - assertTrue("Wrong header: " + header, header.contains("error=\"invalid_client\"")); + assertTrue("Wrong header: " + header, header.contains("Basic realm")); assertEquals(HttpStatus.UNAUTHORIZED, responseStatus); } From 6004abc975e17fd68150e5a5c748b7490d2552a8 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 13 Feb 2013 11:06:36 +0000 Subject: [PATCH 021/831] SECOAUTH-366: add optional filter for token endpoint --- .../provider/endpoint/TokenEndpoint.java | 28 ++- .../TokenEndpointAuthenticationFilter.java | 217 ++++++++++++++++++ ...TestTokenEndpointAuthenticationFilter.java | 99 ++++++++ 3 files changed, 338 insertions(+), 6 deletions(-) create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestTokenEndpointAuthenticationFilter.java diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java index 9740480c8..0ee0bece7 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java @@ -34,6 +34,7 @@ import org.springframework.security.oauth2.common.util.OAuth2Utils; import org.springframework.security.oauth2.provider.ClientRegistrationException; import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; @@ -70,13 +71,11 @@ public ResponseEntity getAccessToken(Principal principal, "There is no client authentication. Try adding an appropriate authentication filter."); } - Authentication client = (Authentication) principal; - if (!client.isAuthenticated()) { - throw new InsufficientAuthenticationException("The client is not authenticated."); - } HashMap request = new HashMap(parameters); - String clientId = client.getName(); - request.put("client_id", clientId); + String clientId = getClientId(principal); + if (clientId != null) { + request.put("client_id", clientId); + } if (!StringUtils.hasText(grantType)) { throw new InvalidRequestException("Missing grant type"); @@ -107,6 +106,23 @@ public ResponseEntity getAccessToken(Principal principal, } + /** + * @param principal the currently authentication principal + * @return a client id if there is one in the principal + */ + protected String getClientId(Principal principal) { + Authentication client = (Authentication) principal; + if (!client.isAuthenticated()) { + throw new InsufficientAuthenticationException("The client is not authenticated."); + } + String clientId = client.getName(); + if (client instanceof OAuth2Authentication) { + // Might be a client and user combined authentication + clientId = ((OAuth2Authentication) client).getAuthorizationRequest().getClientId(); + } + return clientId; + } + @ExceptionHandler(ClientRegistrationException.class) public ResponseEntity handleClientRegistrationException(Exception e) throws Exception { logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage()); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java new file mode 100644 index 000000000..5da006d83 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java @@ -0,0 +1,217 @@ +/* + * Copyright 2012-2013 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.endpoint; + +import java.io.IOException; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.security.authentication.AuthenticationDetailsSource; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.oauth2.common.util.OAuth2Utils; +import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; + +/** + *

+ * An optional authentication filter for the {@link TokenEndpoint}. It sits downstream of another filter (usually + * {@link BasicAuthenticationFilter}) for the client, and creates an {@link OAuth2Authentication} for the Spring + * {@link SecurityContext} if the request also contains user credentials, e.g. as typically would be the case in a + * password grant. This filter is only required if the TokenEndpoint (or one of it's dependencies) needs to know about + * the authenticated user. In a vanilla password grant this isn't normally necessary because the token granter + * will also authenticate the user. + *

+ * + *

+ * If this filter is used the Spring Security context will contain an OAuth2Authentication encapsulating (as the + * authorization request) the form parameters coming into the filter and the client id from the already authenticated + * client authentication, and the authenticated user token extracted from the request and validated using the + * authentication manager. + *

+ * + * @author Dave Syer + * + */ +public class TokenEndpointAuthenticationFilter implements Filter { + + private static final Log logger = LogFactory.getLog(TokenEndpointAuthenticationFilter.class); + + private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource(); + + private AuthenticationEntryPoint authenticationEntryPoint = new OAuth2AuthenticationEntryPoint(); + + private final AuthenticationManager authenticationManager; + + /** + * @param authenticationManager an AuthenticationManager for the incoming request + */ + public TokenEndpointAuthenticationFilter(AuthenticationManager authenticationManager) { + super(); + this.authenticationManager = authenticationManager; + } + + /** + * An authentication entry point that can handle unsuccessful authentication. Defaults to an + * {@link OAuth2AuthenticationEntryPoint}. + * + * @param authenticationEntryPoint the authenticationEntryPoint to set + */ + public void setAuthenticationEntryPoint(AuthenticationEntryPoint authenticationEntryPoint) { + this.authenticationEntryPoint = authenticationEntryPoint; + } + + /** + * A source of authentication details for requests that result in authentication. + * + * @param authenticationDetailsSource the authenticationDetailsSource to set + */ + public void setAuthenticationDetailsSource( + AuthenticationDetailsSource authenticationDetailsSource) { + this.authenticationDetailsSource = authenticationDetailsSource; + } + + public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, + ServletException { + + final boolean debug = logger.isDebugEnabled(); + final HttpServletRequest request = (HttpServletRequest) req; + final HttpServletResponse response = (HttpServletResponse) res; + + try { + Authentication credentials = extractCredentials(request); + + if (credentials != null) { + + if (debug) { + logger.debug("Authentication credentials found for '" + credentials.getName() + "'"); + } + + Authentication authResult = authenticationManager.authenticate(credentials); + + if (debug) { + logger.debug("Authentication success: " + authResult.getName()); + } + + Authentication clientAuth = SecurityContextHolder.getContext().getAuthentication(); + if (clientAuth == null) { + throw new BadCredentialsException( + "No client authentication found. Remember to put a filter upstream of the TokenEndpointAuthenticationFilter."); + } + DefaultAuthorizationRequest authorizationRequest = new DefaultAuthorizationRequest( + clientAuth.getName(), getScope(request)); + authorizationRequest.setAuthorizationParameters(getSingleValueMap(request)); + if (clientAuth.isAuthenticated()) { + // Ensure the OAuth2Authentication is authenticated + authorizationRequest.setApproved(true); + } + + SecurityContextHolder.getContext().setAuthentication( + new OAuth2Authentication(authorizationRequest, authResult)); + + onSuccessfulAuthentication(request, response, authResult); + + } + + } + catch (AuthenticationException failed) { + SecurityContextHolder.clearContext(); + + if (debug) { + logger.debug("Authentication request for failed: " + failed); + } + + onUnsuccessfulAuthentication(request, response, failed); + + authenticationEntryPoint.commence(request, response, failed); + + return; + } + + chain.doFilter(request, response); + } + + private Map getSingleValueMap(HttpServletRequest request) { + Map map = new HashMap(); + @SuppressWarnings("unchecked") + Map parameters = request.getParameterMap(); + for (String key : parameters.keySet()) { + String[] values = parameters.get(key); + map.put(key, values != null && values.length > 0 ? values[0] : null); + } + return map; + } + + private Collection getScope(HttpServletRequest request) { + return OAuth2Utils.parseParameterList(request.getParameter("scope")); + } + + protected void onSuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, + Authentication authResult) throws IOException { + } + + protected void onUnsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, + AuthenticationException failed) throws IOException { + } + + /** + * If the incoming request contains user credentials in headers or parameters then extract them here into an + * Authentication token that can be validated later. This implementation only recognises password grant requests and + * extracts the username and password. + * + * @param request the incoming request, possibly with user credentials + * @return an authentication for validation (or null if there is no further authentication) + */ + protected Authentication extractCredentials(HttpServletRequest request) { + String grantType = request.getParameter("grant_type"); + if (grantType != null && grantType.equals("password")) { + UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken( + request.getParameter("username"), request.getParameter("password")); + result.setDetails(authenticationDetailsSource.buildDetails(request)); + return result; + } + return null; + } + + public void init(FilterConfig filterConfig) throws ServletException { + } + + public void destroy() { + } + +} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestTokenEndpointAuthenticationFilter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestTokenEndpointAuthenticationFilter.java new file mode 100644 index 000000000..80ec66dd4 --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestTokenEndpointAuthenticationFilter.java @@ -0,0 +1,99 @@ +/* + * Copyright 2012-2013 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.endpoint; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.springframework.mock.web.MockFilterChain; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.oauth2.provider.OAuth2Authentication; + +/** + * @author Dave Syer + * + */ +public class TestTokenEndpointAuthenticationFilter { + + private MockHttpServletRequest request = new MockHttpServletRequest(); + + private MockHttpServletResponse response = new MockHttpServletResponse(); + + private MockFilterChain chain = new MockFilterChain(); + + private AuthenticationManager authenticationManager = Mockito.mock(AuthenticationManager.class); + + @Before + public void init() { + SecurityContextHolder.clearContext(); + SecurityContextHolder.getContext().setAuthentication( + new UsernamePasswordAuthenticationToken("client", "secret", AuthorityUtils + .commaSeparatedStringToAuthorityList("ROLE_CLIENT"))); + } + + @After + public void close() { + SecurityContextHolder.clearContext(); + } + + @Test + public void testPasswordGrant() throws Exception { + request.setParameter("grant_type", "password"); + Mockito.when(authenticationManager.authenticate(Mockito. any())).thenReturn( + new UsernamePasswordAuthenticationToken("foo", "bar", AuthorityUtils + .commaSeparatedStringToAuthorityList("ROLE_USER"))); + TokenEndpointAuthenticationFilter filter = new TokenEndpointAuthenticationFilter(authenticationManager); + filter.doFilter(request, response, chain); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + assertTrue(authentication instanceof OAuth2Authentication); + assertTrue(authentication.isAuthenticated()); + } + + @Test + public void testPasswordGrantWithUnAuthenticatedClient() throws Exception { + SecurityContextHolder.getContext().setAuthentication( + new UsernamePasswordAuthenticationToken("client", "secret")); + request.setParameter("grant_type", "password"); + Mockito.when(authenticationManager.authenticate(Mockito. any())).thenReturn( + new UsernamePasswordAuthenticationToken("foo", "bar", AuthorityUtils + .commaSeparatedStringToAuthorityList("ROLE_USER"))); + TokenEndpointAuthenticationFilter filter = new TokenEndpointAuthenticationFilter(authenticationManager); + filter.doFilter(request, response, chain); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + assertTrue(authentication instanceof OAuth2Authentication); + assertFalse(authentication.isAuthenticated()); + } + + @Test + public void testNoGrantType() throws Exception { + TokenEndpointAuthenticationFilter filter = new TokenEndpointAuthenticationFilter(authenticationManager); + filter.doFilter(request, response, chain); + // Just the client + assertTrue(SecurityContextHolder.getContext().getAuthentication() instanceof UsernamePasswordAuthenticationToken); + } + +} From 0b36aefa0a3c735681f8ff555ce4c6e96aa9e8d0 Mon Sep 17 00:00:00 2001 From: Dale Olds Date: Wed, 13 Feb 2013 19:08:37 -0800 Subject: [PATCH 022/831] SECOAUTH-366: don't clobber client_id by resetting authorizationParameters --- .../oauth2/provider/DefaultAuthorizationRequest.java | 12 +++++++++--- .../endpoint/TokenEndpointAuthenticationFilter.java | 3 +-- .../provider/TestDefaultAuthorizationRequest.java | 10 ++++++++++ 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequest.java index fdc0a36f2..adc157186 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequest.java @@ -165,11 +165,17 @@ public void setAuthorities(Collection authorities) { } public void setAuthorizationParameters(Map authorizationParameters) { + String clientId = getClientId(); + Set scope = getScope(); this.authorizationParameters = authorizationParameters == null ? new HashMap() : new HashMap(authorizationParameters); - if (authorizationParameters.containsKey(SCOPE) && StringUtils.hasText(authorizationParameters.get(SCOPE))) { - String scope = authorizationParameters.get(SCOPE); - setScope(OAuth2Utils.parseParameterList(scope)); + if (!authorizationParameters.containsKey(CLIENT_ID) && clientId!=null) { + this.authorizationParameters.put(CLIENT_ID, clientId); + } + if (StringUtils.hasText(authorizationParameters.get(SCOPE))) { + setScope(OAuth2Utils.parseParameterList(authorizationParameters.get(SCOPE))); + } else { + setScope(scope); } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java index 5da006d83..8a72c178f 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java @@ -134,8 +134,7 @@ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) "No client authentication found. Remember to put a filter upstream of the TokenEndpointAuthenticationFilter."); } DefaultAuthorizationRequest authorizationRequest = new DefaultAuthorizationRequest( - clientAuth.getName(), getScope(request)); - authorizationRequest.setAuthorizationParameters(getSingleValueMap(request)); + getSingleValueMap(request), null, clientAuth.getName(), getScope(request)); if (clientAuth.isAuthenticated()) { // Ensure the OAuth2Authentication is authenticated authorizationRequest.setApproved(true); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestDefaultAuthorizationRequest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestDefaultAuthorizationRequest.java index 43c91ab3c..d6a103ccd 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestDefaultAuthorizationRequest.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestDefaultAuthorizationRequest.java @@ -21,6 +21,7 @@ import static org.junit.Assert.assertTrue; import static org.springframework.security.oauth2.provider.AuthorizationRequest.REDIRECT_URI; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -66,6 +67,15 @@ public void testScopeSetInParameters() throws Exception { assertEquals("bar foo", authorizationRequest.getAuthorizationParameters().get(AuthorizationRequest.SCOPE)); } + @Test + public void testClientIdNotOverwitten() throws Exception { + DefaultAuthorizationRequest authorizationRequest = new DefaultAuthorizationRequest("client", Arrays.asList("read")); + parameters = new HashMap(); + authorizationRequest.setAuthorizationParameters(parameters); + assertEquals("client", authorizationRequest.getClientId()); + assertEquals("read", authorizationRequest.getAuthorizationParameters().get(AuthorizationRequest.SCOPE)); + } + @Test public void testScopeWithSpace() throws Exception { DefaultAuthorizationRequest authorizationRequest = new DefaultAuthorizationRequest(parameters); From b3da6d2fb3d80146a39f4641ee86a5b8c3f5666a Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 22 Feb 2013 16:57:10 +0000 Subject: [PATCH 023/831] Tidy imports --- .../OAuth2AccessTokenJackson2Deserializer.java | 16 ++++++++-------- .../OAuth2AccessTokenJackson2Serializer.java | 14 +++++++------- .../common/exceptions/OAuth2Exception.java | 5 ----- .../OAuth2ExceptionJackson2Serializer.java | 9 ++++----- .../common/BaseOAuth2AccessTokenJacksonTest.java | 1 - 5 files changed, 19 insertions(+), 26 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2Deserializer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2Deserializer.java index 73df07f39..1a9ef66d5 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2Deserializer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2Deserializer.java @@ -13,19 +13,20 @@ package org.springframework.security.oauth2.common; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.JsonToken; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.deser.std.StdDeserializer; -import org.springframework.security.oauth2.common.util.OAuth2Utils; - import java.io.IOException; import java.util.Date; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; +import org.springframework.security.oauth2.common.util.OAuth2Utils; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; + /** *

* Provides the ability to deserialize JSON response into an {@link org.springframework.security.oauth2.common.OAuth2AccessToken} with jackson2 by implementing @@ -40,7 +41,6 @@ * @author Brian Clozel * @see org.springframework.security.oauth2.common.OAuth2AccessTokenJackson2Serializer */ -@SuppressWarnings("deprecation") public final class OAuth2AccessTokenJackson2Deserializer extends StdDeserializer { public OAuth2AccessTokenJackson2Deserializer() { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2Serializer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2Serializer.java index cdbe86277..f006e3998 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2Serializer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2Serializer.java @@ -12,17 +12,18 @@ */ package org.springframework.security.oauth2.common; -import com.fasterxml.jackson.core.JsonGenerationException; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.SerializerProvider; -import com.fasterxml.jackson.databind.ser.std.StdSerializer; -import org.springframework.util.Assert; - import java.io.IOException; import java.util.Date; import java.util.Map; import java.util.Set; +import org.springframework.util.Assert; + +import com.fasterxml.jackson.core.JsonGenerationException; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; + /** * Provides the ability to serialize an {@link org.springframework.security.oauth2.common.OAuth2AccessToken} with jackson2 by implementing {@link com.fasterxml.jackson.databind.JsonDeserializer}. * Refer to {@link org.springframework.security.oauth2.common.OAuth2AccessTokenJackson1Deserializer} to learn more about the JSON format that is used. @@ -31,7 +32,6 @@ * @author Brian Clozel * @see org.springframework.security.oauth2.common.OAuth2AccessTokenJackson2Deserializer */ -@SuppressWarnings("deprecation") public final class OAuth2AccessTokenJackson2Serializer extends StdSerializer { public OAuth2AccessTokenJackson2Serializer() { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2Exception.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2Exception.java index 265b6e414..047056bdc 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2Exception.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2Exception.java @@ -1,10 +1,5 @@ package org.springframework.security.oauth2.common.exceptions; -import org.springframework.security.oauth2.common.OAuth2AccessTokenJackson1Deserializer; -import org.springframework.security.oauth2.common.OAuth2AccessTokenJackson1Serializer; -import org.springframework.security.oauth2.common.OAuth2AccessTokenJackson2Deserializer; -import org.springframework.security.oauth2.common.OAuth2AccessTokenJackson2Serializer; - import java.util.Map; import java.util.Set; import java.util.TreeMap; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson2Serializer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson2Serializer.java index 161b2e387..89005154a 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson2Serializer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson2Serializer.java @@ -12,14 +12,13 @@ */ package org.springframework.security.oauth2.common.exceptions; -import com.fasterxml.jackson.core.JsonGenerationException; +import java.io.IOException; +import java.util.Map.Entry; + import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.std.StdSerializer; -import com.fasterxml.jackson.core.JsonProcessingException; - -import java.io.IOException; -import java.util.Map.Entry; /** * @author Brian Clozel diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/BaseOAuth2AccessTokenJacksonTest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/BaseOAuth2AccessTokenJacksonTest.java index 638a96c21..e82dac222 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/BaseOAuth2AccessTokenJacksonTest.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/BaseOAuth2AccessTokenJacksonTest.java @@ -23,7 +23,6 @@ import java.util.Set; import java.util.TreeSet; -import org.codehaus.jackson.map.ObjectMapper; import org.junit.Before; import org.junit.Rule; import org.junit.rules.ExpectedException; From cdf933e8ed1dddbfb5002b44917817c8a3a856ec Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 13 Feb 2013 17:04:07 +0000 Subject: [PATCH 024/831] [maven-release-plugin] prepare release 1.0.2.RELEASE --- pom.xml | 4 ++-- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index 1f89c7fff..54077b43d 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ OAuth for Spring Security Parent Project for OAuth Support for Spring Security pom - 1.0.2.BUILD-SNAPSHOT + 1.0.2.RELEASE http://static.springframework.org/spring-security/oauth @@ -26,7 +26,7 @@ http://github.com/SpringSource/spring-security-oauth scm:git:git://github.com/SpringSource/spring-security-oauth.git scm:git:ssh://git@github.com/SpringSource/spring-security-oauth.git - HEAD + 1.0.2.RELEASE JIRA diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index 59c921274..7515d4e68 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 - 1.0.2.BUILD-SNAPSHOT + 1.0.2.RELEASE ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index e4f21725d..59f7fff1d 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 - 1.0.2.BUILD-SNAPSHOT + 1.0.2.RELEASE ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 6c0a7c7db..1a13066ec 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 - 1.0.2.BUILD-SNAPSHOT + 1.0.2.RELEASE ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 65f4e7604..03962c68a 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 1.0.2.BUILD-SNAPSHOT + 1.0.2.RELEASE ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index 659208f5f..733b61075 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 1.0.2.BUILD-SNAPSHOT + 1.0.2.RELEASE spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index 36be444ac..f9668e077 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 - 1.0.2.BUILD-SNAPSHOT + 1.0.2.RELEASE spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index f0877d494..c52c15f43 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 - 1.0.2.BUILD-SNAPSHOT + 1.0.2.RELEASE spring-security-oauth2 From 02d76dd3d9d6c924e945039c3c0506be39fa6d44 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 13 Feb 2013 17:04:07 +0000 Subject: [PATCH 025/831] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index 54077b43d..83b90c2ac 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ OAuth for Spring Security Parent Project for OAuth Support for Spring Security pom - 1.0.2.RELEASE + 1.0.3.BUILD-SNAPSHOT http://static.springframework.org/spring-security/oauth @@ -26,7 +26,7 @@ http://github.com/SpringSource/spring-security-oauth scm:git:git://github.com/SpringSource/spring-security-oauth.git scm:git:ssh://git@github.com/SpringSource/spring-security-oauth.git - 1.0.2.RELEASE + HEAD JIRA diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index 7515d4e68..a09a282b3 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 - 1.0.2.RELEASE + 1.0.3.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index 59f7fff1d..b064521c0 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 - 1.0.2.RELEASE + 1.0.3.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 1a13066ec..d4b472ef2 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 - 1.0.2.RELEASE + 1.0.3.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 03962c68a..cf81a13a5 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 1.0.2.RELEASE + 1.0.3.BUILD-SNAPSHOT ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index 733b61075..b89ebe3fc 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 1.0.2.RELEASE + 1.0.3.BUILD-SNAPSHOT spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index f9668e077..5c783daad 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 - 1.0.2.RELEASE + 1.0.3.BUILD-SNAPSHOT spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index c52c15f43..e9dc346ab 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 - 1.0.2.RELEASE + 1.0.3.BUILD-SNAPSHOT spring-security-oauth2 From e84c5083e8fd0069c65910b60ff7b6e1738b95b9 Mon Sep 17 00:00:00 2001 From: Luke Taylor Date: Fri, 1 Mar 2013 19:54:38 +0000 Subject: [PATCH 026/831] Add JWT support for RSA public key PEM formats. This makes it possible to create an RsaVerifier with a PEM encoded public key. Previously it could only be done with a private key or an ssh-keygen format public key. --- .../jwt/crypto/sign/RsaKeyHelper.java | 55 ++++++++++--------- .../jwt/crypto/cipher/RsaTestKeyData.java | 20 +++++++ .../jwt/crypto/sign/RsaSigningTests.java | 12 +++- 3 files changed, 58 insertions(+), 29 deletions(-) diff --git a/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/RsaKeyHelper.java b/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/RsaKeyHelper.java index 84a35771d..41f36e47e 100644 --- a/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/RsaKeyHelper.java +++ b/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/RsaKeyHelper.java @@ -18,18 +18,13 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.math.BigInteger; -import java.security.KeyFactory; -import java.security.KeyPair; -import java.security.NoSuchAlgorithmException; +import java.security.*; import java.security.interfaces.RSAPublicKey; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.RSAPrivateCrtKeySpec; -import java.security.spec.RSAPublicKeySpec; +import java.security.spec.*; import java.util.Arrays; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.ASN1Sequence; /** @@ -50,32 +45,38 @@ static KeyPair parseKeyPair(String pemData) { } String type = m.group(1); + final byte[] content = b64Decode(utf8Encode(m.group(2))); - if (!type.equals("RSA PRIVATE KEY")) { - throw new IllegalArgumentException("Only private key data is currently supported"); - } - - String content = m.group(2); + PublicKey publicKey; + PrivateKey privateKey = null; try { - ASN1Sequence seq = ASN1Sequence.getInstance(ASN1Primitive.fromByteArray(b64Decode(utf8Encode(content)))); - if (seq.size() != 9) { - throw new IllegalArgumentException("Invalid RSA Key ASN1 sequence."); - } - org.bouncycastle.asn1.pkcs.RSAPrivateKey key = org.bouncycastle.asn1.pkcs.RSAPrivateKey.getInstance(seq); - RSAPublicKeySpec pubSpec = new RSAPublicKeySpec(key.getModulus(), key.getPublicExponent()); - RSAPrivateCrtKeySpec privSpec = new RSAPrivateCrtKeySpec(key.getModulus(), key.getPublicExponent(), + KeyFactory fact = KeyFactory.getInstance("RSA"); + if (type.equals("RSA PRIVATE KEY")) { + ASN1Sequence seq = ASN1Sequence.getInstance(content); + if (seq.size() != 9) { + throw new IllegalArgumentException("Invalid RSA Private Key ASN1 sequence."); + } + org.bouncycastle.asn1.pkcs.RSAPrivateKey key = org.bouncycastle.asn1.pkcs.RSAPrivateKey.getInstance(seq); + RSAPublicKeySpec pubSpec = new RSAPublicKeySpec(key.getModulus(), key.getPublicExponent()); + RSAPrivateCrtKeySpec privSpec = new RSAPrivateCrtKeySpec(key.getModulus(), key.getPublicExponent(), key.getPrivateExponent(), key.getPrime1(), key.getPrime2(), key.getExponent1(), key.getExponent2(), key.getCoefficient()); + publicKey = fact.generatePublic(pubSpec); + privateKey = fact.generatePrivate(privSpec); + } else if (type.equals("PUBLIC KEY")) { + KeySpec keySpec = new X509EncodedKeySpec(content); + publicKey = fact.generatePublic(keySpec); + } else if (type.equals("RSA PUBLIC KEY")) { + ASN1Sequence seq = ASN1Sequence.getInstance(content); + org.bouncycastle.asn1.pkcs.RSAPublicKey key = org.bouncycastle.asn1.pkcs.RSAPublicKey.getInstance(seq); + RSAPublicKeySpec pubSpec = new RSAPublicKeySpec(key.getModulus(), key.getPublicExponent()); + publicKey = fact.generatePublic(pubSpec); + } else { + throw new IllegalArgumentException(type + " is not a supported format"); + } - KeyFactory fact = KeyFactory.getInstance("RSA"); - - return new KeyPair( - fact.generatePublic(pubSpec), - fact.generatePrivate(privSpec)); - } - catch (IOException e) { - throw new RuntimeException(e); + return new KeyPair(publicKey, privateKey); } catch (InvalidKeySpecException e) { throw new RuntimeException(e); diff --git a/spring-security-jwt/src/test/java/org/springframework/security/jwt/crypto/cipher/RsaTestKeyData.java b/spring-security-jwt/src/test/java/org/springframework/security/jwt/crypto/cipher/RsaTestKeyData.java index be567fadc..b37d29504 100644 --- a/spring-security-jwt/src/test/java/org/springframework/security/jwt/crypto/cipher/RsaTestKeyData.java +++ b/spring-security-jwt/src/test/java/org/springframework/security/jwt/crypto/cipher/RsaTestKeyData.java @@ -97,4 +97,24 @@ public class RsaTestKeyData { + "eJQ4nUR0pkfEaeRWOmzWE/3wC9DHoSmYoTF7B3gwyPvuBFgB5KjSk+G6AuubLkMs+jFJQZJkQcI+UJ859MC3024ThjBukLAN8OZBv7" + "2d6rtDQ/Ca0/qMWtXhVneKvZxZg5MXoVwvtkidwbdoK9fGnylRDs0+KZh3vR0Q+67V blah@blah.local"; + + public static final String SSH_PUBLIC_KEY_OPENSSL_PEM_STRING = "-----BEGIN PUBLIC KEY-----\n" + + "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwARN4S7Z0asSEj61+SIv\n" + + "tUUuHopd/ffne1CbaHXNxj/cI4rY0k5ELZ2SGCFVgmx9XADJJhYoQImO+vMxFAqb\n" + + "WxyO45B1rZR1q0ChEFWLGPmNB+fY8TrFHIjJb873s0d2FTYDOwst6HdKPjXkLdgG\n" + + "HO4K1fLnO1cQHKGglBKvc4ZSVniUOJ1EdKZHxGnkVjps1hP98AvQx6EpmKExewd4\n" + + "MMj77gRYAeSo0pPhugLrmy5DLPoxSUGSZEHCPlCfOfTAt9NuE4YwbpCwDfDmQb+9\n" + + "neq7Q0PwmtP6jFrV4VZ3ir2cWYOTF6FcL7ZIncG3aCvXxp8pUQ7NPimYd70dEPuu\n" + + "1QIDAQAB\n" + + "-----END PUBLIC KEY-----"; + + public static final String SSH_PUBLIC_KEY_PEM_STRING = "-----BEGIN RSA PUBLIC KEY-----\n" + + "MIIBCgKCAQEAwARN4S7Z0asSEj61+SIvtUUuHopd/ffne1CbaHXNxj/cI4rY0k5E\n" + + "LZ2SGCFVgmx9XADJJhYoQImO+vMxFAqbWxyO45B1rZR1q0ChEFWLGPmNB+fY8TrF\n" + + "HIjJb873s0d2FTYDOwst6HdKPjXkLdgGHO4K1fLnO1cQHKGglBKvc4ZSVniUOJ1E\n" + + "dKZHxGnkVjps1hP98AvQx6EpmKExewd4MMj77gRYAeSo0pPhugLrmy5DLPoxSUGS\n" + + "ZEHCPlCfOfTAt9NuE4YwbpCwDfDmQb+9neq7Q0PwmtP6jFrV4VZ3ir2cWYOTF6Fc\n" + + "L7ZIncG3aCvXxp8pUQ7NPimYd70dEPuu1QIDAQAB\n" + + "-----END RSA PUBLIC KEY-----"; + } diff --git a/spring-security-jwt/src/test/java/org/springframework/security/jwt/crypto/sign/RsaSigningTests.java b/spring-security-jwt/src/test/java/org/springframework/security/jwt/crypto/sign/RsaSigningTests.java index 7cb7639e6..363dee8ef 100644 --- a/spring-security-jwt/src/test/java/org/springframework/security/jwt/crypto/sign/RsaSigningTests.java +++ b/spring-security-jwt/src/test/java/org/springframework/security/jwt/crypto/sign/RsaSigningTests.java @@ -41,12 +41,20 @@ public void keysFromPrivateAndPublicKeyStringDataAreCorrect() throws Exception { byte[] content = Codecs.utf8Encode("Hi I'm the data"); RsaSigner signer = new RsaSigner(RsaTestKeyData.SSH_PRIVATE_KEY_STRING); + final byte[] signed = signer.sign(content); // First extract the public key from the private key data RsaVerifier verifier = new RsaVerifier(RsaTestKeyData.SSH_PRIVATE_KEY_STRING); - verifier.verify(content, signer.sign(content)); + verifier.verify(content, signed); // Then try with the ssh-rsa public key format verifier = new RsaVerifier(RsaTestKeyData.SSH_PUBLIC_KEY_STRING); - verifier.verify(content, signer.sign(content)); + verifier.verify(content, signed); + + // Try with the PEM format public keys + verifier = new RsaVerifier(RsaTestKeyData.SSH_PUBLIC_KEY_PEM_STRING); + verifier.verify(content, signed); + + verifier = new RsaVerifier(RsaTestKeyData.SSH_PUBLIC_KEY_OPENSSL_PEM_STRING); + verifier.verify(content, signed); } } From d648f056015c5a43e1f8f198180290a0721ef234 Mon Sep 17 00:00:00 2001 From: Luke Taylor Date: Tue, 5 Mar 2013 12:05:03 +0000 Subject: [PATCH 027/831] JWT release 1.0.1 --- spring-security-jwt/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-security-jwt/pom.xml b/spring-security-jwt/pom.xml index 35383d500..5728c5ec3 100755 --- a/spring-security-jwt/pom.xml +++ b/spring-security-jwt/pom.xml @@ -5,7 +5,7 @@ org.springframework.security spring-security-jwt - 1.0.1.BUILD-SNAPSHOT + 1.0.1.RELEASE jar Spring Security JWT Library From 2e9815d05ed695df42b6966be86c2a47a8ab5f51 Mon Sep 17 00:00:00 2001 From: Luke Taylor Date: Tue, 5 Mar 2013 12:56:59 +0000 Subject: [PATCH 028/831] Update JWT pom to snapshot version --- spring-security-jwt/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-security-jwt/pom.xml b/spring-security-jwt/pom.xml index 5728c5ec3..52d894c4d 100755 --- a/spring-security-jwt/pom.xml +++ b/spring-security-jwt/pom.xml @@ -5,7 +5,7 @@ org.springframework.security spring-security-jwt - 1.0.1.RELEASE + 1.0.2.BUILD-SNAPSHOT jar Spring Security JWT Library From 22bdd96b9c447a710aa6de26fbf55ad380e0bff5 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 1 Apr 2013 13:30:09 -0700 Subject: [PATCH 029/831] SECOAUTH-395, SECOAUTH-396: change OSGi metadata for Jackson --- spring-security-oauth2/template.mf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-security-oauth2/template.mf b/spring-security-oauth2/template.mf index d26edc6cb..9a5a474bb 100644 --- a/spring-security-oauth2/template.mf +++ b/spring-security-oauth2/template.mf @@ -5,8 +5,8 @@ Bundle-ManifestVersion: 2 Import-Template: org.apache.commons.logging.*;version="[1.1.1, 2.0.0)", org.apache.commons.codec.*;version="[1.3, 2.0.0)", - org.codehaus.jackson.*;version="[1.9.3, 2.0.0)", - com.fasterxml.jackson.*;version="[2.0.0, 2.1.1)", + org.codehaus.jackson.*;version="[1.9.3, 2.0.0)";resolution:=optional, + com.fasterxml.jackson.*;version="[2.0.0, 3.0.0)";resolution:=optional, org.springframework.beans.*;version="${spring.osgi.range}", org.springframework.aop.*;version="${spring.osgi.range}", org.springframework.core.*;version="${spring.osgi.range}", From 0bc26bcf4bd63ae0a58edabfd39ea9faeaf108e0 Mon Sep 17 00:00:00 2001 From: Ali Moghadam Date: Wed, 26 Dec 2012 18:30:47 -0800 Subject: [PATCH 030/831] SECOAUTH-381: remove password from authorization request Fixes: User's password gets serialized in authentication column if password grant type is used --- .../oauth2/provider/AuthorizationRequest.java | 2 +- .../provider/DefaultAuthorizationRequest.java | 23 +++++++++++++++---- .../ResourceOwnerPasswordTokenGranter.java | 10 ++++---- .../TestDefaultAuthorizationRequest.java | 14 +++++++++++ 4 files changed, 39 insertions(+), 10 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java index 157e376f3..85f6f0c87 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java @@ -49,5 +49,5 @@ public interface AuthorizationRequest { public String getRedirectUri(); public Set getResponseTypes(); - + } \ No newline at end of file diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequest.java index adc157186..db568d9fe 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequest.java @@ -8,6 +8,7 @@ import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.oauth2.common.util.OAuth2Utils; @@ -31,7 +32,7 @@ public class DefaultAuthorizationRequest implements AuthorizationRequest, Serial private Collection authorities = new HashSet(); - private Map authorizationParameters = new HashMap(); + private Map authorizationParameters = new ConcurrentHashMap(); private Map approvalParameters = new HashMap(); @@ -78,8 +79,13 @@ private DefaultAuthorizationRequest(Map authorizationParameters, if (authorities != null) { this.authorities = new HashSet(authorities); } - this.authorizationParameters.put(CLIENT_ID, clientId); - this.authorizationParameters.put(SCOPE, OAuth2Utils.formatParameterList(scope)); + if (clientId != null) { + this.authorizationParameters.put(CLIENT_ID, clientId); + } + String scopes = OAuth2Utils.formatParameterList(scope); + if (scopes != null) { + this.authorizationParameters.put(SCOPE, scopes); + } this.approved = approved; } @@ -169,12 +175,13 @@ public void setAuthorizationParameters(Map authorizationParamete Set scope = getScope(); this.authorizationParameters = authorizationParameters == null ? new HashMap() : new HashMap(authorizationParameters); - if (!authorizationParameters.containsKey(CLIENT_ID) && clientId!=null) { + if (!authorizationParameters.containsKey(CLIENT_ID) && clientId != null) { this.authorizationParameters.put(CLIENT_ID, clientId); } if (StringUtils.hasText(authorizationParameters.get(SCOPE))) { setScope(OAuth2Utils.parseParameterList(authorizationParameters.get(SCOPE))); - } else { + } + else { setScope(scope); } } @@ -241,4 +248,10 @@ else if (!approvalParameters.equals(other.approvalParameters)) return true; } + public void remove(Collection keys) { + for (String key : keys) { + authorizationParameters.remove(key); + } + } + } \ No newline at end of file diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java index 8423327e2..750af1e47 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java @@ -16,7 +16,7 @@ package org.springframework.security.oauth2.provider.password; - +import java.util.Arrays; import java.util.Map; import org.springframework.security.authentication.AccountStatusException; @@ -27,6 +27,7 @@ import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.token.AbstractTokenGranter; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; @@ -70,8 +71,9 @@ protected OAuth2Authentication getOAuth2Authentication(AuthorizationRequest clie throw new InvalidGrantException("Could not authenticate user: " + username); } - return new OAuth2Authentication(clientToken, userAuth); + DefaultAuthorizationRequest request = new DefaultAuthorizationRequest(clientToken); + request.remove(Arrays.asList("password")); + return new OAuth2Authentication(request, userAuth); } - -} +} \ No newline at end of file diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestDefaultAuthorizationRequest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestDefaultAuthorizationRequest.java index d6a103ccd..a3a6ee81f 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestDefaultAuthorizationRequest.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestDefaultAuthorizationRequest.java @@ -18,6 +18,8 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.springframework.security.oauth2.provider.AuthorizationRequest.REDIRECT_URI; @@ -75,6 +77,18 @@ public void testClientIdNotOverwitten() throws Exception { assertEquals("client", authorizationRequest.getClientId()); assertEquals("read", authorizationRequest.getAuthorizationParameters().get(AuthorizationRequest.SCOPE)); } + + @Test + public void testPasswordSetAndRemovedFromParameters() throws Exception { + parameters.put("username", "sample"); + parameters.put("password", "testing"); + DefaultAuthorizationRequest authorizationRequest = new DefaultAuthorizationRequest(parameters); + assertEquals("testing", authorizationRequest.getAuthorizationParameters().get("password")); + + authorizationRequest.remove(Arrays.asList("password")); + assertNotNull(authorizationRequest.getAuthorizationParameters().get("username")); + assertNull(authorizationRequest.getAuthorizationParameters().get("password")); + } @Test public void testScopeWithSpace() throws Exception { From b208346d377deadf1f818f19d6128c4e8ebfb53d Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 11 Apr 2013 11:00:39 +0100 Subject: [PATCH 031/831] Fix typo in javadocs --- .../authentication/OAuth2AuthenticationProcessingFilter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilter.java index fe9b21294..39fff0b43 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilter.java @@ -41,7 +41,7 @@ import org.springframework.util.Assert; /** - * A pre-authemtication filter for OAuth2 protected resources. Extracts an OAuth2 token from the in coming request and + * A pre-authentication filter for OAuth2 protected resources. Extracts an OAuth2 token from the incoming request and * uses it to populate the Spring Security context with an {@link OAuth2Authentication} (if used in conjunction with an * {@link OAuth2AuthenticationManager}). * From b6749cbc78a90a557ee729143967402fc6fc272b Mon Sep 17 00:00:00 2001 From: Luke Taylor Date: Mon, 8 Apr 2013 17:34:03 +0100 Subject: [PATCH 032/831] Stricter checking for requested redirect_uri. For a URL, the protocol and host must match and the registered redirect must be a substring of the requested uri. For a non-URL, an exact match is required. --- .../endpoint/DefaultRedirectResolver.java | 40 +++++++++++++------ .../endpoint/ExactMatchRedirectResolver.java | 7 ++-- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolver.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolver.java index 5124c1860..152a64715 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolver.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolver.java @@ -15,6 +15,8 @@ */ package org.springframework.security.oauth2.provider.endpoint; +import java.net.MalformedURLException; +import java.net.URL; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; @@ -29,17 +31,17 @@ /** * Default implementation for a redirect resolver. - * + * * @author Ryan Heaton * @author Dave Syer */ public class DefaultRedirectResolver implements RedirectResolver { - + private Collection redirectGrantTypes = Arrays.asList("implicit", "authorization_code"); - + /** * Grant types that are permitted to have a redirect uri. - * + * * @param redirectGrantTypes the redirect grant types to set */ public void setRedirectGrantTypes(Collection redirectGrantTypes) { @@ -47,13 +49,13 @@ public void setRedirectGrantTypes(Collection redirectGrantTypes) { } public String resolveRedirect(String requestedRedirect, ClientDetails client) throws OAuth2Exception { - + Set authorizedGrantTypes = client.getAuthorizedGrantTypes(); if (authorizedGrantTypes.isEmpty()) { - throw new InvalidGrantException("A client must have at least one authorized grant type."); + throw new InvalidGrantException("A client must have at least one authorized grant type."); } if (!containsRedirectGrantType(authorizedGrantTypes)) { - throw new InvalidGrantException("A redirect_uri can only be used by implicit or authorization_code grant types."); + throw new InvalidGrantException("A redirect_uri can only be used by implicit or authorization_code grant types."); } Set redirectUris = client.getRegisteredRedirectUri(); @@ -84,21 +86,33 @@ private boolean containsRedirectGrantType(Set grantTypes) { } /** - * Whether the requested redirect URI "matches" the specified redirect URI. This implementation tests if the user - * requrested redirect starts with the registered redirect, so it would have the same host and root path if it is an - * HTTP URL. - * + * Whether the requested redirect URI "matches" the specified redirect URI. For a URL, this implementation tests if + * the user requested redirect starts with the registered redirect, so it would have the same host and root path if + * it is an HTTP URL. + *

+ * For other (non-URL) cases, such as for some implicit clients, the redirect_uri must be an exact match. + * * @param requestedRedirect The requested redirect URI. * @param redirectUri The registered redirect URI. * @return Whether the requested redirect URI "matches" the specified redirect URI. */ protected boolean redirectMatches(String requestedRedirect, String redirectUri) { - return requestedRedirect.startsWith(redirectUri); + try { + URL req = new URL(requestedRedirect); + URL reg = new URL(redirectUri); + + if (reg.getProtocol().equals(req.getProtocol()) && reg.getHost().equals(req.getHost())) { + return requestedRedirect.startsWith(redirectUri); + } + } + catch (MalformedURLException e) { + } + return requestedRedirect.equals(redirectUri); } /** * Attempt to match one of the registered URIs to the that of the requested one. - * + * * @param redirectUris the set of the registered URIs to try and find a match. This cannot be null or empty. * @param requestedRedirect the URI used as part of the request * @return the matching URI diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/ExactMatchRedirectResolver.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/ExactMatchRedirectResolver.java index b4ba8c9fc..65592dafc 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/ExactMatchRedirectResolver.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/ExactMatchRedirectResolver.java @@ -3,8 +3,9 @@ /** - * Default implementation for a redirect resolver. - * + * Strict implementation for a redirect resolver which requires + * an exact match between the registered and requested redirect_uri. + * * @author Ryan Heaton * @author Dave Syer */ @@ -13,7 +14,7 @@ public class ExactMatchRedirectResolver extends DefaultRedirectResolver { /** * Whether the requested redirect URI "matches" the specified redirect URI. This implementation tests strict * equality. - * + * * @param requestedRedirect The requested redirect URI. * @param redirectUri The registered redirect URI. * @return Whether the requested redirect URI "matches" the specified redirect URI. From 99ba2672a96c35d04b9ec0930da823ae63a707fa Mon Sep 17 00:00:00 2001 From: Aliaksandr Autayeu Date: Thu, 11 Apr 2013 16:41:51 +0200 Subject: [PATCH 033/831] SECOAUTH-386: OAuthProviderProcessingFilter should delegate its error handling to an AuthenticationEntryPoint --- .../OAuthProcessingFilterEntryPoint.java | 21 +++++++++++++------ .../filter/OAuthProviderProcessingFilter.java | 10 +-------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/OAuthProcessingFilterEntryPoint.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/OAuthProcessingFilterEntryPoint.java index 5dccae409..3de65b479 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/OAuthProcessingFilterEntryPoint.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/OAuthProcessingFilterEntryPoint.java @@ -17,6 +17,7 @@ package org.springframework.security.oauth.provider; import org.springframework.security.core.AuthenticationException; +import org.springframework.security.oauth.common.signature.UnsupportedSignatureMethodException; import org.springframework.security.web.AuthenticationEntryPoint; import javax.servlet.ServletException; @@ -34,12 +35,20 @@ public class OAuthProcessingFilterEntryPoint implements AuthenticationEntryPoint private String realmName; public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { - StringBuilder headerValue = new StringBuilder("OAuth"); - if (realmName != null) { - headerValue.append(" realm=\"").append(realmName).append('"'); - } - response.addHeader("WWW-Authenticate", headerValue.toString()); - response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage()); + if (authException instanceof InvalidOAuthParametersException) { + response.sendError(400, authException.getMessage()); + } + else if (authException.getCause() instanceof UnsupportedSignatureMethodException) { + response.sendError(400, authException.getMessage()); + } + else { + StringBuilder headerValue = new StringBuilder("OAuth"); + if (realmName != null) { + headerValue.append(" realm=\"").append(realmName).append('"'); + } + response.addHeader("WWW-Authenticate", headerValue.toString()); + response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage()); + } } public String getRealmName() { diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/OAuthProviderProcessingFilter.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/OAuthProviderProcessingFilter.java index 3c3fa4bfa..46f69e13b 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/OAuthProviderProcessingFilter.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/OAuthProviderProcessingFilter.java @@ -373,15 +373,7 @@ protected void fail(HttpServletRequest request, HttpServletResponse response, Au log.debug(failure); } - if (failure instanceof InvalidOAuthParametersException) { - response.sendError(400, failure.getMessage()); - } - else if (failure.getCause() instanceof UnsupportedSignatureMethodException) { - response.sendError(400, failure.getMessage()); - } - else { - authenticationEntryPoint.commence(request, response, failure); - } + authenticationEntryPoint.commence(request, response, failure); } /** From ad93c44117fe8a1a7551f3b3b20e3f84a2169d30 Mon Sep 17 00:00:00 2001 From: Fabiano Taioli Date: Mon, 18 Mar 2013 15:23:16 +0100 Subject: [PATCH 034/831] [gh-68] Allow custom granter to be resolved by XML namespace parser Fixes org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named ... see http://stackoverflow.com/questions/15438472/no-bean-named-but-bean-is-defined --- .../config/AuthorizationServerBeanDefinitionParser.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/AuthorizationServerBeanDefinitionParser.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/AuthorizationServerBeanDefinitionParser.java index fb6074beb..1c4c419f2 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/AuthorizationServerBeanDefinitionParser.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/AuthorizationServerBeanDefinitionParser.java @@ -22,6 +22,7 @@ import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.support.ManagedMap; import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.security.config.BeanIds; import org.springframework.security.oauth2.provider.CompositeTokenGranter; import org.springframework.security.oauth2.provider.DefaultAuthorizationRequestManager; @@ -177,8 +178,7 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P for(Element customGrantElement: customGrantElements) { if(!"true".equalsIgnoreCase(customGrantElement.getAttribute("disabled"))) { String customGranterRef = customGrantElement.getAttribute("token-granter-ref"); - parserContext.getRegistry().getBeanDefinition(customGranterRef); - tokenGranters.add(parserContext.getRegistry().getBeanDefinition(customGranterRef)); + tokenGranters.add( new RuntimeBeanReference(customGranterRef) ); } } } From f781368bd22b164628f4dbd69181e0415b906c95 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 12 Apr 2013 09:49:58 +0100 Subject: [PATCH 035/831] SECOAUTH-394: Append scope to implicit response if different than requested --- .../endpoint/AuthorizationEndpoint.java | 18 +++++- .../endpoint/TestAuthorizationEndpoint.java | 55 +++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java index 085e174d5..1ce06bfae 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java @@ -21,6 +21,7 @@ import java.util.Collections; import java.util.Date; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; @@ -86,6 +87,11 @@ @RequestMapping(value = "/oauth/authorize") public class AuthorizationEndpoint extends AbstractEndpoint implements InitializingBean { + /** + * + */ + private static final String ORIGINAL_SCOPE = "original_scope"; + private AuthorizationCodeServices authorizationCodeServices = new InMemoryAuthorizationCodeServices(); private RedirectResolver redirectResolver = new DefaultRedirectResolver(); @@ -113,7 +119,7 @@ public void setErrorPage(String errorPage) { @RequestMapping public ModelAndView authorize(Map model, @RequestParam(value = "response_type", required = false, defaultValue = "none") String responseType, - @RequestParam Map parameters, SessionStatus sessionStatus, Principal principal) { + @RequestParam Map requestParameters, SessionStatus sessionStatus, Principal principal) { Set responseTypes = OAuth2Utils.parseParameterList(responseType); @@ -122,9 +128,15 @@ public ModelAndView authorize(Map model, } try { + + Map parameters = new LinkedHashMap(requestParameters); // Manually initialize auth request instead of using @ModelAttribute // to make sure it comes from request instead of the session + String originalScope = parameters.get(AuthorizationRequest.SCOPE); + if (originalScope!=null) { + parameters.put(ORIGINAL_SCOPE, originalScope); + } DefaultAuthorizationRequest incomingRequest = new DefaultAuthorizationRequest( getAuthorizationRequestManager().createAuthorizationRequest(parameters)); @@ -305,6 +317,10 @@ private String appendAccessToken(AuthorizationRequest authorizationRequest, OAut long expires_in = (expiration.getTime() - System.currentTimeMillis()) / 1000; url.append("&expires_in=" + expires_in); } + String originalScope = authorizationRequest.getAuthorizationParameters().get(ORIGINAL_SCOPE); + if (originalScope==null || !OAuth2Utils.parseParameterList(originalScope).equals(accessToken.getScope())) { + url.append("&" + AuthorizationRequest.SCOPE + "=" + OAuth2Utils.formatParameterList(accessToken.getScope())); + } Map additionalInformation = accessToken.getAdditionalInformation(); for (String key : additionalInformation.keySet()) { Object value = additionalInformation.get(key); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestAuthorizationEndpoint.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestAuthorizationEndpoint.java index b69f4f08e..962bd00ef 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestAuthorizationEndpoint.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestAuthorizationEndpoint.java @@ -190,6 +190,61 @@ public boolean isApproved(AuthorizationRequest authorizationRequest, Authenticat String url = ((RedirectView) result.getView()).getUrl(); assertTrue("Wrong view: " + result, url.startsWith("http://anywhere.com/")); assertTrue("Wrong state: " + result, url.contains("&state=mystate")); + assertTrue("Wrong token: " + result, url.contains("access_token=")); + } + + @Test + public void testImplicitAppendsScope() throws Exception { + endpoint.setTokenGranter(new TokenGranter() { + public OAuth2AccessToken grant(String grantType, AuthorizationRequest authorizationRequest) { + DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken("FOO"); + token.setScope(Collections.singleton("read")); + return token; + } + }); + endpoint.setUserApprovalHandler(new UserApprovalHandler() { + public AuthorizationRequest updateBeforeApproval(AuthorizationRequest authorizationRequest, + Authentication userAuthentication) { + return authorizationRequest; + } + + public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { + return true; + } + }); + AuthorizationRequest authorizationRequest = getAuthorizationRequest("foo", "http://anywhere.com/", "mystate", + "myscope"); + ModelAndView result = endpoint.authorize(model, "token", authorizationRequest.getAuthorizationParameters(), + sessionStatus, principal); + String url = ((RedirectView) result.getView()).getUrl(); + assertTrue("Wrong scope: " + result, url.contains("&scope=read")); + } + + @Test + public void testImplicitAppendsScopeWhenDefaulting() throws Exception { + endpoint.setTokenGranter(new TokenGranter() { + public OAuth2AccessToken grant(String grantType, AuthorizationRequest authorizationRequest) { + DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken("FOO"); + token.setScope(Collections.singleton("read")); + return token; + } + }); + endpoint.setUserApprovalHandler(new UserApprovalHandler() { + public AuthorizationRequest updateBeforeApproval(AuthorizationRequest authorizationRequest, + Authentication userAuthentication) { + return authorizationRequest; + } + + public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { + return true; + } + }); + AuthorizationRequest authorizationRequest = getAuthorizationRequest("foo", "http://anywhere.com/", "mystate", + null); + ModelAndView result = endpoint.authorize(model, "token", authorizationRequest.getAuthorizationParameters(), + sessionStatus, principal); + String url = ((RedirectView) result.getView()).getUrl(); + assertTrue("Wrong scope: " + result, url.contains("&scope=read")); } @Test(expected = InvalidScopeException.class) From 88dea7e24ef55e4fe30a40676d89f6df3770ca1a Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 12 Apr 2013 10:05:12 +0100 Subject: [PATCH 036/831] [gh-51]: added flag to DefaultAuthorizationEquestManager to hide valid scopes by default from client --- .../DefaultAuthorizationRequestManager.java | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequestManager.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequestManager.java index f1ffede72..2322d456f 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequestManager.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequestManager.java @@ -31,6 +31,18 @@ public class DefaultAuthorizationRequestManager implements AuthorizationRequestM private final ClientDetailsService clientDetailsService; + private boolean revealValidScopes = false; + + /** + * Flag to indicate that when an invalid scope is requested, the valid values should be revealed in the exception + * (which is then seen by the client). Default false; + * + * @param revealValidScopes the revealValidScopes to set + */ + public void setRevealValidScopes(boolean revealValidScopes) { + this.revealValidScopes = revealValidScopes; + } + public DefaultAuthorizationRequestManager(ClientDetailsService clientDetailsService) { this.clientDetailsService = clientDetailsService; } @@ -49,8 +61,8 @@ public AuthorizationRequest createAuthorizationRequest(Map param // least obnoxious choice as a default). scopes = clientDetails.getScope(); } - DefaultAuthorizationRequest request = new DefaultAuthorizationRequest(parameters, Collections. emptyMap(), - clientId, scopes); + DefaultAuthorizationRequest request = new DefaultAuthorizationRequest(parameters, + Collections. emptyMap(), clientId, scopes); request.addClientDetails(clientDetails); return request; @@ -62,7 +74,14 @@ public void validateParameters(Map parameters, ClientDetails cli Set validScope = clientDetails.getScope(); for (String scope : OAuth2Utils.parseParameterList(parameters.get("scope"))) { if (!validScope.contains(scope)) { - throw new InvalidScopeException("Invalid scope: " + scope, validScope); + InvalidScopeException exception; + if (revealValidScopes) { + exception = new InvalidScopeException("Invalid scope: " + scope, validScope); + } + else { + exception = new InvalidScopeException("Invalid scope: " + scope); + } + throw exception; } } } From 2e55ee4768035fe4cf8fc219e784d78282e6023b Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 12 Apr 2013 13:05:35 +0100 Subject: [PATCH 037/831] SECOAUTH-366: Change default type of authentication in 401 response --- .../oauth2/provider/TestClientCredentialsProvider.java | 4 ++-- .../provider/client/ClientCredentialsTokenEndpointFilter.java | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestClientCredentialsProvider.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestClientCredentialsProvider.java index 49c44a845..4789169c4 100644 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestClientCredentialsProvider.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestClientCredentialsProvider.java @@ -101,7 +101,7 @@ public void handleError(ClientHttpResponse response) throws IOException { @Test @OAuth2ContextConfiguration(resource = InvalidClientCredentials.class, initialize = false) public void testInvalidCredentialsWithFormAuthentication() throws Exception { - resource.setAuthenticationScheme(AuthenticationScheme.form); + resource.setClientAuthenticationScheme(AuthenticationScheme.form); context.setAccessTokenProvider(new ClientCredentialsAccessTokenProvider() { @Override protected ResponseErrorHandler getResponseErrorHandler() { @@ -122,7 +122,7 @@ public void handleError(ClientHttpResponse response) throws IOException { } // System.err.println(responseHeaders); String header = responseHeaders.getFirst("WWW-Authenticate"); - assertTrue("Wrong header: " + header, header.contains("Basic realm")); + assertTrue("Wrong header: " + header, header.contains("Form realm")); assertEquals(HttpStatus.UNAUTHORIZED, responseStatus); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenEndpointFilter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenEndpointFilter.java index ffe1955bc..b11be687b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenEndpointFilter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenEndpointFilter.java @@ -50,6 +50,8 @@ public ClientCredentialsTokenEndpointFilter() { public ClientCredentialsTokenEndpointFilter(String path) { super(path); + // If authentication fails the type is "Form" + ((OAuth2AuthenticationEntryPoint)authenticationEntryPoint).setTypeName("Form"); } /** From 7838c880ff8a58525095ebcbee1f7be6206c8f3e Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 17 Apr 2013 08:39:29 +0100 Subject: [PATCH 038/831] [maven-release-plugin] prepare release 1.0.3.RELEASE --- pom.xml | 4 ++-- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index 83b90c2ac..a6f7c0be3 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ OAuth for Spring Security Parent Project for OAuth Support for Spring Security pom - 1.0.3.BUILD-SNAPSHOT + 1.0.3.RELEASE http://static.springframework.org/spring-security/oauth @@ -26,7 +26,7 @@ http://github.com/SpringSource/spring-security-oauth scm:git:git://github.com/SpringSource/spring-security-oauth.git scm:git:ssh://git@github.com/SpringSource/spring-security-oauth.git - HEAD + 1.0.3.RELEASE JIRA diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index a09a282b3..651fc94e2 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 - 1.0.3.BUILD-SNAPSHOT + 1.0.3.RELEASE ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index b064521c0..3c00776df 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 - 1.0.3.BUILD-SNAPSHOT + 1.0.3.RELEASE ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index d4b472ef2..77e168038 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 - 1.0.3.BUILD-SNAPSHOT + 1.0.3.RELEASE ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index cf81a13a5..abc76cfb2 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 1.0.3.BUILD-SNAPSHOT + 1.0.3.RELEASE ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index b89ebe3fc..5630ef687 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 1.0.3.BUILD-SNAPSHOT + 1.0.3.RELEASE spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index 5c783daad..b2ffdd86b 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 - 1.0.3.BUILD-SNAPSHOT + 1.0.3.RELEASE spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index e9dc346ab..56cba590f 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 - 1.0.3.BUILD-SNAPSHOT + 1.0.3.RELEASE spring-security-oauth2 From f7e2fae46a93c6fe65f1361fd2fd5ae6c518f90f Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 17 Apr 2013 08:39:35 +0100 Subject: [PATCH 039/831] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index a6f7c0be3..1bac80b1f 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ OAuth for Spring Security Parent Project for OAuth Support for Spring Security pom - 1.0.3.RELEASE + 1.0.4.BUILD-SNAPSHOT http://static.springframework.org/spring-security/oauth @@ -26,7 +26,7 @@ http://github.com/SpringSource/spring-security-oauth scm:git:git://github.com/SpringSource/spring-security-oauth.git scm:git:ssh://git@github.com/SpringSource/spring-security-oauth.git - 1.0.3.RELEASE + HEAD JIRA diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index 651fc94e2..b272abe11 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 - 1.0.3.RELEASE + 1.0.4.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index 3c00776df..f34932333 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 - 1.0.3.RELEASE + 1.0.4.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 77e168038..9b38c9ad1 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 - 1.0.3.RELEASE + 1.0.4.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index abc76cfb2..4676120b3 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 1.0.3.RELEASE + 1.0.4.BUILD-SNAPSHOT ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index 5630ef687..2cd8bf2e9 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 1.0.3.RELEASE + 1.0.4.BUILD-SNAPSHOT spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index b2ffdd86b..04ee3b3ae 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 - 1.0.3.RELEASE + 1.0.4.BUILD-SNAPSHOT spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 56cba590f..39f3809b1 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 - 1.0.3.RELEASE + 1.0.4.BUILD-SNAPSHOT spring-security-oauth2 From 85dbf8252145bf6aa587bba2e51cbbfac3d8b5f8 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 23 Apr 2013 12:02:36 +0100 Subject: [PATCH 040/831] SECOAUTH-400: ensure implicit response is encoded --- .../endpoint/AuthorizationEndpoint.java | 23 +++++++++++++------ .../endpoint/TestAuthorizationEndpoint.java | 5 ++-- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java index 1ce06bfae..272cc2c1b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java @@ -64,6 +64,7 @@ import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.View; import org.springframework.web.servlet.view.RedirectView; +import org.springframework.web.util.UriTemplate; /** *

@@ -295,6 +296,7 @@ private View getAuthorizationCodeResponse(AuthorizationRequest authorizationRequ } private String appendAccessToken(AuthorizationRequest authorizationRequest, OAuth2AccessToken accessToken) { + Map vars = new HashMap(); String requestedRedirect = authorizationRequest.getRedirectUri(); if (accessToken == null) { throw new InvalidGrantException("An implicit grant could not be made"); @@ -306,30 +308,37 @@ private String appendAccessToken(AuthorizationRequest authorizationRequest, OAut else { url.append("#"); } - url.append("access_token=" + accessToken.getValue()); - url.append("&token_type=" + accessToken.getTokenType()); + url.append("access_token={access_token}"); + url.append("&token_type={token_type}"); + vars.put("access_token", accessToken.getValue()); + vars.put("token_type", accessToken.getTokenType()); String state = authorizationRequest.getState(); if (state != null) { - url.append("&state=" + state); + url.append("&state={state}"); + vars.put("state", state); } Date expiration = accessToken.getExpiration(); if (expiration != null) { long expires_in = (expiration.getTime() - System.currentTimeMillis()) / 1000; - url.append("&expires_in=" + expires_in); + url.append("&expires_in={expires_in}"); + vars.put("expires_in", expires_in); } String originalScope = authorizationRequest.getAuthorizationParameters().get(ORIGINAL_SCOPE); if (originalScope==null || !OAuth2Utils.parseParameterList(originalScope).equals(accessToken.getScope())) { - url.append("&" + AuthorizationRequest.SCOPE + "=" + OAuth2Utils.formatParameterList(accessToken.getScope())); + url.append("&" + AuthorizationRequest.SCOPE + "={scope}"); + vars.put("scope", OAuth2Utils.formatParameterList(accessToken.getScope())); } Map additionalInformation = accessToken.getAdditionalInformation(); for (String key : additionalInformation.keySet()) { Object value = additionalInformation.get(key); if (value != null) { - url.append("&" + key + "=" + value); // implicit call of .toString() here + url.append("&" + key + "={extra_" + key + "}"); + vars.put("extra" + key, value); } } + UriTemplate template = new UriTemplate(url.toString()); // Do not include the refresh token (even if there is one) - return url.toString(); + return template.expand(vars).toString(); } private String generateCode(AuthorizationRequest authorizationRequest, Authentication authentication) diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestAuthorizationEndpoint.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestAuthorizationEndpoint.java index 962bd00ef..2dd61e614 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestAuthorizationEndpoint.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestAuthorizationEndpoint.java @@ -22,6 +22,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashSet; import org.junit.Before; import org.junit.Test; @@ -225,7 +226,7 @@ public void testImplicitAppendsScopeWhenDefaulting() throws Exception { endpoint.setTokenGranter(new TokenGranter() { public OAuth2AccessToken grant(String grantType, AuthorizationRequest authorizationRequest) { DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken("FOO"); - token.setScope(Collections.singleton("read")); + token.setScope(new LinkedHashSet(Arrays.asList("read", "write"))); return token; } }); @@ -244,7 +245,7 @@ public boolean isApproved(AuthorizationRequest authorizationRequest, Authenticat ModelAndView result = endpoint.authorize(model, "token", authorizationRequest.getAuthorizationParameters(), sessionStatus, principal); String url = ((RedirectView) result.getView()).getUrl(); - assertTrue("Wrong scope: " + result, url.contains("&scope=read")); + assertTrue("Wrong scope: " + result, url.contains("&scope=read%20write")); } @Test(expected = InvalidScopeException.class) From 3c06220695f5823fac779462cdfef57dbd35fa77 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 23 Apr 2013 13:19:19 +0100 Subject: [PATCH 041/831] SECOAUTH-400: add integration test for scope in implicit grant --- .../main/webapp/WEB-INF/spring-servlet.xml | 2 +- .../oauth2/provider/ServerRunning.java | 4 ++-- .../oauth2/provider/TestImplicitProvider.java | 24 ++++++++++++++++++- .../token/OAuth2AccessTokenSupport.java | 11 +++++++++ 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml index 83e2b0d4c..d34b56576 100644 --- a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml +++ b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml @@ -154,7 +154,7 @@ + authorities="ROLE_CLIENT" scope="read,write,trust" /> asList(new ClientHttpRequestInterceptor() { + public ClientHttpResponse intercept(HttpRequest request, byte[] body, + ClientHttpRequestExecution execution) throws IOException { + ClientHttpResponse result = execution.execute(request, body); + latestHeaders = result.getHeaders(); + return result; + } + })); + context.setAccessTokenProvider(implicitProvider); context.getAccessTokenRequest().setCookie(cookie); assertNotNull(context.getAccessToken()); + assertTrue("Wrong location header: " + latestHeaders.getLocation().getFragment(), latestHeaders.getLocation().getFragment() + .contains("scope=read trust write")); } @Test @@ -83,7 +106,6 @@ static class AutoApproveImplicit extends ImplicitResourceDetails { public AutoApproveImplicit(Object target) { super(); setClientId("my-less-trusted-autoapprove-client"); - setScope(Arrays.asList("read")); setId(getClientId()); setPreEstablishedRedirectUri("http://anywhere/"); TestImplicitProvider test = (TestImplicitProvider) target; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/OAuth2AccessTokenSupport.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/OAuth2AccessTokenSupport.java index d0fe5c7c9..f6ff53bb8 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/OAuth2AccessTokenSupport.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/OAuth2AccessTokenSupport.java @@ -13,6 +13,7 @@ import org.springframework.http.MediaType; import org.springframework.http.client.ClientHttpRequest; import org.springframework.http.client.ClientHttpRequestFactory; +import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.http.client.ClientHttpResponse; import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.http.converter.FormHttpMessageConverter; @@ -56,6 +57,15 @@ public abstract class OAuth2AccessTokenSupport { private ResponseErrorHandler responseErrorHandler = new AccessTokenErrorHandler(); + private List interceptors = new ArrayList(); + + /** + * Sets the request interceptors that this accessor should use. + */ + public void setInterceptors(List interceptors) { + this.interceptors = interceptors; + } + private ClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory() { @Override protected void prepareConnection(HttpURLConnection connection, String httpMethod) @@ -72,6 +82,7 @@ protected RestOperations getRestTemplate() { RestTemplate restTemplate = new RestTemplate(); restTemplate.setErrorHandler(getResponseErrorHandler()); restTemplate.setRequestFactory(requestFactory); + restTemplate.setInterceptors(interceptors); this.restTemplate = restTemplate; } } From bbe9c54e336facd91db235718fafab8433bcf02b Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 23 Apr 2013 13:26:16 +0100 Subject: [PATCH 042/831] [maven-release-plugin] prepare release 1.0.4.RELEASE --- pom.xml | 4 ++-- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index 1bac80b1f..dba525a07 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ OAuth for Spring Security Parent Project for OAuth Support for Spring Security pom - 1.0.4.BUILD-SNAPSHOT + 1.0.4.RELEASE http://static.springframework.org/spring-security/oauth @@ -26,7 +26,7 @@ http://github.com/SpringSource/spring-security-oauth scm:git:git://github.com/SpringSource/spring-security-oauth.git scm:git:ssh://git@github.com/SpringSource/spring-security-oauth.git - HEAD + 1.0.4.RELEASE JIRA diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index b272abe11..1fc4b204c 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 - 1.0.4.BUILD-SNAPSHOT + 1.0.4.RELEASE ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index f34932333..917233706 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 - 1.0.4.BUILD-SNAPSHOT + 1.0.4.RELEASE ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 9b38c9ad1..d8021f6c0 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 - 1.0.4.BUILD-SNAPSHOT + 1.0.4.RELEASE ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 4676120b3..526e39e00 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 1.0.4.BUILD-SNAPSHOT + 1.0.4.RELEASE ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index 2cd8bf2e9..1da750de7 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 1.0.4.BUILD-SNAPSHOT + 1.0.4.RELEASE spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index 04ee3b3ae..67164a530 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 - 1.0.4.BUILD-SNAPSHOT + 1.0.4.RELEASE spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 39f3809b1..fa24bb39f 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 - 1.0.4.BUILD-SNAPSHOT + 1.0.4.RELEASE spring-security-oauth2 From 0cdf48b86922c51230a46524791b69be1c045023 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 23 Apr 2013 13:26:24 +0100 Subject: [PATCH 043/831] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index dba525a07..fba549181 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ OAuth for Spring Security Parent Project for OAuth Support for Spring Security pom - 1.0.4.RELEASE + 1.0.5.BUILD-SNAPSHOT http://static.springframework.org/spring-security/oauth @@ -26,7 +26,7 @@ http://github.com/SpringSource/spring-security-oauth scm:git:git://github.com/SpringSource/spring-security-oauth.git scm:git:ssh://git@github.com/SpringSource/spring-security-oauth.git - 1.0.4.RELEASE + HEAD JIRA diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index 1fc4b204c..0e526e714 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 - 1.0.4.RELEASE + 1.0.5.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index 917233706..bb190790a 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 - 1.0.4.RELEASE + 1.0.5.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index d8021f6c0..188eda35f 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 - 1.0.4.RELEASE + 1.0.5.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 526e39e00..ecb4e3e06 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 1.0.4.RELEASE + 1.0.5.BUILD-SNAPSHOT ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index 1da750de7..ed0b5c1ba 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 1.0.4.RELEASE + 1.0.5.BUILD-SNAPSHOT spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index 67164a530..f5430a55e 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 - 1.0.4.RELEASE + 1.0.5.BUILD-SNAPSHOT spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index fa24bb39f..444484fdd 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 - 1.0.4.RELEASE + 1.0.5.BUILD-SNAPSHOT spring-security-oauth2 From fcb470f748d418db0fbd4672f06f23e59a4a2d2d Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 23 Apr 2013 21:47:48 +0100 Subject: [PATCH 044/831] Fix key error in implicit grant response (for additional info) --- .../oauth2/provider/endpoint/AuthorizationEndpoint.java | 2 +- .../oauth2/provider/endpoint/TestAuthorizationEndpoint.java | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java index 272cc2c1b..2022a8a30 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java @@ -333,7 +333,7 @@ private String appendAccessToken(AuthorizationRequest authorizationRequest, OAut Object value = additionalInformation.get(key); if (value != null) { url.append("&" + key + "={extra_" + key + "}"); - vars.put("extra" + key, value); + vars.put("extra_" + key, value); } } UriTemplate template = new UriTemplate(url.toString()); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestAuthorizationEndpoint.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestAuthorizationEndpoint.java index 2dd61e614..d78593c02 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestAuthorizationEndpoint.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestAuthorizationEndpoint.java @@ -171,7 +171,9 @@ public void testAuthorizationCodeWithMultipleResponseTypes() throws Exception { public void testImplicitPreApproved() throws Exception { endpoint.setTokenGranter(new TokenGranter() { public OAuth2AccessToken grant(String grantType, AuthorizationRequest authorizationRequest) { - return new DefaultOAuth2AccessToken("FOO"); + DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken("FOO"); + token.setAdditionalInformation(Collections.singletonMap("foo", (Object)"bar")); + return token; } }); endpoint.setUserApprovalHandler(new UserApprovalHandler() { @@ -192,6 +194,7 @@ public boolean isApproved(AuthorizationRequest authorizationRequest, Authenticat assertTrue("Wrong view: " + result, url.startsWith("http://anywhere.com/")); assertTrue("Wrong state: " + result, url.contains("&state=mystate")); assertTrue("Wrong token: " + result, url.contains("access_token=")); + assertTrue("Wrong token: " + result, url.contains("foo=bar")); } @Test From be52453f005b9f46532f7de5e30744784370522c Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 23 Apr 2013 21:49:21 +0100 Subject: [PATCH 045/831] [maven-release-plugin] prepare release 1.0.5.RELEASE --- pom.xml | 4 ++-- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index fba549181..87d8c6a33 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ OAuth for Spring Security Parent Project for OAuth Support for Spring Security pom - 1.0.5.BUILD-SNAPSHOT + 1.0.5.RELEASE http://static.springframework.org/spring-security/oauth @@ -26,7 +26,7 @@ http://github.com/SpringSource/spring-security-oauth scm:git:git://github.com/SpringSource/spring-security-oauth.git scm:git:ssh://git@github.com/SpringSource/spring-security-oauth.git - HEAD + 1.0.5.RELEASE JIRA diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index 0e526e714..e49fdbdd9 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 - 1.0.5.BUILD-SNAPSHOT + 1.0.5.RELEASE ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index bb190790a..9d377f8bf 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 - 1.0.5.BUILD-SNAPSHOT + 1.0.5.RELEASE ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 188eda35f..a607bbb4f 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 - 1.0.5.BUILD-SNAPSHOT + 1.0.5.RELEASE ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index ecb4e3e06..25b642b3c 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 1.0.5.BUILD-SNAPSHOT + 1.0.5.RELEASE ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index ed0b5c1ba..88d0f63ee 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 1.0.5.BUILD-SNAPSHOT + 1.0.5.RELEASE spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index f5430a55e..36d1bda9e 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 - 1.0.5.BUILD-SNAPSHOT + 1.0.5.RELEASE spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 444484fdd..57941fa6a 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 - 1.0.5.BUILD-SNAPSHOT + 1.0.5.RELEASE spring-security-oauth2 From cfc84bca8f96a6befe274676921eba706dd9db45 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 23 Apr 2013 21:49:27 +0100 Subject: [PATCH 046/831] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index 87d8c6a33..16e33b52b 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ OAuth for Spring Security Parent Project for OAuth Support for Spring Security pom - 1.0.5.RELEASE + 1.0.6.BUILD-SNAPSHOT http://static.springframework.org/spring-security/oauth @@ -26,7 +26,7 @@ http://github.com/SpringSource/spring-security-oauth scm:git:git://github.com/SpringSource/spring-security-oauth.git scm:git:ssh://git@github.com/SpringSource/spring-security-oauth.git - 1.0.5.RELEASE + HEAD JIRA diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index e49fdbdd9..bc9954ee8 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 - 1.0.5.RELEASE + 1.0.6.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index 9d377f8bf..f24227992 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 - 1.0.5.RELEASE + 1.0.6.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index a607bbb4f..75e8f8a2e 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 - 1.0.5.RELEASE + 1.0.6.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 25b642b3c..95bf59596 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 1.0.5.RELEASE + 1.0.6.BUILD-SNAPSHOT ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index 88d0f63ee..b742fbc86 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 1.0.5.RELEASE + 1.0.6.BUILD-SNAPSHOT spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index 36d1bda9e..d6ba7881b 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 - 1.0.5.RELEASE + 1.0.6.BUILD-SNAPSHOT spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 57941fa6a..10e0e40ae 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 - 1.0.5.RELEASE + 1.0.6.BUILD-SNAPSHOT spring-security-oauth2 From 1ec9aa7f485b80313366f478053a04d06c9ea645 Mon Sep 17 00:00:00 2001 From: joemccall86 Date: Fri, 17 May 2013 10:29:32 -0300 Subject: [PATCH 047/831] Grammar nazi - it's vs its, etc. --- docs/oauth2.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/oauth2.md b/docs/oauth2.md index 84086bd70..e48bc32f6 100644 --- a/docs/oauth2.md +++ b/docs/oauth2.md @@ -2,7 +2,7 @@ ## Introduction -This is the user guide for the support for [`OAuth 2.0`](http://tools.ietf.org/html/draft-ietf-oauth-v2). For OAuth 1.0, everything is different, so [see it's user guide][oauth1]. +This is the user guide for the support for [`OAuth 2.0`](http://tools.ietf.org/html/draft-ietf-oauth-v2). For OAuth 1.0, everything is different, so [see its user guide][oauth1]. This user guide is divided into two parts, the first for the OAuth 2.0 provider, the second for the OAuth 2.0 client. @@ -107,7 +107,7 @@ The expressions include _oauth2.clientHasRole_, _oauth2.clientHasAnyRole_, and _ ## Resource Server Configuration -You need to supply the `` element with an `id` attribute - this is the bean id for a servlet `Filter` that can be added to teh standard Spring Security chain, e.g. +You need to supply the `` element with an `id` attribute - this is the bean id for a servlet `Filter` that can be added to the standard Spring Security chain, e.g. From bc4b1d26fab9c9182573b5aa2544b830f7d9589b Mon Sep 17 00:00:00 2001 From: Cailie Crane Date: Wed, 24 Apr 2013 19:28:33 -0700 Subject: [PATCH 048/831] SECOAUTH-401 Add support for "password" grant type --- .../config/ResourceBeanDefinitionParser.java | 34 ++++++++++++++----- .../oauth2/spring-security-oauth2-1.0.xsd | 14 ++++++++ .../TestResourceBeanDefinitionParser.java | 15 +++++++- ...stResourceBeanDefinitionParser-context.xml | 3 ++ 4 files changed, 56 insertions(+), 10 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/ResourceBeanDefinitionParser.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/ResourceBeanDefinitionParser.java index 5afcc7a05..bd549ddc8 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/ResourceBeanDefinitionParser.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/ResourceBeanDefinitionParser.java @@ -29,6 +29,7 @@ import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails; import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails; import org.springframework.security.oauth2.client.token.grant.implicit.ImplicitResourceDetails; +import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordResourceDetails; import org.springframework.security.oauth2.common.AuthenticationScheme; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.util.StringUtils; @@ -41,15 +42,19 @@ public class ResourceBeanDefinitionParser extends AbstractSingleBeanDefinitionPa @Override protected Class getBeanClass(Element element) { - if ("authorization_code".equals(element.getAttribute("type"))) { + String type = element.getAttribute("type"); + if ("authorization_code".equals(type)) { return AuthorizationCodeResourceDetails.class; } - if ("implicit".equals(element.getAttribute("type"))) { + if ("implicit".equals(type)) { return ImplicitResourceDetails.class; } - if ("client_credentials".equals(element.getAttribute("type"))) { + if ("client_credentials".equals(type)) { return ClientCredentialsResourceDetails.class; } + if ("password".equals(type)) { + return ResourceOwnerPasswordResourceDetails.class; + } return BaseOAuth2ProtectedResourceDetails.class; } @@ -92,15 +97,15 @@ protected void doParse(Element element, ParserContext parserContext, BeanDefinit String userAuthorizationUri = element.getAttribute("user-authorization-uri"); if (StringUtils.hasText(userAuthorizationUri)) { - if (type.equals("client_credentials")) { - parserContext.getReaderContext().error("The client_credentials grant type does not accept an authorization URI", element); - } else { + if (needsUserAuthorizationUri(type)) { builder.addPropertyValue("userAuthorizationUri", userAuthorizationUri); + } else { + parserContext.getReaderContext().error("The " + type + " grant type does not accept an authorization URI", element); } } else { - if (!type.equals("client_credentials")) { - parserContext.getReaderContext().error("An authorization URI must be supplied for a resource of type " + type, element); - } + if (needsUserAuthorizationUri(type)) { + parserContext.getReaderContext().error("An authorization URI must be supplied for a resource of type " + type, element); + } } String preEstablishedRedirectUri = element.getAttribute("pre-established-redirect-uri"); @@ -139,6 +144,13 @@ protected void doParse(Element element, ParserContext parserContext, BeanDefinit } builder.addPropertyValue("tokenName", bearerTokenName); + if (type.equals("password")) { + String[] attributeNames = {"username", "password"}; + for (String attributeName : attributeNames) { + String attribute = element.getAttribute(attributeName); + builder.addPropertyValue(attributeName, attribute); + } + } } /** @@ -168,4 +180,8 @@ public boolean isSingleton() { } + private boolean needsUserAuthorizationUri(String type) { + return type.equals("authorization_code") || type.equals("implicit"); + } + } \ No newline at end of file diff --git a/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.0.xsd b/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.0.xsd index 2e12bca5a..00f2eaa99 100644 --- a/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.0.xsd +++ b/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.0.xsd @@ -697,6 +697,20 @@ + + + + The username for authentication, required only when type is "password". + + + + + + + The password for authentication, required only when type is "password". + + + diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/TestResourceBeanDefinitionParser.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/TestResourceBeanDefinitionParser.java index 96aff44b6..92836a2bc 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/TestResourceBeanDefinitionParser.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/TestResourceBeanDefinitionParser.java @@ -14,6 +14,7 @@ import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails; import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails; import org.springframework.security.oauth2.client.token.grant.implicit.ImplicitResourceDetails; +import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordResourceDetails; import org.springframework.security.oauth2.common.AuthenticationScheme; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -45,7 +46,11 @@ public class TestResourceBeanDefinitionParser { @Autowired @Qualifier("six") private AuthorizationCodeResourceDetails six; - + + @Autowired + @Qualifier("seven") + private ResourceOwnerPasswordResourceDetails seven; + @Autowired @Qualifier("template") private OAuth2RestTemplate template; @@ -99,4 +104,12 @@ public void testResourceWithCurrentUriHint() { assertEquals(AuthenticationScheme.form, six.getClientAuthenticationScheme()); } + @Test + public void testResourceWithPasswordGrant() { + assertEquals("my-client-id", seven.getClientId()); + assertEquals("secret", seven.getClientSecret()); + assertEquals("http://somewhere.com/", seven.getAccessTokenUri()); + assertEquals("admin", seven.getUsername()); + assertEquals("long-and-strong", seven.getPassword()); + } } diff --git a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/TestResourceBeanDefinitionParser-context.xml b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/TestResourceBeanDefinitionParser-context.xml index b9752ae90..475093106 100644 --- a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/TestResourceBeanDefinitionParser-context.xml +++ b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/TestResourceBeanDefinitionParser-context.xml @@ -36,6 +36,9 @@ type="authorization_code" access-token-uri="http://somewhere.com/" user-authorization-uri="http://somewhere.com/" scope="none,some" token-name="token" client-authentication-scheme="form" use-current-uri="false" /> + + From ea0aa347121d128be4445975ef18c203e525c6bc Mon Sep 17 00:00:00 2001 From: Cailie Crane Date: Thu, 25 Apr 2013 09:56:13 -0700 Subject: [PATCH 049/831] SECOAUTH-401 Require the username and password attributes for password grant type --- .../config/ResourceBeanDefinitionParser.java | 6 +++++- .../TestInvalidResourceBeanDefinitionParser.java | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/ResourceBeanDefinitionParser.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/ResourceBeanDefinitionParser.java index bd549ddc8..27038a411 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/ResourceBeanDefinitionParser.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/ResourceBeanDefinitionParser.java @@ -148,7 +148,11 @@ protected void doParse(Element element, ParserContext parserContext, BeanDefinit String[] attributeNames = {"username", "password"}; for (String attributeName : attributeNames) { String attribute = element.getAttribute(attributeName); - builder.addPropertyValue(attributeName, attribute); + if (StringUtils.hasText(attribute)) { + builder.addPropertyValue(attributeName, attribute); + } else { + parserContext.getReaderContext().error("A " + attributeName + " must be supplied on a resource element of type " + type, element); + } } } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/TestInvalidResourceBeanDefinitionParser.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/TestInvalidResourceBeanDefinitionParser.java index 8f745b7e1..61d372eda 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/TestInvalidResourceBeanDefinitionParser.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/TestInvalidResourceBeanDefinitionParser.java @@ -64,6 +64,20 @@ public void testMissingAuthorizationUriForAuthorizationCode() { loadContext("type='authorization_code' access-token-uri='http://somewhere.com/'"); } + @Test + public void testMissingUsernameForPassword() { + expected.expect(BeanDefinitionParsingException.class); + expected.expectMessage("A username must be supplied on a resource element of type password"); + loadContext("type='password' access-token-uri='http://somewhere.com/'"); + } + + @Test + public void testMissingPasswordForPassword() { + expected.expect(BeanDefinitionParsingException.class); + expected.expectMessage("A password must be supplied on a resource element of type password"); + loadContext("type='password' username='admin' access-token-uri='http://somewhere.com/'"); + } + private void loadContext(String attributes) { String config = HEADER + String.format(TEMPLATE, attributes) + FOOTER; context = new GenericXmlApplicationContext(new ByteArrayResource(config .getBytes())); From 9d9768ecde14f59ac9582623fd12681e27df8081 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 5 Jun 2013 08:42:15 +0100 Subject: [PATCH 050/831] Update versions to 1.1.0 --- pom.xml | 2 +- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index 16e33b52b..df816be2d 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ OAuth for Spring Security Parent Project for OAuth Support for Spring Security pom - 1.0.6.BUILD-SNAPSHOT + 1.1.0.BUILD-SNAPSHOT http://static.springframework.org/spring-security/oauth diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index bc9954ee8..d737c63c9 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 - 1.0.6.BUILD-SNAPSHOT + 1.1.0.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index f24227992..485eaf1fe 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 - 1.0.6.BUILD-SNAPSHOT + 1.1.0.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 75e8f8a2e..a08bb0f15 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 - 1.0.6.BUILD-SNAPSHOT + 1.1.0.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 95bf59596..466cdc8e1 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 1.0.6.BUILD-SNAPSHOT + 1.1.0.BUILD-SNAPSHOT ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index b742fbc86..643c02272 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 1.0.6.BUILD-SNAPSHOT + 1.1.0.BUILD-SNAPSHOT spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index d6ba7881b..36cc0a83a 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 - 1.0.6.BUILD-SNAPSHOT + 1.1.0.BUILD-SNAPSHOT spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 10e0e40ae..24c90d12b 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 - 1.0.6.BUILD-SNAPSHOT + 1.1.0.BUILD-SNAPSHOT spring-security-oauth2 From 4f577389b3061a1527833e6db8e01d4acb2bdb05 Mon Sep 17 00:00:00 2001 From: Amanda Anganes Date: Fri, 5 Apr 2013 13:31:22 -0400 Subject: [PATCH 051/831] Major refactor or authorization and token requests * Untangles AuthorizationEndpoint and changed UserApprovalHandler to use two methods for the two different situations during which it is called * Replaces AuthorizationRequest with OAuth2Request * Moved validateScope into its own interface, with a default implementation --- .../AuthorizationCodeAccessTokenProvider.java | 10 +- .../oauth2/common/util/OAuth2Utils.java | 2 +- ...thorizationServerBeanDefinitionParser.java | 28 +- .../oauth2/provider/AuthorizationRequest.java | 53 --- .../provider/AuthorizationRequestManager.java | 56 --- .../provider/CompositeTokenGranter.java | 4 +- .../provider/DefaultAuthorizationRequest.java | 257 ---------- .../DefaultAuthorizationRequestManager.java | 91 ---- .../provider/DefaultOAuth2RequestFactory.java | 63 +++ .../DefaultOAuth2RequestValidator.java | 30 ++ .../oauth2/provider/OAuth2Authentication.java | 6 +- .../oauth2/provider/OAuth2Request.java | 439 ++++++++++++++++++ .../oauth2/provider/OAuth2RequestFactory.java | 41 ++ .../provider/OAuth2RequestValidator.java | 25 + .../oauth2/provider/TokenGranter.java | 2 +- .../approval/DefaultUserApprovalHandler.java | 25 +- .../TokenServicesUserApprovalHandler.java | 28 +- .../approval/UserApprovalHandler.java | 44 +- .../OAuth2AuthenticationManager.java | 4 +- .../client/ClientCredentialsTokenGranter.java | 6 +- .../code/AuthorizationCodeTokenGranter.java | 33 +- .../code/AuthorizationRequestHolder.java | 20 +- .../provider/endpoint/AbstractEndpoint.java | 26 +- .../endpoint/AuthorizationEndpoint.java | 242 +++++----- .../FrameworkEndpointHandlerMapping.java | 10 +- .../provider/endpoint/TokenEndpoint.java | 35 +- .../TokenEndpointAuthenticationFilter.java | 29 +- .../expression/OAuth2ExpressionUtils.java | 6 +- .../implicit/ImplicitTokenGranter.java | 4 +- .../ResourceOwnerPasswordTokenGranter.java | 24 +- .../provider/refresh/RefreshTokenGranter.java | 8 +- .../provider/token/AbstractTokenGranter.java | 24 +- .../AuthorizationServerTokenServices.java | 4 +- .../DefaultAuthenticationKeyGenerator.java | 4 +- .../provider/token/DefaultTokenServices.java | 14 +- .../oauth2/provider/vote/ScopeVoter.java | 8 +- ...2ClientAuthenticationProcessingFilter.java | 6 +- ...tAuthorizationServerCustomGrantParser.java | 4 +- .../provider/TestAuthorizationRequest.java | 146 ++++++ .../TestDefaultAuthorizationRequest.java | 92 ++-- ...estDefaultAuthorizationRequestManager.java | 6 +- .../provider/TestOAuth2Authentication.java | 2 +- .../TestDefaultUserApprovalHandler.java | 6 +- .../TestTokenServicesUserApprovalHandler.java | 16 +- .../TestOAuth2AuthenticationManager.java | 6 +- ...tOAuth2AuthenticationProcessingFilter.java | 6 +- .../TestAuthorizationCodeServicesBase.java | 8 +- .../TestAuthorizationCodeTokenGranter.java | 80 ++-- .../code/TestAuthorizationRequestHolder.java | 4 +- .../endpoint/TestAuthorizationEndpoint.java | 241 ++++++---- .../provider/endpoint/TestTokenEndpoint.java | 44 +- ...TestTokenEndpointAuthenticationFilter.java | 24 +- .../TestWhitelabelApprovalEndpoint.java | 16 +- ...OAuth2MethodSecurityExpressionHandler.java | 15 +- .../TestOAuth2SecurityExpressionMethods.java | 23 +- ...estOAuth2WebSecurityExpressionHandler.java | 9 +- ...TestResourceOwnerPasswordTokenGranter.java | 27 +- .../AbstractTestDefaultTokenServices.java | 20 +- .../TestDefaultTokenServicesWithInMemory.java | 14 +- .../token/TestInMemoryTokenStore.java | 8 +- .../provider/token/TestTokenStoreBase.java | 44 +- .../oauth2/provider/vote/TestScopeVoter.java | 13 +- .../config/authorization-server-extras.xml | 4 +- 63 files changed, 1512 insertions(+), 1077 deletions(-) delete mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java delete mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequestManager.java delete mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequest.java delete mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequestManager.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestFactory.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestValidator.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestFactory.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestValidator.java create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationRequest.java diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProvider.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProvider.java index ab72bad1c..c5779ec3f 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProvider.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProvider.java @@ -57,7 +57,7 @@ import org.springframework.security.oauth2.common.OAuth2RefreshToken; import org.springframework.security.oauth2.common.exceptions.InvalidRequestException; import org.springframework.security.oauth2.common.util.OAuth2Utils; -import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.ResponseExtractor; @@ -96,9 +96,9 @@ public String obtainAuthorizationCode(OAuth2ProtectedResourceDetails details, Ac HttpHeaders headers = getHeadersForTokenRequest(request); MultiValueMap form = new LinkedMultiValueMap(); - if (request.containsKey(AuthorizationRequest.USER_OAUTH_APPROVAL)) { - form.set(AuthorizationRequest.USER_OAUTH_APPROVAL, - request.getFirst(AuthorizationRequest.USER_OAUTH_APPROVAL)); + if (request.containsKey(OAuth2Request.USER_OAUTH_APPROVAL)) { + form.set(OAuth2Request.USER_OAUTH_APPROVAL, + request.getFirst(OAuth2Request.USER_OAUTH_APPROVAL)); } else { form.putAll(getParametersForAuthorizeRequest(resource, request)); @@ -320,7 +320,7 @@ protected UserApprovalRequiredException getUserApprovalSignal(AuthorizationCodeR String message = String.format("Do you approve the client '%s' to access your resources with scope=%s", resource.getClientId(), resource.getScope()); return new UserApprovalRequiredException(resource.getUserAuthorizationUri(), Collections.singletonMap( - AuthorizationRequest.USER_OAUTH_APPROVAL, message), resource.getClientId(), resource.getScope()); + OAuth2Request.USER_OAUTH_APPROVAL, message), resource.getClientId(), resource.getScope()); } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/OAuth2Utils.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/OAuth2Utils.java index a5ab3fc19..7d91cab78 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/OAuth2Utils.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/OAuth2Utils.java @@ -46,7 +46,7 @@ public static Set parseParameterList(String values) { } return result; } - + /** * Formats a set of string values into a format appropriate for sending as a single-valued form value. * diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/AuthorizationServerBeanDefinitionParser.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/AuthorizationServerBeanDefinitionParser.java index 1c4c419f2..53d42a024 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/AuthorizationServerBeanDefinitionParser.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/AuthorizationServerBeanDefinitionParser.java @@ -25,7 +25,7 @@ import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.security.config.BeanIds; import org.springframework.security.oauth2.provider.CompositeTokenGranter; -import org.springframework.security.oauth2.provider.DefaultAuthorizationRequestManager; +import org.springframework.security.oauth2.provider.DefaultOAuth2RequestFactory; import org.springframework.security.oauth2.provider.approval.DefaultUserApprovalHandler; import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenGranter; import org.springframework.security.oauth2.provider.code.AuthorizationCodeTokenGranter; @@ -54,7 +54,7 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P String tokenServicesRef, String serializerRef) { String clientDetailsRef = element.getAttribute("client-details-service-ref"); - String authorizationRequestManagerRef = element.getAttribute("authorization-request-manager-ref"); + String oAuth2RequestFactoryRef = element.getAttribute("authorization-request-manager-ref"); String tokenEndpointUrl = element.getAttribute("token-endpoint-url"); String authorizationEndpointUrl = element.getAttribute("authorization-endpoint-url"); String tokenGranterRef = element.getAttribute("token-granter-ref"); @@ -112,9 +112,9 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P if (StringUtils.hasText(clientTokenCacheRef)) { authorizationEndpointBean.addPropertyReference("clientTokenCache", clientTokenCacheRef); } - if (StringUtils.hasText(authorizationRequestManagerRef)) { - authorizationEndpointBean.addPropertyReference("authorizationRequestManager", - authorizationRequestManagerRef); + if (StringUtils.hasText(oAuth2RequestFactoryRef)) { + authorizationEndpointBean.addPropertyReference("oAuth2RequestFactory", + oAuth2RequestFactoryRef); } if (tokenGranters != null) { @@ -124,13 +124,13 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P registerAuthorizationEndpoint = true; } - if (!StringUtils.hasText(authorizationRequestManagerRef)) { - authorizationRequestManagerRef = "oauth2AuthorizationRequestManager"; - BeanDefinitionBuilder authorizationRequestManager = BeanDefinitionBuilder - .rootBeanDefinition(DefaultAuthorizationRequestManager.class); - authorizationRequestManager.addConstructorArgReference(clientDetailsRef); - parserContext.getRegistry().registerBeanDefinition(authorizationRequestManagerRef, - authorizationRequestManager.getBeanDefinition()); + if (!StringUtils.hasText(oAuth2RequestFactoryRef)) { + oAuth2RequestFactoryRef = "oAuth2AuthorizationRequestManager"; + BeanDefinitionBuilder oAuth2RequestManager = BeanDefinitionBuilder + .rootBeanDefinition(DefaultOAuth2RequestFactory.class); + oAuth2RequestManager.addConstructorArgReference(clientDetailsRef); + parserContext.getRegistry().registerBeanDefinition(oAuth2RequestFactoryRef, + oAuth2RequestManager.getBeanDefinition()); } if (tokenGranters != null) { @@ -223,8 +223,8 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P tokenEndpointBean.addPropertyReference("tokenGranter", tokenGranterRef); parserContext.getRegistry() .registerBeanDefinition("oauth2TokenEndpoint", tokenEndpointBean.getBeanDefinition()); - if (StringUtils.hasText(authorizationRequestManagerRef)) { - tokenEndpointBean.addPropertyReference("authorizationRequestManager", authorizationRequestManagerRef); + if (StringUtils.hasText(oAuth2RequestFactoryRef)) { + tokenEndpointBean.addPropertyReference("oAuth2RequestFactory", oAuth2RequestFactoryRef); } // Register a handler mapping that can detect the auth server endpoints diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java deleted file mode 100644 index 85f6f0c87..000000000 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.springframework.security.oauth2.provider; - -import java.util.Collection; -import java.util.Map; -import java.util.Set; - -import org.springframework.security.core.GrantedAuthority; - -/** - * Base class representing a request for authorization. There are convenience methods for the well-known properties - * required by the OAUth2 spec, and a set of generic authorizationParameters to allow for extensions. - * - * @author Ryan Heaton - * @author Dave Syer - * @author Amanda Anganes - */ -public interface AuthorizationRequest { - - public static final String CLIENT_ID = "client_id"; - - public static final String STATE = "state"; - - public static final String SCOPE = "scope"; - - public static final String REDIRECT_URI = "redirect_uri"; - - public static final String RESPONSE_TYPE = "response_type"; - - public static final String USER_OAUTH_APPROVAL = "user_oauth_approval"; - - public Map getAuthorizationParameters(); - - public Map getApprovalParameters(); - - public String getClientId(); - - public Set getScope(); - - public Set getResourceIds(); - - public Collection getAuthorities(); - - public boolean isApproved(); - - public boolean isDenied(); - - public String getState(); - - public String getRedirectUri(); - - public Set getResponseTypes(); - -} \ No newline at end of file diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequestManager.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequestManager.java deleted file mode 100644 index 48c61a71e..000000000 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequestManager.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2006-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; - -import java.util.Map; - -import org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint; -import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint; - -/** - * Strategy for managing AuthorizationRequest instances during a token grant. - * - * @author Dave Syer - * - */ -public interface AuthorizationRequestManager { - - /** - * Create a new {@link AuthorizationRequest} extracting all the needed information from the incoming parameter map. - * Typical implementations would load the client details from the client id provided and validate the grant type and - * scopes, populating any fields in the request that are known only to the authorization server. - * - * @param authorizationParameters the parameters in the request - * @return a new AuthorizationRequest - */ - AuthorizationRequest createAuthorizationRequest(Map authorizationParameters); - - /** - *

- * Validate the parameters provided by the client. Called by the {@link AuthorizationEndpoint} and also by the - * {@link TokenEndpoint} before a response is sent back to the client. Note that during an authorization code flow - * both endpoints will call this method, but the TokenEndpoint in that case has very little if anything to validate - * since all the parameters neeeded for the access token were provided to the AuthorizationEndpoint. - *

- * - *

- * Implementations should at a minimum check that the scope values requested are legal for the client. - *

- * - * @param parameters the request parameters - * @param clientDetails the client requesting the token - */ - void validateParameters(Map parameters, ClientDetails clientDetails); - -} \ No newline at end of file diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/CompositeTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/CompositeTokenGranter.java index b820f4b48..7c1ab4656 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/CompositeTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/CompositeTokenGranter.java @@ -33,9 +33,9 @@ public CompositeTokenGranter(List tokenGranters) { this.tokenGranters = new ArrayList(tokenGranters); } - public OAuth2AccessToken grant(String grantType, AuthorizationRequest authorizationRequest) { + public OAuth2AccessToken grant(String grantType, OAuth2Request tokenRequest) { for (TokenGranter granter : tokenGranters) { - OAuth2AccessToken grant = granter.grant(grantType, authorizationRequest); + OAuth2AccessToken grant = granter.grant(grantType, tokenRequest); if (grant!=null) { return grant; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequest.java deleted file mode 100644 index db568d9fe..000000000 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequest.java +++ /dev/null @@ -1,257 +0,0 @@ -package org.springframework.security.oauth2.provider; - -import java.io.Serializable; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.oauth2.common.util.OAuth2Utils; -import org.springframework.util.StringUtils; - -/** - * Base class representing a request for authorization. There are convenience methods for the well-known properties - * required by the OAuth2 spec, and a set of generic authorizationParameters to allow for extensions. - * - * @author Ryan Heaton - * @author Dave Syer - * @author Amanda Anganes - */ -public class DefaultAuthorizationRequest implements AuthorizationRequest, Serializable { - - private Set scope = new LinkedHashSet(); - - private Set resourceIds = new HashSet(); - - private boolean approved = false; - - private Collection authorities = new HashSet(); - - private Map authorizationParameters = new ConcurrentHashMap(); - - private Map approvalParameters = new HashMap(); - - private String resolvedRedirectUri; - - public DefaultAuthorizationRequest(Map authorizationParameters) { - this(authorizationParameters, Collections. emptyMap(), authorizationParameters.get(CLIENT_ID), - OAuth2Utils.parseParameterList(authorizationParameters.get("scope")), null, null, false); - } - - public DefaultAuthorizationRequest(Map authorizationParameters, - Map approvalParameters, String clientId, Collection scope) { - this(authorizationParameters, approvalParameters, clientId, scope, null, null, false); - } - - public DefaultAuthorizationRequest(String clientId, Collection scope) { - this(null, null, clientId, scope, null, null, false); - } - - public DefaultAuthorizationRequest(AuthorizationRequest copy) { - this(copy.getAuthorizationParameters(), copy.getApprovalParameters(), copy.getClientId(), copy.getScope(), copy - .getAuthorities(), copy.getResourceIds(), copy.isApproved()); - setRedirectUri(copy.getRedirectUri()); - if (!scope.isEmpty()) { - this.authorizationParameters.put(SCOPE, OAuth2Utils.formatParameterList(scope)); - } - } - - private DefaultAuthorizationRequest(Map authorizationParameters, - Map approvalParameters, String clientId, Collection scope, - Collection authorities, Collection resourceIds, boolean approved) { - if (authorizationParameters != null) { - this.authorizationParameters.putAll(authorizationParameters); - } - if (approvalParameters != null) { - this.approvalParameters.putAll(approvalParameters); - } - if (resourceIds != null) { - this.resourceIds = new HashSet(resourceIds); - } - if (scope != null) { - this.scope = new LinkedHashSet(scope); - } - if (authorities != null) { - this.authorities = new HashSet(authorities); - } - if (clientId != null) { - this.authorizationParameters.put(CLIENT_ID, clientId); - } - String scopes = OAuth2Utils.formatParameterList(scope); - if (scopes != null) { - this.authorizationParameters.put(SCOPE, scopes); - } - this.approved = approved; - } - - public Map getAuthorizationParameters() { - return Collections.unmodifiableMap(authorizationParameters); - } - - public Map getApprovalParameters() { - return Collections.unmodifiableMap(approvalParameters); - } - - public String getClientId() { - return authorizationParameters.get(CLIENT_ID); - } - - public Set getScope() { - return Collections.unmodifiableSet(this.scope); - } - - public Set getResourceIds() { - return Collections.unmodifiableSet(resourceIds); - } - - public Collection getAuthorities() { - return Collections.unmodifiableSet((Set) authorities); - } - - public boolean isApproved() { - return approved; - } - - public boolean isDenied() { - return !approved; - } - - public String getState() { - return authorizationParameters.get(STATE); - } - - public String getRedirectUri() { - return resolvedRedirectUri == null ? authorizationParameters.get(REDIRECT_URI) : resolvedRedirectUri; - } - - public Set getResponseTypes() { - return OAuth2Utils.parseParameterList(authorizationParameters.get(RESPONSE_TYPE)); - } - - public void setRedirectUri(String redirectUri) { - this.resolvedRedirectUri = redirectUri; - } - - public void addClientDetails(ClientDetails clientDetails) { - resourceIds.addAll(clientDetails.getResourceIds()); - authorities.addAll(clientDetails.getAuthorities()); - } - - public void setScope(Set scope) { - if (scope != null && scope.size() == 1) { - String value = scope.iterator().next(); - /* - * This is really an error, but it can catch out unsuspecting users and it's easy to fix. It happens when an - * AuthorizationRequest gets bound accidentally from request parameters using @ModelAttribute. - */ - if (value.contains(" ") || scope.contains(",")) { - scope = OAuth2Utils.parseParameterList(value); - } - } - this.scope = scope == null ? new LinkedHashSet() : new LinkedHashSet(scope); - authorizationParameters.put(SCOPE, OAuth2Utils.formatParameterList(scope)); - } - - public void setResourceIds(Set resourceIds) { - this.resourceIds = resourceIds == null ? new HashSet() : new HashSet(resourceIds); - } - - public void setApproved(boolean approved) { - this.approved = approved; - } - - public void setAuthorities(Collection authorities) { - this.authorities = authorities == null ? new HashSet() : new HashSet( - authorities); - } - - public void setAuthorizationParameters(Map authorizationParameters) { - String clientId = getClientId(); - Set scope = getScope(); - this.authorizationParameters = authorizationParameters == null ? new HashMap() - : new HashMap(authorizationParameters); - if (!authorizationParameters.containsKey(CLIENT_ID) && clientId != null) { - this.authorizationParameters.put(CLIENT_ID, clientId); - } - if (StringUtils.hasText(authorizationParameters.get(SCOPE))) { - setScope(OAuth2Utils.parseParameterList(authorizationParameters.get(SCOPE))); - } - else { - setScope(scope); - } - } - - public void setApprovalParameters(Map approvalParameters) { - this.approvalParameters = approvalParameters == null ? new HashMap() - : new HashMap(approvalParameters); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((authorities == null) ? 0 : authorities.hashCode()); - result = prime * result + (approved ? 1231 : 1237); - result = prime * result + ((authorizationParameters == null) ? 0 : authorizationParameters.hashCode()); - result = prime * result + ((approvalParameters == null) ? 0 : approvalParameters.hashCode()); - result = prime * result + ((resourceIds == null) ? 0 : resourceIds.hashCode()); - result = prime * result + ((scope == null) ? 0 : scope.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - DefaultAuthorizationRequest other = (DefaultAuthorizationRequest) obj; - if (authorities == null) { - if (other.authorities != null) - return false; - } - else if (!authorities.equals(other.authorities)) - return false; - if (approved != other.approved) - return false; - if (authorizationParameters == null) { - if (other.authorizationParameters != null) - return false; - } - else if (!authorizationParameters.equals(other.authorizationParameters)) - return false; - if (resourceIds == null) { - if (other.resourceIds != null) - return false; - } - else if (!resourceIds.equals(other.resourceIds)) - return false; - if (scope == null) { - if (other.scope != null) - return false; - } - else if (!scope.equals(other.scope)) - return false; - if (approvalParameters == null) { - if (other.approvalParameters != null) - return false; - } - else if (!approvalParameters.equals(other.approvalParameters)) - return false; - return true; - } - - public void remove(Collection keys) { - for (String key : keys) { - authorizationParameters.remove(key); - } - } - -} \ No newline at end of file diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequestManager.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequestManager.java deleted file mode 100644 index 2322d456f..000000000 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequestManager.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2006-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; - -import java.util.Collections; -import java.util.Map; -import java.util.Set; - -import org.springframework.security.oauth2.common.exceptions.InvalidClientException; -import org.springframework.security.oauth2.common.exceptions.InvalidScopeException; -import org.springframework.security.oauth2.common.util.OAuth2Utils; - -/** - * Default implementation of {@link AuthorizationRequestManager} which validates grant types and scopes and fills in - * scopes with the default values from the client if they are missing. - * - * @author Dave Syer - * - */ -public class DefaultAuthorizationRequestManager implements AuthorizationRequestManager { - - private final ClientDetailsService clientDetailsService; - - private boolean revealValidScopes = false; - - /** - * Flag to indicate that when an invalid scope is requested, the valid values should be revealed in the exception - * (which is then seen by the client). Default false; - * - * @param revealValidScopes the revealValidScopes to set - */ - public void setRevealValidScopes(boolean revealValidScopes) { - this.revealValidScopes = revealValidScopes; - } - - public DefaultAuthorizationRequestManager(ClientDetailsService clientDetailsService) { - this.clientDetailsService = clientDetailsService; - } - - public AuthorizationRequest createAuthorizationRequest(Map parameters) { - - String clientId = parameters.get("client_id"); - if (clientId == null) { - throw new InvalidClientException("A client id must be provided"); - } - ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId); - Set scopes = OAuth2Utils.parseParameterList(parameters.get("scope")); - if ((scopes == null || scopes.isEmpty())) { - // If no scopes are specified in the incoming data, use the default values registered with the client - // (the spec allows us to choose between this option and rejecting the request completely, so we'll take the - // least obnoxious choice as a default). - scopes = clientDetails.getScope(); - } - DefaultAuthorizationRequest request = new DefaultAuthorizationRequest(parameters, - Collections. emptyMap(), clientId, scopes); - request.addClientDetails(clientDetails); - return request; - - } - - public void validateParameters(Map parameters, ClientDetails clientDetails) { - if (parameters.containsKey("scope")) { - if (clientDetails.isScoped()) { - Set validScope = clientDetails.getScope(); - for (String scope : OAuth2Utils.parseParameterList(parameters.get("scope"))) { - if (!validScope.contains(scope)) { - InvalidScopeException exception; - if (revealValidScopes) { - exception = new InvalidScopeException("Invalid scope: " + scope, validScope); - } - else { - exception = new InvalidScopeException("Invalid scope: " + scope); - } - throw exception; - } - } - } - } - } - -} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestFactory.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestFactory.java new file mode 100644 index 000000000..447d632ed --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestFactory.java @@ -0,0 +1,63 @@ +/* + * Copyright 2006-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; + +import java.util.Collections; +import java.util.Map; +import java.util.Set; + +import org.springframework.security.oauth2.common.util.OAuth2Utils; + +/** + * Default implementation of {@link OAuth2RequestFactory} which initializes fields from the parameters map, + * validates grant types and scopes, and fills in scopes with the default values from the client if they are missing. + * + * @author Dave Syer + * @author Amanda Anganes + * + */ +public class DefaultOAuth2RequestFactory implements OAuth2RequestFactory { + + private final ClientDetailsService clientDetailsService; + + public DefaultOAuth2RequestFactory(ClientDetailsService clientDetailsService) { + this.clientDetailsService = clientDetailsService; + } + + public OAuth2Request createOAuth2Request(Map authorizationParameters) { + + String clientId = authorizationParameters.get(OAuth2Request.CLIENT_ID); + Set scopes = OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Request.SCOPE)); + String state = authorizationParameters.get(OAuth2Request.STATE); + String redirectUri = authorizationParameters.get(OAuth2Request.REDIRECT_URI); + Set responseTypes = OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Request.RESPONSE_TYPE)); + + ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId); + + if ((scopes == null || scopes.isEmpty())) { + // If no scopes are specified in the incoming data, use the default values registered with the client + // (the spec allows us to choose between this option and rejecting the request completely, so we'll take the + // least obnoxious choice as a default). + scopes = clientDetails.getScope(); + } + + OAuth2Request request = new OAuth2Request(authorizationParameters, Collections. emptyMap(), + clientId, scopes, null, null, false, state, redirectUri, responseTypes); + + request.setResourceIdsAndAuthoritiesFromClientDetails(clientDetails); + + return request; + + } + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestValidator.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestValidator.java new file mode 100644 index 000000000..d1a5e6226 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestValidator.java @@ -0,0 +1,30 @@ +package org.springframework.security.oauth2.provider; + +import java.util.Map; +import java.util.Set; + +import org.springframework.security.oauth2.common.exceptions.InvalidScopeException; +import org.springframework.security.oauth2.common.util.OAuth2Utils; + +/** + * Default implementation of {@link OAuth2RequestValidator}. + * + * @author Amanda Anganes + * + */ +public class DefaultOAuth2RequestValidator implements OAuth2RequestValidator { + + + public void validateScope(Map parameters, Set clientScopes) { + if (parameters.containsKey("scope")) { + if (clientScopes != null && !clientScopes.isEmpty()) { + for (String scope : OAuth2Utils.parseParameterList(parameters.get("scope"))) { + if (!clientScopes.contains(scope)) { + throw new InvalidScopeException("Invalid scope: " + scope, clientScopes); + } + } + } + } + } + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Authentication.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Authentication.java index dfad67932..ab0e5c3e3 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Authentication.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Authentication.java @@ -13,7 +13,7 @@ public class OAuth2Authentication extends AbstractAuthenticationToken { private static final long serialVersionUID = -4809832298438307309L; - private final AuthorizationRequest clientAuthentication; + private final OAuth2Request clientAuthentication; private final Authentication userAuthentication; @@ -24,7 +24,7 @@ public class OAuth2Authentication extends AbstractAuthenticationToken { * @param authorizationRequest The authorization request (must not be null). * @param userAuthentication The user authentication (possibly null). */ - public OAuth2Authentication(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { + public OAuth2Authentication(OAuth2Request authorizationRequest, Authentication userAuthentication) { super(userAuthentication == null ? authorizationRequest.getAuthorities() : userAuthentication.getAuthorities()); this.clientAuthentication = authorizationRequest; this.userAuthentication = userAuthentication; @@ -53,7 +53,7 @@ public boolean isClientOnly() { * * @return The client authentication. */ - public AuthorizationRequest getAuthorizationRequest() { + public OAuth2Request getAuthorizationRequest() { return clientAuthentication; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java new file mode 100644 index 000000000..8ac4b99ab --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java @@ -0,0 +1,439 @@ +package org.springframework.security.oauth2.provider; + +import java.io.Serializable; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.oauth2.common.util.OAuth2Utils; + +/** + * Base class representing an OAuth2 authorization or token request. HTTP request parameters are stored in + * the parameters map, and any processing the server makes throughout the lifecycle of a request are stored + * on individual properties. The original request parameters will remain available through the parameters + * map. For convenience, constants are defined in order to get at those original values. However, the + * parameters map is unmodifiable so that processing cannot drop the original values. + * + * @author Ryan Heaton + * @author Dave Syer + * @author Amanda Anganes + */ +public class OAuth2Request implements Serializable { + + private static final long serialVersionUID = 1L; + + public static final String CLIENT_ID = "client_id"; + + public static final String STATE = "state"; + + public static final String SCOPE = "scope"; + + public static final String REDIRECT_URI = "redirect_uri"; + + public static final String RESPONSE_TYPE = "response_type"; + + public static final String USER_OAUTH_APPROVAL = "user_oauth_approval"; + + /** + * Map of parameters passed in to the Authorizatoin Endpoint or Token + * Endpoint, preserved unchanged from the original request. This map should + * not be modified after initialization. In general, classes should not + * retrieve values from this map directly, and should instead use the + * individual members on this class. + * + * The OAuth2RequestFactory is responsible for initializing all members of + * this class, usually by parsing the values inside the requestParmaeters + * map. + * + */ + private Map requestParameters = Collections.unmodifiableMap(new HashMap()); + + /** + * Map to hold the original, unchanged parameter set returned from the + * Approval Endpoint. Once set this should not be modified. + */ + private Map approvalParameters = Collections.unmodifiableMap(new HashMap()); + + /** + * Resolved client ID. This may be present in the original request + * parameters, or in some cases may be inferred by a processing class and + * inserted here. + */ + private String clientId; + + /** + * Resolved scope set, initialized (by the OAuth2RequestFactory) with the + * scopes originally requested. Further processing and user interaction may + * alter the set of scopes that is finally granted and stored when the + * request processing is complete. + */ + private Set scope = new HashSet(); + + /** + * Resolved resource IDs. This set may change during request processing. + */ + private Set resourceIds = new HashSet(); + + /** + * Resolved granted authorities for this request. May change during request + * processing. + */ + private Collection authorities = new HashSet(); + + /** + * Whether the request has been approved by the end user (or other process). + * This will be altered by the User Approval Endpoint and/or the + * UserApprovalHandler as appropriate. + */ + private boolean approved = false; + + /** + * The value of the "state" parameter sent by the client in the request, if + * sent by the client. As this must be echoed back to the client unchanged, + * it should not be modified by any processing classes. + */ + private String state; + + /** + * The resolved redirect URI of this request. A URI may be present in the + * original request, in the authorizationParameters, or it may not be + * provided, in which case it will be defaulted (by processing classes) to + * the Client's default registered value. + */ + private String resolvedRedirectUri; + + /** + * Resolved requested response types initialized (by the + * OAuth2RequestFactory) with the response types originally requested. + */ + private Set responseTypes = new HashSet(); + + /** + * Extension point for custom processing classes which may wish to store + * additional information about the OAuth2 request. Since this class is + * serializable, all members of this map must also be serializable. + */ + private Map extensionProperties = new HashMap(); + + /** + * Default constructor. + */ + public OAuth2Request() { + + } + + /** + * Full constructor. + * + * @param authorizationParameters + * @param approvalParameters + * @param clientId + * @param scope + * @param resourceIds + * @param authorities + * @param approved + * @param state + * @param redirectUri + * @param responseTypes + */ + public OAuth2Request(Map authorizationParameters, Map approvalParameters, + String clientId, Set scope, Set resourceIds, + Collection authorities, boolean approved, String state, + String redirectUri, Set responseTypes){ + if (authorizationParameters != null) { + //this.authorizationParameters.putAll(authorizationParameters); + this.requestParameters = Collections.unmodifiableMap(authorizationParameters); + } + if (approvalParameters != null) { + this.approvalParameters = Collections.unmodifiableMap(approvalParameters); + } + if (resourceIds != null) { + this.resourceIds = new HashSet(resourceIds); + } + if (scope != null) { + this.scope = new LinkedHashSet(scope); + } + if (authorities != null) { + this.authorities = new HashSet(authorities); + } + if (responseTypes != null) { + this.responseTypes = responseTypes; + } + this.resolvedRedirectUri = redirectUri; + this.state = state; + this.clientId = clientId; + this.approved = approved; + } + + /** + * Convenience constructor for unit tests, where client ID and scope are often + * the only needed fields. + * + * @param clientId + * @param scopes + */ + public OAuth2Request(String clientId, Collection scopes) { + this.clientId = clientId; + if (scopes!= null) { + this.scope.addAll(scopes); + } + } + + /** + * Convenience method to set resourceIds and authorities on this request by + * inheriting from a ClientDetails object. + * + * @param clientDetails + */ + public void setResourceIdsAndAuthoritiesFromClientDetails(ClientDetails clientDetails) { + resourceIds.addAll(clientDetails.getResourceIds()); + authorities.addAll(clientDetails.getAuthorities()); + } + + /** + * Warning: most classes should use the individual properties of this class, such + * as {{@link #getScope()} or {{@link #getClientId()}, rather than retrieving values from this map. + * + * @return the original, unchanged set of request parameters + */ + public Map getRequestParameters() { + return requestParameters; + } + + /** + * Warning: most classes should not alter this map after it has been initialized. + * + * @param requestParameters the original, unchanged set of request parameters to set + */ + public void setRequestParameters( + Map requestParameters) { + this.requestParameters = Collections.unmodifiableMap(requestParameters); + } + + public Map getApprovalParameters() { + return approvalParameters; + } + + public void setApprovalParameters(Map approvalParameters) { + this.approvalParameters = approvalParameters; + } + + public String getClientId() { + return clientId; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + public Set getScope() { + return scope; + } + + //TODO: remove parser and do intensive wiretesting to see if this is really needed + public void setScope(Set scope) { + if (scope != null && scope.size() == 1) { + String value = scope.iterator().next(); + /* + * This is really an error, but it can catch out unsuspecting users and it's easy to fix. It happens when an + * AuthorizationRequest gets bound accidentally from request parameters using @ModelAttribute. + */ + if (value.contains(" ") || scope.contains(",")) { + scope = OAuth2Utils.parseParameterList(value); + } + } + this.scope = scope == null ? new LinkedHashSet() : new LinkedHashSet(scope); + } + + public Set getResourceIds() { + return resourceIds; + } + + public void setResourceIds(Set resourceIds) { + this.resourceIds = resourceIds; + } + + public Collection getAuthorities() { + return authorities; + } + + public void setAuthorities(Collection authorities) { + if (authorities!= null) { + this.authorities = new HashSet(authorities); + } + } + + public boolean isApproved() { + return approved; + } + + public void setApproved(boolean approved) { + this.approved = approved; + } + + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } + + public String getRedirectUri() { + return resolvedRedirectUri; + } + + public void setRedirectUri(String redirectUri) { + this.resolvedRedirectUri = redirectUri; + } + + public Set getResponseTypes() { + return responseTypes; + } + + public void setResponseTypes(Set responseTypes) { + this.responseTypes = responseTypes; + } + + /** + * @return the extensionProperties + */ + public Map getExtensionProperties() { + return extensionProperties; + } + + /** + * @param extensionProperties the extensionProperties to set + */ + public void setExtensionProperties(Map extensionProperties) { + this.extensionProperties = extensionProperties; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime + * result + + ((approvalParameters == null) ? 0 : approvalParameters + .hashCode()); + result = prime * result + (approved ? 1231 : 1237); + result = prime * result + + ((authorities == null) ? 0 : authorities.hashCode()); + result = prime * result + + ((clientId == null) ? 0 : clientId.hashCode()); + result = prime + * result + + ((extensionProperties == null) ? 0 : extensionProperties + .hashCode()); + result = prime + * result + + ((requestParameters == null) ? 0 : requestParameters + .hashCode()); + result = prime + * result + + ((resolvedRedirectUri == null) ? 0 : resolvedRedirectUri + .hashCode()); + result = prime * result + + ((resourceIds == null) ? 0 : resourceIds.hashCode()); + result = prime * result + + ((responseTypes == null) ? 0 : responseTypes.hashCode()); + result = prime * result + ((scope == null) ? 0 : scope.hashCode()); + result = prime * result + ((state == null) ? 0 : state.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof OAuth2Request)) { + return false; + } + OAuth2Request other = (OAuth2Request) obj; + if (approvalParameters == null) { + if (other.approvalParameters != null) { + return false; + } + } else if (!approvalParameters.equals(other.approvalParameters)) { + return false; + } + if (approved != other.approved) { + return false; + } + if (authorities == null) { + if (other.authorities != null) { + return false; + } + } else if (!authorities.equals(other.authorities)) { + return false; + } + if (clientId == null) { + if (other.clientId != null) { + return false; + } + } else if (!clientId.equals(other.clientId)) { + return false; + } + if (extensionProperties == null) { + if (other.extensionProperties != null) { + return false; + } + } else if (!extensionProperties.equals(other.extensionProperties)) { + return false; + } + if (requestParameters == null) { + if (other.requestParameters != null) { + return false; + } + } else if (!requestParameters.equals(other.requestParameters)) { + return false; + } + if (resolvedRedirectUri == null) { + if (other.resolvedRedirectUri != null) { + return false; + } + } else if (!resolvedRedirectUri.equals(other.resolvedRedirectUri)) { + return false; + } + if (resourceIds == null) { + if (other.resourceIds != null) { + return false; + } + } else if (!resourceIds.equals(other.resourceIds)) { + return false; + } + if (responseTypes == null) { + if (other.responseTypes != null) { + return false; + } + } else if (!responseTypes.equals(other.responseTypes)) { + return false; + } + if (scope == null) { + if (other.scope != null) { + return false; + } + } else if (!scope.equals(other.scope)) { + return false; + } + if (state == null) { + if (other.state != null) { + return false; + } + } else if (!state.equals(other.state)) { + return false; + } + return true; + } + +} \ No newline at end of file diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestFactory.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestFactory.java new file mode 100644 index 000000000..851f2115c --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestFactory.java @@ -0,0 +1,41 @@ +/* + * Copyright 2006-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; + +import java.util.Map; + +/** + * Strategy for managing OAuth2Request instances during a token grant. + * + * @author Dave Syer + * @author Amanda Anganes + * + */ +public interface OAuth2RequestFactory { + + /** + * Create a new {@link OAuth2Request} extracting all the needed information from the incoming parameter map, and + * initializing all individual fields on the {@link OAuth2Request} to reasonable values. When a class uses + * the factory to create an {@link OAuth2Request}, it should not need to access the parameter map directly afterwards. + * + * Typical implementations would initialize the individual fields on the {@link OAuth2Request} with the values + * requested in the original parameter map. It may also load the client details from the client id provided and + * validate the grant type and scopes, populating any fields in the request that are known only to the authorization server. + * + * @param authorizationParameters the parameters in the request + * @return a new OAuth2Request + */ + OAuth2Request createOAuth2Request(Map authorizationParameters); + +} \ No newline at end of file diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestValidator.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestValidator.java new file mode 100644 index 000000000..fc6214fbe --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestValidator.java @@ -0,0 +1,25 @@ +package org.springframework.security.oauth2.provider; + +import java.util.Map; +import java.util.Set; + +import org.springframework.security.oauth2.common.exceptions.InvalidScopeException; + +/** + * Validation interface for OAuth2 requests to the {@link AuthorizationEndpoint} and {@link TokenEndpoint}. + * + * @author Amanda Anganes + * + */ +public interface OAuth2RequestValidator { + + /** + * Ensure that the client has requested a valid set of scopes. + * + * @param parameters the parameters on the OAuth2Request, including scope + * @param clientScopes the requesting client's registered, allowed scopes + * @throws InvalidScopeException if a requested scope is invalid + */ + public void validateScope(Map parameters, Set clientScopes) throws InvalidScopeException; + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenGranter.java index 1e5b52513..272979985 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenGranter.java @@ -27,6 +27,6 @@ */ public interface TokenGranter { - OAuth2AccessToken grant(String grantType, AuthorizationRequest authorizationRequest); + OAuth2AccessToken grant(String grantType, OAuth2Request tokenRequest); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/DefaultUserApprovalHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/DefaultUserApprovalHandler.java index 72c8f4fb9..9d80aedbf 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/DefaultUserApprovalHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/DefaultUserApprovalHandler.java @@ -16,8 +16,10 @@ package org.springframework.security.oauth2.provider.approval; +import java.util.Map; + import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Request; /** * A default user approval handler that doesn't remember any decisions. @@ -27,7 +29,7 @@ */ public class DefaultUserApprovalHandler implements UserApprovalHandler { - private String approvalParameter = AuthorizationRequest.USER_OAUTH_APPROVAL; + private String approvalParameter = OAuth2Request.USER_OAUTH_APPROVAL; /** * @param approvalParameter the approvalParameter to set @@ -35,24 +37,29 @@ public class DefaultUserApprovalHandler implements UserApprovalHandler { public void setApprovalParameter(String approvalParameter) { this.approvalParameter = approvalParameter; } - - public AuthorizationRequest updateBeforeApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { - return authorizationRequest; - } /** * Basic implementation just requires the authorization request to be explicitly approved and the user to be * authenticated. * - * @param authorizationRequest The authorization request. + * @param oAuth2Request The authorization request. * @param userAuthentication the current user authentication * * @return Whether the specified request has been approved by the current user. */ - public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { - String flag = authorizationRequest.getApprovalParameters().get(approvalParameter); + public boolean isApproved(OAuth2Request oAuth2Request, Authentication userAuthentication) { + Map approvalParameters = oAuth2Request.getApprovalParameters(); + String flag = approvalParameters.get(approvalParameter); boolean approved = flag != null && flag.toLowerCase().equals("true"); return userAuthentication.isAuthenticated() && approved; } + public OAuth2Request checkForPreApproval(OAuth2Request oAuth2Request, Authentication userAuthentication) { + return oAuth2Request; + } + + public OAuth2Request updateAfterApproval(OAuth2Request oAuth2Request, Authentication userAuthentication) { + return oAuth2Request; + } + } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenServicesUserApprovalHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenServicesUserApprovalHandler.java index 7651cdd09..31f5a9f88 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenServicesUserApprovalHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenServicesUserApprovalHandler.java @@ -21,7 +21,7 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; import org.springframework.util.Assert; @@ -36,7 +36,7 @@ public class TokenServicesUserApprovalHandler implements UserApprovalHandler, In private static Log logger = LogFactory.getLog(TokenServicesUserApprovalHandler.class); - private String approvalParameter = AuthorizationRequest.USER_OAUTH_APPROVAL; + private String approvalParameter = OAuth2Request.USER_OAUTH_APPROVAL; /** * @param approvalParameter the approvalParameter to set @@ -58,29 +58,25 @@ public void afterPropertiesSet() { Assert.state(tokenServices != null, "AuthorizationServerTokenServices must be provided"); } - public AuthorizationRequest updateBeforeApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { - return authorizationRequest; - } - /** * Basic implementation just requires the authorization request to be explicitly approved and the user to be * authenticated. * - * @param authorizationRequest The authorization request. + * @param oAuth2Request The authorization request. * @param userAuthentication the current user authentication * * @return Whether the specified request has been approved by the current user. */ - public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { + public boolean isApproved(OAuth2Request oAuth2Request, Authentication userAuthentication) { - String flag = authorizationRequest.getApprovalParameters().get(approvalParameter); + String flag = oAuth2Request.getApprovalParameters().get(approvalParameter); boolean approved = flag != null && flag.toLowerCase().equals("true"); - OAuth2Authentication authentication = new OAuth2Authentication(authorizationRequest, userAuthentication); + OAuth2Authentication authentication = new OAuth2Authentication(oAuth2Request, userAuthentication); if (logger.isDebugEnabled()) { StringBuilder builder = new StringBuilder("Looking up existing token for "); - builder.append("client_id=" + authorizationRequest.getClientId()); - builder.append(", scope=" + authorizationRequest.getScope()); + builder.append("client_id=" + oAuth2Request.getClientId()); + builder.append(", scope=" + oAuth2Request.getScope()); builder.append(" and username=" + userAuthentication.getName()); logger.debug(builder.toString()); } @@ -100,4 +96,12 @@ public boolean isApproved(AuthorizationRequest authorizationRequest, Authenticat return approved; } + + public OAuth2Request checkForPreApproval(OAuth2Request oAuth2Request, Authentication userAuthentication) { + return oAuth2Request; + } + + public OAuth2Request updateAfterApproval(OAuth2Request oAuth2Request, Authentication userAuthentication) { + return oAuth2Request; + } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/UserApprovalHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/UserApprovalHandler.java index c9cfe1f82..e579aad33 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/UserApprovalHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/UserApprovalHandler.java @@ -1,38 +1,54 @@ package org.springframework.security.oauth2.provider.approval; import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Request; /** * Basic interface for determining whether a given client authentication request has been approved by the current user. * * @author Ryan Heaton * @author Dave Syer + * @author Amanda Anganes */ public interface UserApprovalHandler { + /** *

- * Provides an opportunity to update the authorization request before it is checked for approval in cases where the - * incoming approval parameters contain richer information than just true/false (e.g. some scopes are approved, and - * others are rejected), implementations may need to be able to modify the {@link AuthorizationRequest} before a - * token is generated from it. + * Tests whether the specified authorization request has been approved by the current user (if there is one). *

* - * @param authorizationRequest the authorization request. - * @param userAuthentication TODO - * @return a new instance or the same one if no changes are required + * @param oAuth2Request the authorization request. + * @param userAuthentication the user authentication for the current user. + * @return true if the request has been approved, false otherwise */ - AuthorizationRequest updateBeforeApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication); + boolean isApproved(OAuth2Request oAuth2Request, Authentication userAuthentication); /** *

- * Tests whether the specified authorization request has been approved by the current user (if there is one). + * Provides a hook for allowing requests to be pre-approved (skipping the User Approval Page). Some implementations + * may allow users to store approval decisions so that they only have to approve a site once. This method is called + * in the AuthorizationEndpoint before sending the user to the Approval page. If this method sets oAuth2Request.approved + * to true, the Approval page will be skipped. *

* - * @param authorizationRequest the authorization request. - * @param userAuthentication the user authentication for the current user. - * @return a new instance or the same one if no changes are required + * @param oAuth2Request the authorization request. + * @param userAuthentication the user authentication + * @return the OAuth2Request, modified if necessary + */ + OAuth2Request checkForPreApproval(OAuth2Request oAuth2Request, Authentication userAuthentication); + + /** + *

+ * Provides an opportunity to update the authorization request before it is checked for approval in cases where the + * incoming approval parameters contain richer information than just true/false (e.g. some scopes are approved, and + * others are rejected), implementations may need to be able to modify the {@link OAuth2Request} before a + * token is generated from it. + *

+ * + * @param oAuth2Request the authorization request. + * @param userAuthentication the user authentication + * @return the OAuth2Request, modified if necessary */ - boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication); + OAuth2Request updateAfterApproval(OAuth2Request oAuth2Request, Authentication userAuthentication); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java index da53a2a35..a5aa702ae 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java @@ -20,7 +20,7 @@ import org.springframework.security.core.AuthenticationException; import org.springframework.security.oauth2.client.resource.OAuth2AccessDeniedException; import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; -import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices; import org.springframework.util.Assert; @@ -55,7 +55,7 @@ public void afterPropertiesSet() { /** * Expects the incoming authentication request to have a principal value that is an access token value (e.g. from an * authorization header) .Loads an authentication from the {@link ResourceServerTokenServices} and checks that the - * resource id is contained in the {@link AuthorizationRequest} (if one is specified). Also copies authentication + * resource id is contained in the {@link OAuth2Request} (if one is specified). Also copies authentication * details over from the input to the output (e.g. typically so that the access token value and request details can * be reported later). * diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenGranter.java index 9d3b46caf..40fb97cd6 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenGranter.java @@ -18,8 +18,8 @@ import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.token.AbstractTokenGranter; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; @@ -37,8 +37,8 @@ public ClientCredentialsTokenGranter(AuthorizationServerTokenServices tokenServi } @Override - public OAuth2AccessToken grant(String grantType, AuthorizationRequest authorizationRequest) { - OAuth2AccessToken token = super.grant(grantType, authorizationRequest); + public OAuth2AccessToken grant(String grantType, OAuth2Request tokenRequest) { + OAuth2AccessToken token = super.grant(grantType, tokenRequest); if (token != null) { DefaultOAuth2AccessToken norefresh = new DefaultOAuth2AccessToken(token); // The spec says that client credentials are not allowed to get a refresh token diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranter.java index b3b4d17c0..b02a447bb 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranter.java @@ -24,9 +24,8 @@ import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.common.exceptions.RedirectMismatchException; -import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.ClientDetailsService; -import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.token.AbstractTokenGranter; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; @@ -50,11 +49,11 @@ public AuthorizationCodeTokenGranter(AuthorizationServerTokenServices tokenServi } @Override - protected OAuth2Authentication getOAuth2Authentication(AuthorizationRequest authorizationRequest) { + protected OAuth2Authentication getOAuth2Authentication(OAuth2Request oAuth2Request) { - Map parameters = authorizationRequest.getAuthorizationParameters(); + Map parameters = oAuth2Request.getRequestParameters(); String authorizationCode = parameters.get("code"); - String redirectUri = parameters.get(AuthorizationRequest.REDIRECT_URI); + String redirectUri = parameters.get(OAuth2Request.REDIRECT_URI); if (authorizationCode == null) { throw new OAuth2Exception("An authorization code must be supplied."); @@ -65,19 +64,19 @@ protected OAuth2Authentication getOAuth2Authentication(AuthorizationRequest auth throw new InvalidGrantException("Invalid authorization code: " + authorizationCode); } - AuthorizationRequest pendingAuthorizationRequest = storedAuth.getAuthenticationRequest(); + OAuth2Request pendingOAuth2Request = storedAuth.getAuthenticationRequest(); // https://jira.springsource.org/browse/SECOAUTH-333 // This might be null, if the authorization was done without the redirect_uri parameter - String redirectUriApprovalParameter = pendingAuthorizationRequest.getAuthorizationParameters().get( - AuthorizationRequest.REDIRECT_URI); + String redirectUriApprovalParameter = pendingOAuth2Request.getRequestParameters().get( + OAuth2Request.REDIRECT_URI); if ((redirectUri != null || redirectUriApprovalParameter != null) - && !pendingAuthorizationRequest.getRedirectUri().equals(redirectUri)) { + && !pendingOAuth2Request.getRedirectUri().equals(redirectUri)) { throw new RedirectMismatchException("Redirect URI mismatch."); } - String pendingClientId = pendingAuthorizationRequest.getClientId(); - String clientId = authorizationRequest.getClientId(); + String pendingClientId = pendingOAuth2Request.getClientId(); + String clientId = oAuth2Request.getClientId(); if (clientId != null && !clientId.equals(pendingClientId)) { // just a sanity check. throw new InvalidClientException("Client ID mismatch"); @@ -88,16 +87,14 @@ protected OAuth2Authentication getOAuth2Authentication(AuthorizationRequest auth // in the token request, but that happens elsewhere. Map combinedParameters = new HashMap(storedAuth.getAuthenticationRequest() - .getAuthorizationParameters()); + .getRequestParameters()); // Combine the parameters adding the new ones last so they override if there are any clashes combinedParameters.putAll(parameters); - // Similarly scopes are not required in the token request, so we don't make a comparison here, just - // enforce validity through the AuthorizationRequestFactory. - DefaultAuthorizationRequest outgoingRequest = new DefaultAuthorizationRequest(pendingAuthorizationRequest); - outgoingRequest.setAuthorizationParameters(combinedParameters); - + + pendingOAuth2Request.setRequestParameters(combinedParameters); + Authentication userAuth = storedAuth.getUserAuthentication(); - return new OAuth2Authentication(outgoingRequest, userAuth); + return new OAuth2Authentication(pendingOAuth2Request, userAuth); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationRequestHolder.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationRequestHolder.java index d8d94a80b..218423fed 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationRequestHolder.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationRequestHolder.java @@ -19,7 +19,7 @@ import java.io.Serializable; import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Request; /** * Convenience class for {@link AuthorizationCodeServices} to store and retrieve. @@ -31,18 +31,18 @@ public class AuthorizationRequestHolder implements Serializable { private static final long serialVersionUID = 914967629530462926L; - private final AuthorizationRequest authorizationRequest; + private final OAuth2Request oAuth2Request; private final Authentication userAuthentication; public AuthorizationRequestHolder( - AuthorizationRequest authorizationRequest, Authentication userAuthentication) { - this.authorizationRequest = authorizationRequest; + OAuth2Request oAuth2Request, Authentication userAuthentication) { + this.oAuth2Request = oAuth2Request; this.userAuthentication = userAuthentication; } - public AuthorizationRequest getAuthenticationRequest() { - return authorizationRequest; + public OAuth2Request getAuthenticationRequest() { + return oAuth2Request; } public Authentication getUserAuthentication() { @@ -53,7 +53,7 @@ public Authentication getUserAuthentication() { public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + ((authorizationRequest == null) ? 0 : authorizationRequest.hashCode()); + result = prime * result + ((oAuth2Request == null) ? 0 : oAuth2Request.hashCode()); result = prime * result + ((userAuthentication == null) ? 0 : userAuthentication.hashCode()); return result; } @@ -67,10 +67,10 @@ public boolean equals(Object obj) { if (getClass() != obj.getClass()) return false; AuthorizationRequestHolder other = (AuthorizationRequestHolder) obj; - if (authorizationRequest == null) { - if (other.authorizationRequest != null) + if (oAuth2Request == null) { + if (other.oAuth2Request != null) return false; - } else if (!authorizationRequest.equals(other.authorizationRequest)) + } else if (!oAuth2Request.equals(other.oAuth2Request)) return false; if (userAuthentication == null) { if (other.userAuthentication != null) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AbstractEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AbstractEndpoint.java index a36e18b42..95e8f59f0 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AbstractEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AbstractEndpoint.java @@ -19,9 +19,9 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; -import org.springframework.security.oauth2.provider.AuthorizationRequestManager; +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; import org.springframework.security.oauth2.provider.ClientDetailsService; -import org.springframework.security.oauth2.provider.DefaultAuthorizationRequestManager; +import org.springframework.security.oauth2.provider.DefaultOAuth2RequestFactory; import org.springframework.security.oauth2.provider.TokenGranter; import org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator; import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator; @@ -41,16 +41,16 @@ public class AbstractEndpoint implements InitializingBean { private ClientDetailsService clientDetailsService; - private AuthorizationRequestManager authorizationRequestManager; + private OAuth2RequestFactory oAuth2RequestFactory; - private AuthorizationRequestManager defaultAuthorizationRequestManager; + private OAuth2RequestFactory defaultOAuth2RequestFactory; public void afterPropertiesSet() throws Exception { Assert.state(tokenGranter != null, "TokenGranter must be provided"); Assert.state(clientDetailsService != null, "ClientDetailsService must be provided"); - defaultAuthorizationRequestManager = new DefaultAuthorizationRequestManager(getClientDetailsService()); - if (authorizationRequestManager == null) { - authorizationRequestManager = defaultAuthorizationRequestManager; + defaultOAuth2RequestFactory = new DefaultOAuth2RequestFactory(getClientDetailsService()); + if (oAuth2RequestFactory == null) { + oAuth2RequestFactory = defaultOAuth2RequestFactory; } } @@ -70,16 +70,16 @@ protected WebResponseExceptionTranslator getExceptionTranslator() { return providerExceptionHandler; } - protected AuthorizationRequestManager getAuthorizationRequestManager() { - return authorizationRequestManager; + protected OAuth2RequestFactory getOAuth2RequestFactory() { + return oAuth2RequestFactory; } - protected AuthorizationRequestManager getDefaultAuthorizationRequestManager() { - return defaultAuthorizationRequestManager; + protected OAuth2RequestFactory getDefaultOAuth2RequestFactory() { + return defaultOAuth2RequestFactory; } - public void setAuthorizationRequestManager(AuthorizationRequestManager authorizationRequestManager) { - this.authorizationRequestManager = authorizationRequestManager; + public void setOAuth2RequestFactory(OAuth2RequestFactory oAuth2RequestFactory) { + this.oAuth2RequestFactory = oAuth2RequestFactory; } protected ClientDetailsService getClientDetailsService() { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java index 2022a8a30..57afab37d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java @@ -13,7 +13,7 @@ package org.springframework.security.oauth2.provider.endpoint; -import static org.springframework.security.oauth2.provider.AuthorizationRequest.REDIRECT_URI; +import static org.springframework.security.oauth2.provider.OAuth2Request.REDIRECT_URI; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; @@ -21,7 +21,6 @@ import java.util.Collections; import java.util.Date; import java.util.HashMap; -import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; @@ -34,6 +33,7 @@ import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.exceptions.BadClientCredentialsException; import org.springframework.security.oauth2.common.exceptions.ClientAuthenticationException; +import org.springframework.security.oauth2.common.exceptions.InvalidClientException; import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; import org.springframework.security.oauth2.common.exceptions.InvalidRequestException; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; @@ -42,9 +42,11 @@ import org.springframework.security.oauth2.common.exceptions.UnsupportedResponseTypeException; import org.springframework.security.oauth2.common.exceptions.UserDeniedAuthorizationException; import org.springframework.security.oauth2.common.util.OAuth2Utils; -import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientRegistrationException; -import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; +import org.springframework.security.oauth2.provider.DefaultOAuth2RequestValidator; +import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.OAuth2RequestValidator; import org.springframework.security.oauth2.provider.approval.DefaultUserApprovalHandler; import org.springframework.security.oauth2.provider.approval.UserApprovalHandler; import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; @@ -88,11 +90,6 @@ @RequestMapping(value = "/oauth/authorize") public class AuthorizationEndpoint extends AbstractEndpoint implements InitializingBean { - /** - * - */ - private static final String ORIGINAL_SCOPE = "original_scope"; - private AuthorizationCodeServices authorizationCodeServices = new InMemoryAuthorizationCodeServices(); private RedirectResolver redirectResolver = new DefaultRedirectResolver(); @@ -100,6 +97,8 @@ public class AuthorizationEndpoint extends AbstractEndpoint implements Initializ private UserApprovalHandler userApprovalHandler = new DefaultUserApprovalHandler(); private SessionAttributeStore sessionAttributeStore = new DefaultSessionAttributeStore(); + + private OAuth2RequestValidator oAuth2RequestValidator = new DefaultOAuth2RequestValidator(); private String userApprovalPage = "forward:/oauth/confirm_access"; @@ -118,60 +117,70 @@ public void setErrorPage(String errorPage) { } @RequestMapping - public ModelAndView authorize(Map model, - @RequestParam(value = "response_type", required = false, defaultValue = "none") String responseType, - @RequestParam Map requestParameters, SessionStatus sessionStatus, Principal principal) { + public ModelAndView authorize(Map model, @RequestParam Map parameters, + SessionStatus sessionStatus, Principal principal) { + + //Pull out the authorization request first, using the OAuth2RequestFactory. All further logic should + //query off of the authorization request instead of referring back to the parameters map. The contents of the + //parameters map will be stored without change in the OAuth2Request object once it is created. + OAuth2Request oAuth2Request = getOAuth2RequestFactory().createOAuth2Request(parameters); - Set responseTypes = OAuth2Utils.parseParameterList(responseType); + Set responseTypes = oAuth2Request.getResponseTypes(); if (!responseTypes.contains("token") && !responseTypes.contains("code")) { throw new UnsupportedResponseTypeException("Unsupported response types: " + responseTypes); } + if (oAuth2Request.getClientId() == null) { + throw new InvalidClientException("A client id must be provided"); + } + try { - Map parameters = new LinkedHashMap(requestParameters); - - // Manually initialize auth request instead of using @ModelAttribute - // to make sure it comes from request instead of the session - String originalScope = parameters.get(AuthorizationRequest.SCOPE); - if (originalScope!=null) { - parameters.put(ORIGINAL_SCOPE, originalScope); - } - DefaultAuthorizationRequest incomingRequest = new DefaultAuthorizationRequest( - getAuthorizationRequestManager().createAuthorizationRequest(parameters)); - if (!(principal instanceof Authentication) || !((Authentication) principal).isAuthenticated()) { throw new InsufficientAuthenticationException( "User must be authenticated with Spring Security before authorization can be completed."); } - - // The resolvedRedirectUri is either the redirect_uri from the parameters or the one from - // clientDetails. Either way we need to store it on the DefaultAuthorizationRequest - AuthorizationRequest outgoingRequest = resolveRedirectUriAndCheckApproval(incomingRequest, - (Authentication) principal); + + ClientDetails client = getClientDetailsService().loadClientByClientId(oAuth2Request.getClientId()); + + // The resolved redirect URI is either the redirect_uri from the parameters or the one from + // clientDetails. Either way we need to store it on the OAuth2Request. + String redirectUriParameter = oAuth2Request.getRequestParameters().get(OAuth2Request.REDIRECT_URI); + String resolvedRedirect = redirectResolver.resolveRedirect(redirectUriParameter, client); + if (!StringUtils.hasText(resolvedRedirect)) { + throw new RedirectMismatchException( + "A redirectUri must be either supplied or preconfigured in the ClientDetails"); + } + oAuth2Request.setRedirectUri(resolvedRedirect); // We intentionally only validate the parameters requested by the client (ignoring any data that may have // been added to the request by the manager). - getAuthorizationRequestManager().validateParameters(parameters, - getClientDetailsService().loadClientByClientId(outgoingRequest.getClientId())); - + oAuth2RequestValidator.validateScope(oAuth2Request.getRequestParameters(), + client.getScope()); + + //Some systems may allow for approval decisions to be remembered or approved by default. Check for + //such logic here, and set the approved flag on the authorization request accordingly. + oAuth2Request = userApprovalHandler.checkForPreApproval(oAuth2Request, (Authentication) principal); + boolean approved = userApprovalHandler.isApproved(oAuth2Request, (Authentication) principal); + oAuth2Request.setApproved(approved); + // Validation is all done, so we can check for auto approval... - if (outgoingRequest.isApproved()) { + if (oAuth2Request.isApproved()) { if (responseTypes.contains("token")) { - return getImplicitGrantResponse(outgoingRequest); + return getImplicitGrantResponse(oAuth2Request); } if (responseTypes.contains("code")) { - return new ModelAndView(getAuthorizationCodeResponse(outgoingRequest, (Authentication) principal)); + return new ModelAndView(getAuthorizationCodeResponse(oAuth2Request, (Authentication) principal)); } } // Place auth request into the model so that it is stored in the session // for approveOrDeny to use. That way we make sure that auth request comes from the session, // so any auth request parameters passed to approveOrDeny will be ignored and retrieved from the session. - model.put("authorizationRequest", outgoingRequest); + model.put("authorizationRequest", oAuth2Request); - return getUserApprovalPageResponse(model, outgoingRequest); + return getUserApprovalPageResponse(model, oAuth2Request); } catch (RuntimeException e) { @@ -181,7 +190,7 @@ public ModelAndView authorize(Map model, } - @RequestMapping(method = RequestMethod.POST, params = AuthorizationRequest.USER_OAUTH_APPROVAL) + @RequestMapping(method = RequestMethod.POST, params = OAuth2Request.USER_OAUTH_APPROVAL) public View approveOrDeny(@RequestParam Map approvalParameters, Map model, SessionStatus sessionStatus, Principal principal) { @@ -191,32 +200,36 @@ public View approveOrDeny(@RequestParam Map approvalParameters, "User must be authenticated with Spring Security before authorizing an access token."); } - AuthorizationRequest authorizationRequest = (AuthorizationRequest) model.get("authorizationRequest"); + OAuth2Request oAuth2Request = (OAuth2Request) model.get("authorizationRequest"); - if (authorizationRequest == null) { + if (oAuth2Request == null) { sessionStatus.setComplete(); throw new InvalidRequestException("Cannot approve uninitialized authorization request."); } try { - Set responseTypes = authorizationRequest.getResponseTypes(); - - DefaultAuthorizationRequest incomingRequest = new DefaultAuthorizationRequest(authorizationRequest); - incomingRequest.setApprovalParameters(approvalParameters); + Set responseTypes = oAuth2Request.getResponseTypes(); - AuthorizationRequest outgoingRequest = resolveRedirectUriAndCheckApproval(incomingRequest, - (Authentication) principal); + oAuth2Request.setApprovalParameters(approvalParameters); + oAuth2Request = userApprovalHandler.updateAfterApproval(oAuth2Request, (Authentication) principal); + boolean approved = userApprovalHandler.isApproved(oAuth2Request, (Authentication) principal); + oAuth2Request.setApproved(approved); - if (!outgoingRequest.isApproved()) { - return new RedirectView(getUnsuccessfulRedirect(outgoingRequest, new UserDeniedAuthorizationException( + if (oAuth2Request.getRedirectUri() == null) { + sessionStatus.setComplete(); + throw new InvalidRequestException("Cannot approve request when no redirect URI is provided."); + } + + if (!oAuth2Request.isApproved()) { + return new RedirectView(getUnsuccessfulRedirect(oAuth2Request, new UserDeniedAuthorizationException( "User denied access"), responseTypes.contains("token")), false); } if (responseTypes.contains("token")) { - return getImplicitGrantResponse(outgoingRequest).getView(); + return getImplicitGrantResponse(oAuth2Request).getView(); } - return getAuthorizationCodeResponse(outgoingRequest, (Authentication) principal); + return getAuthorizationCodeResponse(oAuth2Request, (Authentication) principal); } finally { sessionStatus.setComplete(); @@ -224,80 +237,44 @@ public View approveOrDeny(@RequestParam Map approvalParameters, } - /** - * Resolving and return the redirect uri if possible, throwing an exception otherwise, and then checking to see if - * the request has been authorized, setting the flag appropriately. - * - * @param authorizationRequest the current request - * @param authentication the current authentication token - * - * @return the resolved redirect uri ( - * {@link RedirectResolver#resolveRedirect(String, org.springframework.security.oauth2.provider.ClientDetails)} - * - * @throws OAuth2Exception if the redirect uri or client is invalid - */ - private AuthorizationRequest resolveRedirectUriAndCheckApproval(AuthorizationRequest authorizationRequest, - Authentication authentication) throws OAuth2Exception { - - String redirectUriParameter = authorizationRequest.getAuthorizationParameters().get( - AuthorizationRequest.REDIRECT_URI); - String resolvedRedirect = redirectResolver.resolveRedirect(redirectUriParameter, getClientDetailsService() - .loadClientByClientId(authorizationRequest.getClientId())); - if (!StringUtils.hasText(resolvedRedirect)) { - throw new RedirectMismatchException( - "A redirectUri must be either supplied or preconfigured in the ClientDetails"); - } - - DefaultAuthorizationRequest requestForApproval = new DefaultAuthorizationRequest(authorizationRequest); - requestForApproval.setRedirectUri(resolvedRedirect); - DefaultAuthorizationRequest outgoingRequest = new DefaultAuthorizationRequest( - userApprovalHandler.updateBeforeApproval(requestForApproval, authentication)); - - boolean approved = authorizationRequest.isApproved(); - if (!approved) { - approved = userApprovalHandler.isApproved(outgoingRequest, authentication); - outgoingRequest.setApproved(approved); - } - - return outgoingRequest; - } - // We need explicit approval from the user. private ModelAndView getUserApprovalPageResponse(Map model, - AuthorizationRequest authorizationRequest) { + OAuth2Request oAuth2Request) { logger.debug("Loading user approval page: " + userApprovalPage); // In case of a redirect we might want the request parameters to be included - model.putAll(authorizationRequest.getAuthorizationParameters()); + model.putAll(oAuth2Request.getRequestParameters()); return new ModelAndView(userApprovalPage, model); } // We can grant a token and return it with implicit approval. - private ModelAndView getImplicitGrantResponse(AuthorizationRequest authorizationRequest) { + private ModelAndView getImplicitGrantResponse(OAuth2Request oAuth2Request) { try { - OAuth2AccessToken accessToken = getTokenGranter().grant("implicit", authorizationRequest); + OAuth2AccessToken accessToken = getTokenGranter().grant("implicit", oAuth2Request); if (accessToken == null) { throw new UnsupportedResponseTypeException("Unsupported response type: token"); } - return new ModelAndView(new RedirectView(appendAccessToken(authorizationRequest, accessToken), false)); + return new ModelAndView(new RedirectView(appendAccessToken(oAuth2Request, accessToken), false)); } catch (OAuth2Exception e) { - return new ModelAndView(new RedirectView(getUnsuccessfulRedirect(authorizationRequest, e, true), false)); + return new ModelAndView(new RedirectView(getUnsuccessfulRedirect(oAuth2Request, e, true), false)); } } - private View getAuthorizationCodeResponse(AuthorizationRequest authorizationRequest, Authentication authUser) { + private View getAuthorizationCodeResponse(OAuth2Request oAuth2Request, Authentication authUser) { try { - return new RedirectView(getSuccessfulRedirect(authorizationRequest, - generateCode(authorizationRequest, authUser)), false); + return new RedirectView(getSuccessfulRedirect(oAuth2Request, + generateCode(oAuth2Request, authUser)), false); } catch (OAuth2Exception e) { - return new RedirectView(getUnsuccessfulRedirect(authorizationRequest, e, false), false); + return new RedirectView(getUnsuccessfulRedirect(oAuth2Request, e, false), false); } } - - private String appendAccessToken(AuthorizationRequest authorizationRequest, OAuth2AccessToken accessToken) { - Map vars = new HashMap(); - String requestedRedirect = authorizationRequest.getRedirectUri(); + + private String appendAccessToken(OAuth2Request oAuth2Request, OAuth2AccessToken accessToken) { + + Map vars = new HashMap(); + + String requestedRedirect = oAuth2Request.getRedirectUri(); if (accessToken == null) { throw new InvalidGrantException("An implicit grant could not be made"); } @@ -308,11 +285,13 @@ private String appendAccessToken(AuthorizationRequest authorizationRequest, OAut else { url.append("#"); } + url.append("access_token={access_token}"); url.append("&token_type={token_type}"); vars.put("access_token", accessToken.getValue()); vars.put("token_type", accessToken.getTokenType()); - String state = authorizationRequest.getState(); + String state = oAuth2Request.getState(); + if (state != null) { url.append("&state={state}"); vars.put("state", state); @@ -323,9 +302,9 @@ private String appendAccessToken(AuthorizationRequest authorizationRequest, OAut url.append("&expires_in={expires_in}"); vars.put("expires_in", expires_in); } - String originalScope = authorizationRequest.getAuthorizationParameters().get(ORIGINAL_SCOPE); + String originalScope = oAuth2Request.getRequestParameters().get(OAuth2Request.SCOPE); if (originalScope==null || !OAuth2Utils.parseParameterList(originalScope).equals(accessToken.getScope())) { - url.append("&" + AuthorizationRequest.SCOPE + "={scope}"); + url.append("&" + OAuth2Request.SCOPE + "={scope}"); vars.put("scope", OAuth2Utils.formatParameterList(accessToken.getScope())); } Map additionalInformation = accessToken.getAdditionalInformation(); @@ -341,12 +320,12 @@ private String appendAccessToken(AuthorizationRequest authorizationRequest, OAut return template.expand(vars).toString(); } - private String generateCode(AuthorizationRequest authorizationRequest, Authentication authentication) + private String generateCode(OAuth2Request oAuth2Request, Authentication authentication) throws AuthenticationException { try { - AuthorizationRequestHolder combinedAuth = new AuthorizationRequestHolder(authorizationRequest, + AuthorizationRequestHolder combinedAuth = new AuthorizationRequestHolder(oAuth2Request, authentication); String code = authorizationCodeServices.createAuthorizationCode(combinedAuth); @@ -355,8 +334,8 @@ private String generateCode(AuthorizationRequest authorizationRequest, Authentic } catch (OAuth2Exception e) { - if (authorizationRequest.getState() != null) { - e.addAdditionalInformation("state", authorizationRequest.getState()); + if (oAuth2Request.getState() != null) { + e.addAdditionalInformation("state", oAuth2Request.getState()); } throw e; @@ -364,15 +343,15 @@ private String generateCode(AuthorizationRequest authorizationRequest, Authentic } } - private String getSuccessfulRedirect(AuthorizationRequest authorizationRequest, String authorizationCode) { + private String getSuccessfulRedirect(OAuth2Request oAuth2Request, String authorizationCode) { if (authorizationCode == null) { throw new IllegalStateException("No authorization code found in the current request scope."); } - String requestedRedirect = authorizationRequest.getRedirectUri(); + String requestedRedirect = oAuth2Request.getRedirectUri(); String[] fragments = requestedRedirect.split("#"); - String state = authorizationRequest.getState(); + String state = oAuth2Request.getState(); StringBuilder url = new StringBuilder(fragments[0]); if (requestedRedirect.indexOf('?') < 0) { @@ -394,15 +373,15 @@ private String getSuccessfulRedirect(AuthorizationRequest authorizationRequest, return url.toString(); } - private String getUnsuccessfulRedirect(AuthorizationRequest authorizationRequest, OAuth2Exception failure, + private String getUnsuccessfulRedirect(OAuth2Request oAuth2Request, OAuth2Exception failure, boolean fragment) { - if (authorizationRequest == null || authorizationRequest.getRedirectUri() == null) { + if (oAuth2Request == null || oAuth2Request.getRedirectUri() == null) { // we have no redirect for the user. very sad. throw new UnapprovedClientAuthenticationException("Authorization failure, and no redirect URI.", failure); } - String redirectUri = authorizationRequest.getRedirectUri(); + String redirectUri = oAuth2Request.getRedirectUri(); // extract existing fragments if any String[] fragments = redirectUri.split("#"); @@ -421,8 +400,8 @@ private String getUnsuccessfulRedirect(AuthorizationRequest authorizationRequest url.append("&error_description=").append(URLEncoder.encode(failure.getMessage(), "UTF-8")); - if (authorizationRequest.getState() != null) { - url.append('&').append("state=").append(authorizationRequest.getState()); + if (oAuth2Request.getState() != null) { + url.append('&').append("state=").append(oAuth2Request.getState()); } if (failure.getAdditionalInformation() != null) { @@ -461,6 +440,10 @@ public void setUserApprovalHandler(UserApprovalHandler userApprovalHandler) { this.userApprovalHandler = userApprovalHandler; } + public void setoAuth2RequestValidator(OAuth2RequestValidator oAuth2RequestValidator) { + this.oAuth2RequestValidator = oAuth2RequestValidator; + } + @ExceptionHandler(ClientRegistrationException.class) public ModelAndView handleClientRegistrationException(Exception e, ServletWebRequest webRequest) throws Exception { logger.info("Handling ClientRegistrationException error: " + e.getMessage()); @@ -490,15 +473,14 @@ private ModelAndView handleException(Exception e, ServletWebRequest webRequest) return new ModelAndView(errorPage, Collections.singletonMap("error", translate.getBody())); } - AuthorizationRequest errorRequest = null; + OAuth2Request oAuth2Request = null; try { - errorRequest = getAuthorizationRequestForError(webRequest); - DefaultAuthorizationRequest authorizationRequest = new DefaultAuthorizationRequest(errorRequest); - String requestedRedirectParam = authorizationRequest.getAuthorizationParameters().get(REDIRECT_URI); + oAuth2Request = getOAuth2RequestForError(webRequest); + String requestedRedirectParam = oAuth2Request.getRequestParameters().get(REDIRECT_URI); String requestedRedirect = redirectResolver.resolveRedirect(requestedRedirectParam, - getClientDetailsService().loadClientByClientId(authorizationRequest.getClientId())); - authorizationRequest.setRedirectUri(requestedRedirect); - String redirect = getUnsuccessfulRedirect(authorizationRequest, translate.getBody(), authorizationRequest + getClientDetailsService().loadClientByClientId(oAuth2Request.getClientId())); + oAuth2Request.setRedirectUri(requestedRedirect); + String redirect = getUnsuccessfulRedirect(oAuth2Request, translate.getBody(), oAuth2Request .getResponseTypes().contains("token")); return new ModelAndView(new RedirectView(redirect, false)); } @@ -511,13 +493,13 @@ private ModelAndView handleException(Exception e, ServletWebRequest webRequest) } - private AuthorizationRequest getAuthorizationRequestForError(ServletWebRequest webRequest) { + private OAuth2Request getOAuth2RequestForError(ServletWebRequest webRequest) { // If it's already there then we are in the approveOrDeny phase and we can use the saved request - AuthorizationRequest authorizationRequest = (AuthorizationRequest) sessionAttributeStore.retrieveAttribute( + OAuth2Request oAuth2Request = (OAuth2Request) sessionAttributeStore.retrieveAttribute( webRequest, "authorizationRequest"); - if (authorizationRequest != null) { - return authorizationRequest; + if (oAuth2Request != null) { + return oAuth2Request; } Map parameters = new HashMap(); @@ -530,10 +512,10 @@ private AuthorizationRequest getAuthorizationRequestForError(ServletWebRequest w } try { - return getAuthorizationRequestManager().createAuthorizationRequest(parameters); + return getOAuth2RequestFactory().createOAuth2Request(parameters); } catch (Exception e) { - return getDefaultAuthorizationRequestManager().createAuthorizationRequest(parameters); + return getDefaultOAuth2RequestFactory().createOAuth2Request(parameters); } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java index 48158f584..ad73b6608 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java @@ -20,7 +20,7 @@ import org.springframework.core.Ordered; import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.web.servlet.mvc.condition.NameValueExpression; import org.springframework.web.servlet.mvc.condition.ParamsRequestCondition; import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition; @@ -37,7 +37,7 @@ public class FrameworkEndpointHandlerMapping extends RequestMappingHandlerMappin private Map mappings = new HashMap(); - private String approvalParameter = AuthorizationRequest.USER_OAUTH_APPROVAL; + private String approvalParameter = OAuth2Request.USER_OAUTH_APPROVAL; /** * Custom mappings for framework endpoint paths. The keys in the map are the default framework endpoint path, e.g. @@ -51,7 +51,7 @@ public void setMappings(Map patternMap) { /** * The name of the request parameter that distinguishes a call to approve an authorization. Default is - * {@link AuthorizationRequest#USER_OAUTH_APPROVAL}. + * {@link OAuth2Request#USER_OAUTH_APPROVAL}. * * @param approvalParameter the approvalParameter to set */ @@ -96,14 +96,14 @@ protected RequestMappingInfo getMappingForMethod(Method method, Class handler PatternsRequestCondition patternsInfo = new PatternsRequestCondition(patterns); ParamsRequestCondition paramsInfo = defaultMapping.getParamsCondition(); - if (!approvalParameter.equals(AuthorizationRequest.USER_OAUTH_APPROVAL) + if (!approvalParameter.equals(OAuth2Request.USER_OAUTH_APPROVAL) && defaultPatterns.contains("/oauth/authorize")) { String[] params = new String[paramsInfo.getExpressions().size()]; Set> expressions = paramsInfo.getExpressions(); i = 0; for (NameValueExpression expression : expressions) { String param = expression.toString(); - if (AuthorizationRequest.USER_OAUTH_APPROVAL.equals(param)) { + if (OAuth2Request.USER_OAUTH_APPROVAL.equals(param)) { params[i] = approvalParameter; } else { params[i] = param; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java index 0ee0bece7..cfbea60d8 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java @@ -32,9 +32,12 @@ import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.common.exceptions.UnsupportedGrantTypeException; import org.springframework.security.oauth2.common.util.OAuth2Utils; +import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientRegistrationException; -import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; +import org.springframework.security.oauth2.provider.DefaultOAuth2RequestValidator; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.OAuth2RequestValidator; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; @@ -46,7 +49,7 @@ * parameter (e.g. "authorization_code") and other parameters as determined by the grant type. Supported grant types are * handled by the provided {@link #setTokenGranter(org.springframework.security.oauth2.provider.TokenGranter) token * granter}. - *

+ *

* *

* Clients must be authenticated using a Spring Security {@link Authentication} to access this endpoint, and the client @@ -61,6 +64,8 @@ @RequestMapping(value = "/oauth/token") public class TokenEndpoint extends AbstractEndpoint { + private OAuth2RequestValidator oAuth2RequestValidator = new DefaultOAuth2RequestValidator(); + @RequestMapping public ResponseEntity getAccessToken(Principal principal, @RequestParam(value = "grant_type", required = false) String grantType, @@ -70,34 +75,36 @@ public ResponseEntity getAccessToken(Principal principal, throw new InsufficientAuthenticationException( "There is no client authentication. Try adding an appropriate authentication filter."); } - + HashMap request = new HashMap(parameters); String clientId = getClientId(principal); if (clientId != null) { request.put("client_id", clientId); + //Only validate the client details if a client authenticated during this + //request. + ClientDetails client = getClientDetailsService().loadClientByClientId(clientId); + if (client != null) { + oAuth2RequestValidator.validateScope(parameters, client.getScope()); + } } if (!StringUtils.hasText(grantType)) { throw new InvalidRequestException("Missing grant type"); } - getAuthorizationRequestManager().validateParameters(parameters, - getClientDetailsService().loadClientByClientId(clientId)); - - DefaultAuthorizationRequest authorizationRequest = new DefaultAuthorizationRequest( - getAuthorizationRequestManager().createAuthorizationRequest(request)); + OAuth2Request tokenRequest = getOAuth2RequestFactory().createOAuth2Request(request); if (isAuthCodeRequest(parameters) || isRefreshTokenRequest(parameters)) { // The scope was requested or determined during the authorization step - if (!authorizationRequest.getScope().isEmpty()) { + if (!tokenRequest.getScope().isEmpty()) { logger.debug("Clearing scope of incoming auth code request"); - authorizationRequest.setScope(Collections. emptySet()); + tokenRequest.setScope(Collections. emptySet()); } } if (isRefreshTokenRequest(parameters)) { // A refresh token has its own default scopes, so we should ignore any added by the factory here. - authorizationRequest.setScope(OAuth2Utils.parseParameterList(parameters.get("scope"))); + tokenRequest.setScope(OAuth2Utils.parseParameterList(parameters.get("scope"))); } - OAuth2AccessToken token = getTokenGranter().grant(grantType, authorizationRequest); + OAuth2AccessToken token = getTokenGranter().grant(grantType, tokenRequest); if (token == null) { throw new UnsupportedGrantTypeException("Unsupported grant type: " + grantType); } @@ -149,5 +156,9 @@ private boolean isRefreshTokenRequest(Map parameters) { private boolean isAuthCodeRequest(Map parameters) { return "authorization_code".equals(parameters.get("grant_type")) && parameters.get("code") != null; } + + public void setoAuth2RequestValidator(OAuth2RequestValidator oAuth2RequestValidator) { + this.oAuth2RequestValidator = oAuth2RequestValidator; + } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java index 8a72c178f..770674f19 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java @@ -17,9 +17,9 @@ package org.springframework.security.oauth2.provider.endpoint; import java.io.IOException; -import java.util.Collection; import java.util.HashMap; import java.util.Map; +import java.util.Set; import javax.servlet.Filter; import javax.servlet.FilterChain; @@ -41,7 +41,8 @@ import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.oauth2.common.util.OAuth2Utils; -import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint; import org.springframework.security.web.AuthenticationEntryPoint; @@ -77,13 +78,16 @@ public class TokenEndpointAuthenticationFilter implements Filter { private AuthenticationEntryPoint authenticationEntryPoint = new OAuth2AuthenticationEntryPoint(); private final AuthenticationManager authenticationManager; + + private final OAuth2RequestFactory oAuth2RequestFactory; /** * @param authenticationManager an AuthenticationManager for the incoming request */ - public TokenEndpointAuthenticationFilter(AuthenticationManager authenticationManager) { + public TokenEndpointAuthenticationFilter(AuthenticationManager authenticationManager, OAuth2RequestFactory oAuth2RequestFactory) { super(); this.authenticationManager = authenticationManager; + this.oAuth2RequestFactory = oAuth2RequestFactory; } /** @@ -133,15 +137,18 @@ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throw new BadCredentialsException( "No client authentication found. Remember to put a filter upstream of the TokenEndpointAuthenticationFilter."); } - DefaultAuthorizationRequest authorizationRequest = new DefaultAuthorizationRequest( - getSingleValueMap(request), null, clientAuth.getName(), getScope(request)); + + OAuth2Request oAuth2Request = oAuth2RequestFactory.createOAuth2Request(getSingleValueMap(request)); + + oAuth2Request.setClientId(clientAuth.getName()); + oAuth2Request.setScope(getScope(request)); if (clientAuth.isAuthenticated()) { // Ensure the OAuth2Authentication is authenticated - authorizationRequest.setApproved(true); + oAuth2Request.setApproved(true); } SecurityContextHolder.getContext().setAuthentication( - new OAuth2Authentication(authorizationRequest, authResult)); + new OAuth2Authentication(oAuth2Request, authResult)); onSuccessfulAuthentication(request, response, authResult); @@ -176,10 +183,6 @@ private Map getSingleValueMap(HttpServletRequest request) { return map; } - private Collection getScope(HttpServletRequest request) { - return OAuth2Utils.parseParameterList(request.getParameter("scope")); - } - protected void onSuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, Authentication authResult) throws IOException { } @@ -207,6 +210,10 @@ protected Authentication extractCredentials(HttpServletRequest request) { return null; } + private Set getScope(HttpServletRequest request) { + return OAuth2Utils.parseParameterList(request.getParameter("scope")); + } + public void init(FilterConfig filterConfig) throws ServletException { } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionUtils.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionUtils.java index 3a1ff8380..13eafe0c2 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionUtils.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionUtils.java @@ -18,8 +18,8 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.AuthorityUtils; -import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.OAuth2Request; /** * @author Dave Syer @@ -29,7 +29,7 @@ public abstract class OAuth2ExpressionUtils { public static boolean clientHasAnyRole(Authentication authentication, String... roles) { if (authentication instanceof OAuth2Authentication) { - AuthorizationRequest clientAuthentication = ((OAuth2Authentication) authentication).getAuthorizationRequest(); + OAuth2Request clientAuthentication = ((OAuth2Authentication) authentication).getAuthorizationRequest(); Collection clientAuthorities = clientAuthentication.getAuthorities(); if (clientAuthorities != null) { Set roleSet = AuthorityUtils.authorityListToSet(clientAuthorities); @@ -74,7 +74,7 @@ public static boolean isOAuthUserAuth(Authentication authentication) { public static boolean hasAnyScope(Authentication authentication, String[] scopes) { if (authentication instanceof OAuth2Authentication) { - AuthorizationRequest clientAuthentication = ((OAuth2Authentication) authentication).getAuthorizationRequest(); + OAuth2Request clientAuthentication = ((OAuth2Authentication) authentication).getAuthorizationRequest(); Collection assigned = clientAuthentication.getScope(); if (assigned != null) { for (String scope : scopes) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java index 043d18f3b..bd685631e 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java @@ -20,7 +20,7 @@ import org.springframework.security.authentication.InsufficientAuthenticationException; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.token.AbstractTokenGranter; @@ -39,7 +39,7 @@ public ImplicitTokenGranter(AuthorizationServerTokenServices tokenServices, Clie } @Override - protected OAuth2Authentication getOAuth2Authentication(AuthorizationRequest clientToken) { + protected OAuth2Authentication getOAuth2Authentication(OAuth2Request clientToken) { Authentication userAuth = SecurityContextHolder.getContext().getAuthentication(); if (userAuth==null || !userAuth.isAuthenticated()) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java index 750af1e47..b647b566d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java @@ -16,7 +16,8 @@ package org.springframework.security.oauth2.provider.password; -import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; import java.util.Map; import org.springframework.security.authentication.AccountStatusException; @@ -25,10 +26,9 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; -import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.ClientDetailsService; -import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.token.AbstractTokenGranter; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; @@ -49,9 +49,9 @@ public ResourceOwnerPasswordTokenGranter(AuthenticationManager authenticationMan } @Override - protected OAuth2Authentication getOAuth2Authentication(AuthorizationRequest clientToken) { + protected OAuth2Authentication getOAuth2Authentication(OAuth2Request clientToken) { - Map parameters = clientToken.getAuthorizationParameters(); + Map parameters = clientToken.getRequestParameters(); String username = parameters.get("username"); String password = parameters.get("password"); @@ -70,10 +70,14 @@ protected OAuth2Authentication getOAuth2Authentication(AuthorizationRequest clie if (userAuth == null || !userAuth.isAuthenticated()) { throw new InvalidGrantException("Could not authenticate user: " + username); } + + //TODO: Why are we removing something from the original parameters map? + Map requestParameters = clientToken.getRequestParameters(); + HashMap modifiable = new HashMap(requestParameters); + modifiable.remove("password"); - DefaultAuthorizationRequest request = new DefaultAuthorizationRequest(clientToken); - request.remove(Arrays.asList("password")); - - return new OAuth2Authentication(request, userAuth); + clientToken.setRequestParameters(Collections.unmodifiableMap(modifiable)); + + return new OAuth2Authentication(clientToken, userAuth); } -} \ No newline at end of file +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/refresh/RefreshTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/refresh/RefreshTokenGranter.java index 38ae449da..4709924bd 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/refresh/RefreshTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/refresh/RefreshTokenGranter.java @@ -17,7 +17,7 @@ package org.springframework.security.oauth2.provider.refresh; import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.token.AbstractTokenGranter; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; @@ -35,9 +35,9 @@ public RefreshTokenGranter(AuthorizationServerTokenServices tokenServices, Clien } @Override - protected OAuth2AccessToken getAccessToken(AuthorizationRequest authorizationRequest) { - String refreshToken = authorizationRequest.getAuthorizationParameters().get("refresh_token"); - return getTokenServices().refreshAccessToken(refreshToken, authorizationRequest); + protected OAuth2AccessToken getAccessToken(OAuth2Request oAuth2Request) { + String refreshToken = oAuth2Request.getRequestParameters().get("refresh_token"); + return getTokenServices().refreshAccessToken(refreshToken, oAuth2Request); } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AbstractTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AbstractTokenGranter.java index 8b800fac5..1d7f41aeb 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AbstractTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AbstractTokenGranter.java @@ -18,11 +18,10 @@ import org.apache.commons.logging.LogFactory; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; -import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; -import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.TokenGranter; /** @@ -46,30 +45,31 @@ protected AbstractTokenGranter(AuthorizationServerTokenServices tokenServices, this.tokenServices = tokenServices; } - public OAuth2AccessToken grant(String grantType, AuthorizationRequest authorizationRequest) { + public OAuth2AccessToken grant(String grantType, OAuth2Request tokenRequest) { if (!this.grantType.equals(grantType)) { return null; } - String clientId = authorizationRequest.getClientId(); + String clientId = tokenRequest.getClientId(); ClientDetails client = clientDetailsService.loadClientByClientId(clientId); validateGrantType(grantType, client); logger.debug("Getting access token for: " + clientId); - return getAccessToken(authorizationRequest); + + // FIXME: do we need to explicitly set approved flag here? + tokenRequest.setApproved(true); + + return getAccessToken(tokenRequest); } - protected OAuth2AccessToken getAccessToken(AuthorizationRequest authorizationRequest) { - DefaultAuthorizationRequest outgoingRequest = new DefaultAuthorizationRequest(authorizationRequest); - outgoingRequest.setApproved(true); - // FIXME: do we need to explicitly set approved flag here? - return tokenServices.createAccessToken(getOAuth2Authentication(outgoingRequest)); + protected OAuth2AccessToken getAccessToken(OAuth2Request tokenRequest) { + return tokenServices.createAccessToken(getOAuth2Authentication(tokenRequest)); } - protected OAuth2Authentication getOAuth2Authentication(AuthorizationRequest authorizationRequest) { - return new OAuth2Authentication(authorizationRequest, null); + protected OAuth2Authentication getOAuth2Authentication(OAuth2Request tokenRequest) { + return new OAuth2Authentication(tokenRequest, null); } protected void validateGrantType(String grantType, ClientDetails clientDetails) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AuthorizationServerTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AuthorizationServerTokenServices.java index 6d1e0d08f..c6596555e 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AuthorizationServerTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AuthorizationServerTokenServices.java @@ -18,8 +18,8 @@ import org.springframework.security.core.AuthenticationException; import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.OAuth2Request; /** * @author Ryan Heaton @@ -46,7 +46,7 @@ public interface AuthorizationServerTokenServices { * @return The (new) access token. * @throws AuthenticationException If the refresh token is invalid or expired. */ - OAuth2AccessToken refreshAccessToken(String refreshToken, AuthorizationRequest request) + OAuth2AccessToken refreshAccessToken(String refreshToken, OAuth2Request request) throws AuthenticationException; /** diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAuthenticationKeyGenerator.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAuthenticationKeyGenerator.java index 470458727..4a87fec71 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAuthenticationKeyGenerator.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAuthenticationKeyGenerator.java @@ -20,8 +20,8 @@ import java.util.Map; import org.springframework.security.oauth2.common.util.OAuth2Utils; -import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.OAuth2Request; /** * Basic key generator taking into account the client id, scope, reource ids and username (principal name) if they @@ -40,7 +40,7 @@ public class DefaultAuthenticationKeyGenerator implements AuthenticationKeyGener public String extractKey(OAuth2Authentication authentication) { Map values = new LinkedHashMap(); - AuthorizationRequest authorizationRequest = authentication.getAuthorizationRequest(); + OAuth2Request authorizationRequest = authentication.getAuthorizationRequest(); if (!authentication.isClientOnly()) { values.put(USERNAME, authentication.getName()); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java index 7f6897263..98c6d8ddc 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java @@ -28,10 +28,10 @@ import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; import org.springframework.security.oauth2.common.exceptions.InvalidScopeException; import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; -import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.util.Assert; /** @@ -112,7 +112,7 @@ else if (refreshToken instanceof ExpiringOAuth2RefreshToken) { } - public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, AuthorizationRequest request) + public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, OAuth2Request request) throws AuthenticationException { if (!supportRefreshToken) { @@ -168,7 +168,7 @@ public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) { private OAuth2Authentication createRefreshedAuthentication(OAuth2Authentication authentication, Set scope) { OAuth2Authentication narrowed = authentication; if (scope != null && !scope.isEmpty()) { - AuthorizationRequest clientAuth = authentication.getAuthorizationRequest(); + OAuth2Request clientAuth = authentication.getAuthorizationRequest(); Set originalScope = clientAuth.getScope(); if (originalScope == null || !originalScope.containsAll(scope)) { throw new InvalidScopeException("Unable to narrow the scope of the client authentication to " + scope @@ -213,7 +213,7 @@ public String getClientId(String tokenValue) { if (authentication == null) { throw new InvalidTokenException("Invalid access token: " + tokenValue); } - AuthorizationRequest authorizationRequest = authentication.getAuthorizationRequest(); + OAuth2Request authorizationRequest = authentication.getAuthorizationRequest(); if (authorizationRequest == null) { throw new InvalidTokenException("Invalid access token (no client id): " + tokenValue); } @@ -267,7 +267,7 @@ private OAuth2AccessToken createAccessToken(OAuth2Authentication authentication, * @param authorizationRequest the current authorization request * @return the access token validity period in seconds */ - protected int getAccessTokenValiditySeconds(AuthorizationRequest authorizationRequest) { + protected int getAccessTokenValiditySeconds(OAuth2Request authorizationRequest) { if (clientDetailsService != null) { ClientDetails client = clientDetailsService.loadClientByClientId(authorizationRequest.getClientId()); Integer validity = client.getAccessTokenValiditySeconds(); @@ -283,7 +283,7 @@ protected int getAccessTokenValiditySeconds(AuthorizationRequest authorizationRe * @param authorizationRequest the current authorization request * @return the refresh token validity period in seconds */ - protected int getRefreshTokenValiditySeconds(AuthorizationRequest authorizationRequest) { + protected int getRefreshTokenValiditySeconds(OAuth2Request authorizationRequest) { if (clientDetailsService != null) { ClientDetails client = clientDetailsService.loadClientByClientId(authorizationRequest.getClientId()); Integer validity = client.getRefreshTokenValiditySeconds(); @@ -300,7 +300,7 @@ protected int getRefreshTokenValiditySeconds(AuthorizationRequest authorizationR * @param authorizationRequest the current authorization request * @return boolean to indicate if refresh token is supported */ - protected boolean isSupportRefreshToken(AuthorizationRequest authorizationRequest) { + protected boolean isSupportRefreshToken(OAuth2Request authorizationRequest) { if (clientDetailsService != null) { ClientDetails client = clientDetailsService.loadClientByClientId(authorizationRequest.getClientId()); return client.getAuthorizedGrantTypes().contains("refresh_token"); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/vote/ScopeVoter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/vote/ScopeVoter.java index 86a3cd7f1..6df759a01 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/vote/ScopeVoter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/vote/ScopeVoter.java @@ -25,7 +25,7 @@ import org.springframework.security.access.ConfigAttribute; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.common.exceptions.InsufficientScopeException; -import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.OAuth2Authentication; /** @@ -39,8 +39,8 @@ *

* Abstains from voting if no configuration attribute commences with the scope prefix, or if the current * Authentication is not a {@link OAuth2Authentication} or the current client authentication is not a - * {@link AuthorizationRequest} (which contains teh scope data). Votes to grant access if there is an exact matching - * {@link AuthorizationRequest#getScope() authorized scope} to a ConfigAttribute starting with the scope + * {@link OAuth2Request} (which contains teh scope data). Votes to grant access if there is an exact matching + * {@link OAuth2Request#getScope() authorized scope} to a ConfigAttribute starting with the scope * prefix. Votes to deny access if there is no exact matching authorized scope to a ConfigAttribute * starting with the scope prefix. *

@@ -131,7 +131,7 @@ public int vote(Authentication authentication, Object object, Collection parameters; + + @Before + public void prepare() { + parameters = new HashMap(); + parameters.put("client_id", "theClient"); + parameters.put("state", "XYZ123"); + parameters.put("redirect_uri", "http://www.callistaenterprise.se/"); + } + + private OAuth2Request createFromParameters(Map authorizationParameters) { + OAuth2Request request = new OAuth2Request(authorizationParameters, Collections. emptyMap(), + authorizationParameters.get(OAuth2Request.CLIENT_ID), + OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Request.SCOPE)), null, + null, false, authorizationParameters.get(OAuth2Request.STATE), + authorizationParameters.get(OAuth2Request.REDIRECT_URI), + OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Request.RESPONSE_TYPE))); + return request; + } + + @Test + public void testApproval() throws Exception { + OAuth2Request oAuth2Request = createFromParameters(parameters); + assertFalse(oAuth2Request.isApproved()); + oAuth2Request.setApproved(true); + assertTrue(oAuth2Request.isApproved()); + } + + /** + * Ensure that setting the scope does not alter the original request parameters. + * + * @throws Exception + */ + @Test + public void testScopeNotSetInParameters() throws Exception { + parameters.put("scope", "read,write"); + OAuth2Request oAuth2Request = createFromParameters(parameters); + oAuth2Request.setScope(StringUtils.commaDelimitedListToSet("foo,bar")); + assertFalse(oAuth2Request.getRequestParameters().get(OAuth2Request.SCOPE).contains("bar")); + assertFalse(oAuth2Request.getRequestParameters().get(OAuth2Request.SCOPE).contains("foo")); + } + + @Test + public void testClientIdNotOverwitten() throws Exception { + OAuth2Request oAuth2Request = new OAuth2Request("client", Arrays.asList("read")); + parameters = new HashMap(); + parameters.put("scope", "write"); + oAuth2Request.setRequestParameters(parameters); + + assertEquals("client", oAuth2Request.getClientId()); + assertEquals(1, oAuth2Request.getScope().size()); + assertTrue(oAuth2Request.getScope().contains("read")); + assertFalse(oAuth2Request.getRequestParameters().get(OAuth2Request.SCOPE).contains("read")); + } + + @Test + public void testScopeWithSpace() throws Exception { + parameters.put("scope", "bar foo"); + OAuth2Request oAuth2Request = createFromParameters(parameters); + oAuth2Request.setScope(Collections.singleton("foo bar")); + assertEquals("bar foo", oAuth2Request.getRequestParameters().get(OAuth2Request.SCOPE)); + } + + /** + * Tests that the construction of an AuthorizationRequest objects using + * a parameter Map maintains a sorted order of the scope. + */ + @Test + public void testScopeSortedOrder() { + // Arbitrary scope set + String scopeString = "AUTHORITY_A AUTHORITY_X AUTHORITY_B AUTHORITY_C AUTHORITY_D " + + "AUTHORITY_Y AUTHORITY_V AUTHORITY_ZZ AUTHORITY_DYV AUTHORITY_ABC AUTHORITY_BA " + + "AUTHORITY_AV AUTHORITY_AB AUTHORITY_CDA AUTHORITY_ABCD"; + // Create correctly sorted scope string + Set sortedSet = OAuth2Utils.parseParameterList(scopeString); + Assert.assertTrue(sortedSet instanceof SortedSet); + String sortedScopeString = OAuth2Utils.formatParameterList(sortedSet); + + parameters.put("scope", scopeString); + OAuth2Request oAuth2Request = createFromParameters(parameters); + oAuth2Request.setScope(sortedSet); + + // Assert that the scope parameter is still sorted + + String fromAR = OAuth2Utils.formatParameterList(oAuth2Request.getScope()); + + Assert.assertEquals(sortedScopeString, fromAR); + } + + @Test + public void testRedirectUriDefaultsToMap() { + parameters.put("scope", "one two"); + OAuth2Request oAuth2Request = createFromParameters(parameters); + + assertEquals("XYZ123", oAuth2Request.getState()); + assertEquals("theClient", oAuth2Request.getClientId()); + assertEquals("http://www.callistaenterprise.se/", oAuth2Request.getRedirectUri()); + assertEquals("http://www.callistaenterprise.se/", oAuth2Request.getRequestParameters().get(REDIRECT_URI)); + assertEquals("[one, two]", oAuth2Request.getScope().toString()); + } + +} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestDefaultAuthorizationRequest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestDefaultAuthorizationRequest.java index a3a6ee81f..7bf75cec2 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestDefaultAuthorizationRequest.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestDefaultAuthorizationRequest.java @@ -18,10 +18,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; -import static org.springframework.security.oauth2.provider.AuthorizationRequest.REDIRECT_URI; import java.util.Arrays; import java.util.Collections; @@ -54,47 +51,57 @@ public void prepare() { parameters.put("redirect_uri", "http://www.callistaenterprise.se/"); } + private OAuth2Request createFromParameters(Map authorizationParameters) { + OAuth2Request request = new OAuth2Request(authorizationParameters, Collections. emptyMap(), + authorizationParameters.get(OAuth2Request.CLIENT_ID), + OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Request.SCOPE)), null, + null, false, authorizationParameters.get(OAuth2Request.STATE), + authorizationParameters.get(OAuth2Request.REDIRECT_URI), + OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Request.RESPONSE_TYPE))); + return request; + } + @Test public void testApproval() throws Exception { - DefaultAuthorizationRequest authorizationRequest = new DefaultAuthorizationRequest(parameters); - assertFalse(authorizationRequest.isApproved()); - authorizationRequest.setApproved(true); - assertTrue(authorizationRequest.isApproved()); + OAuth2Request oAuth2Request = createFromParameters(parameters); + assertFalse(oAuth2Request.isApproved()); + oAuth2Request.setApproved(true); + assertTrue(oAuth2Request.isApproved()); } + /** + * Ensure that setting the scope does not alter the original request parameters. + * + * @throws Exception + */ @Test - public void testScopeSetInParameters() throws Exception { - DefaultAuthorizationRequest authorizationRequest = new DefaultAuthorizationRequest(parameters); - authorizationRequest.setScope(StringUtils.commaDelimitedListToSet("foo,bar")); - assertEquals("bar foo", authorizationRequest.getAuthorizationParameters().get(AuthorizationRequest.SCOPE)); + public void testScopeNotSetInParameters() throws Exception { + parameters.put("scope", "read,write"); + OAuth2Request oAuth2Request = createFromParameters(parameters); + oAuth2Request.setScope(StringUtils.commaDelimitedListToSet("foo,bar")); + assertFalse(oAuth2Request.getRequestParameters().get(OAuth2Request.SCOPE).contains("bar")); + assertFalse(oAuth2Request.getRequestParameters().get(OAuth2Request.SCOPE).contains("foo")); } @Test public void testClientIdNotOverwitten() throws Exception { - DefaultAuthorizationRequest authorizationRequest = new DefaultAuthorizationRequest("client", Arrays.asList("read")); + OAuth2Request oAuth2Request = new OAuth2Request("client", Arrays.asList("read")); parameters = new HashMap(); - authorizationRequest.setAuthorizationParameters(parameters); - assertEquals("client", authorizationRequest.getClientId()); - assertEquals("read", authorizationRequest.getAuthorizationParameters().get(AuthorizationRequest.SCOPE)); - } - - @Test - public void testPasswordSetAndRemovedFromParameters() throws Exception { - parameters.put("username", "sample"); - parameters.put("password", "testing"); - DefaultAuthorizationRequest authorizationRequest = new DefaultAuthorizationRequest(parameters); - assertEquals("testing", authorizationRequest.getAuthorizationParameters().get("password")); - - authorizationRequest.remove(Arrays.asList("password")); - assertNotNull(authorizationRequest.getAuthorizationParameters().get("username")); - assertNull(authorizationRequest.getAuthorizationParameters().get("password")); + parameters.put("scope", "write"); + oAuth2Request.setRequestParameters(parameters); + + assertEquals("client", oAuth2Request.getClientId()); + assertEquals(1, oAuth2Request.getScope().size()); + assertTrue(oAuth2Request.getScope().contains("read")); + assertFalse(oAuth2Request.getRequestParameters().get(OAuth2Request.SCOPE).contains("read")); } @Test public void testScopeWithSpace() throws Exception { - DefaultAuthorizationRequest authorizationRequest = new DefaultAuthorizationRequest(parameters); - authorizationRequest.setScope(Collections.singleton("foo bar")); - assertEquals("bar foo", authorizationRequest.getAuthorizationParameters().get(AuthorizationRequest.SCOPE)); + parameters.put("scope", "bar foo"); + OAuth2Request oAuth2Request = createFromParameters(parameters); + oAuth2Request.setScope(Collections.singleton("foo bar")); + assertEquals("bar foo", oAuth2Request.getRequestParameters().get(OAuth2Request.SCOPE)); } /** @@ -113,23 +120,26 @@ public void testScopeSortedOrder() { String sortedScopeString = OAuth2Utils.formatParameterList(sortedSet); parameters.put("scope", scopeString); - AuthorizationRequest authorizationRequest = new DefaultAuthorizationRequest(parameters); + OAuth2Request oAuth2Request = createFromParameters(parameters); + oAuth2Request.setScope(sortedSet); - // Assert that both the scope parameter and the scope Set of - // the constructed AuthorizationRequest are sorted - Assert.assertEquals(sortedScopeString, OAuth2Utils.formatParameterList(authorizationRequest.getScope())); - Assert.assertEquals(sortedScopeString, authorizationRequest.getAuthorizationParameters().get("scope")); + // Assert that the scope parameter is still sorted + + String fromAR = OAuth2Utils.formatParameterList(oAuth2Request.getScope()); + + Assert.assertEquals(sortedScopeString, fromAR); } @Test public void testRedirectUriDefaultsToMap() { parameters.put("scope", "one two"); - DefaultAuthorizationRequest authorizationRequest = new DefaultAuthorizationRequest(parameters); - assertEquals("XYZ123", authorizationRequest.getState()); - assertEquals("theClient", authorizationRequest.getClientId()); - assertEquals("http://www.callistaenterprise.se/", authorizationRequest.getRedirectUri()); - assertEquals("http://www.callistaenterprise.se/", authorizationRequest.getAuthorizationParameters().get(REDIRECT_URI)); - assertEquals("[one, two]", authorizationRequest.getScope().toString()); + OAuth2Request oAuth2Request = createFromParameters(parameters); + + assertEquals("XYZ123", oAuth2Request.getState()); + assertEquals("theClient", oAuth2Request.getClientId()); + assertEquals("http://www.callistaenterprise.se/", oAuth2Request.getRedirectUri()); + assertEquals("http://www.callistaenterprise.se/", oAuth2Request.getRequestParameters().get(OAuth2Request.REDIRECT_URI)); + assertEquals("[one, two]", oAuth2Request.getScope().toString()); } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestDefaultAuthorizationRequestManager.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestDefaultAuthorizationRequestManager.java index 27c1159b6..66a308802 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestDefaultAuthorizationRequestManager.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestDefaultAuthorizationRequestManager.java @@ -30,7 +30,7 @@ public class TestDefaultAuthorizationRequestManager { private BaseClientDetails client = new BaseClientDetails(); - private DefaultAuthorizationRequestManager factory = new DefaultAuthorizationRequestManager(new ClientDetailsService() { + private DefaultOAuth2RequestFactory factory = new DefaultOAuth2RequestFactory(new ClientDetailsService() { public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exception { return client; } @@ -44,13 +44,13 @@ public void start() { @Test public void testCreateAuthorizationRequest() { - AuthorizationRequest request = factory.createAuthorizationRequest(Collections.singletonMap("client_id", "foo")); + OAuth2Request request = factory.createOAuth2Request(Collections.singletonMap("client_id", "foo")); assertEquals("foo", request.getClientId()); } @Test public void testCreateAuthorizationRequestWithDefaultScopes() { - AuthorizationRequest request = factory.createAuthorizationRequest(Collections.singletonMap("client_id", "foo")); + OAuth2Request request = factory.createOAuth2Request(Collections.singletonMap("client_id", "foo")); assertEquals("[bar]", request.getScope().toString()); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestOAuth2Authentication.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestOAuth2Authentication.java index d42507c64..6a24d2a06 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestOAuth2Authentication.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestOAuth2Authentication.java @@ -13,7 +13,7 @@ public class TestOAuth2Authentication { - private DefaultAuthorizationRequest request = new DefaultAuthorizationRequest("id", Arrays.asList("read")); + private OAuth2Request request = new OAuth2Request("id", Arrays.asList("read")); private UsernamePasswordAuthenticationToken userAuthentication = new UsernamePasswordAuthenticationToken("foo", "bar", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"))); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestDefaultUserApprovalHandler.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestDefaultUserApprovalHandler.java index 24e93120e..50045a47b 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestDefaultUserApprovalHandler.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestDefaultUserApprovalHandler.java @@ -18,7 +18,7 @@ import org.junit.Test; import org.springframework.security.authentication.AbstractAuthenticationToken; -import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Request; /** * @author Dave Syer @@ -30,12 +30,14 @@ public class TestDefaultUserApprovalHandler { @Test public void testBasicApproval() { - DefaultAuthorizationRequest request =new DefaultAuthorizationRequest(new HashMap()); + OAuth2Request request =new OAuth2Request(new HashMap(), null, null, null, null, null, false, null, null, null); request.setApproved(true); // This isn't enough to be explicitly approved assertFalse(handler.isApproved(request, new TestAuthentication("marissa", true))); } protected static class TestAuthentication extends AbstractAuthenticationToken { + + private static final long serialVersionUID = 1L; private String principal; public TestAuthentication(String name, boolean authenticated) { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenServicesUserApprovalHandler.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenServicesUserApprovalHandler.java index a809e2fb6..a141da13c 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenServicesUserApprovalHandler.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenServicesUserApprovalHandler.java @@ -20,7 +20,7 @@ import org.junit.Test; import org.springframework.security.authentication.AbstractAuthenticationToken; -import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.token.DefaultTokenServices; import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; @@ -48,22 +48,24 @@ public void testMandatoryProperties() throws Exception { @Test public void testBasicApproval() { - DefaultAuthorizationRequest request = new DefaultAuthorizationRequest(new HashMap()); + OAuth2Request request = new OAuth2Request(new HashMap(), null, null, null, null, null, false, null, null, null); request.setApproved(true); // This isn't enough to be explicitly approved assertFalse(handler.isApproved(request , new TestAuthentication("marissa", true))); } @Test public void testMemorizedApproval() { - DefaultAuthorizationRequest authorizationRequest = new DefaultAuthorizationRequest(Collections.singletonMap( - "client_id", "foo")); - authorizationRequest.setApproved(false); + OAuth2Request oAuth2Request = new OAuth2Request(Collections.singletonMap( + "client_id", "foo"), null, "foo", null, null, null, false, null, null, null); + oAuth2Request.setApproved(false); TestAuthentication userAuthentication = new TestAuthentication("marissa", true); - tokenServices.createAccessToken(new OAuth2Authentication(authorizationRequest, userAuthentication)); - assertTrue(handler.isApproved(authorizationRequest, userAuthentication)); + tokenServices.createAccessToken(new OAuth2Authentication(oAuth2Request, userAuthentication)); + assertTrue(handler.isApproved(oAuth2Request, userAuthentication)); } protected static class TestAuthentication extends AbstractAuthenticationToken { + + private static final long serialVersionUID = 1L; private String principal; public TestAuthentication(String name, boolean authenticated) { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationManager.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationManager.java index 643f8de21..60914b5aa 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationManager.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationManager.java @@ -22,7 +22,7 @@ import org.mockito.Mockito; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices; import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken; @@ -39,8 +39,8 @@ public class TestOAuth2AuthenticationManager { private Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala"); - private OAuth2Authentication authentication = new OAuth2Authentication(new DefaultAuthorizationRequest( - Collections. emptyMap()), userAuthentication); + private OAuth2Authentication authentication = new OAuth2Authentication(new OAuth2Request( + Collections. emptyMap(), null, null, null, null, null, false, null, null, null), userAuthentication); { manager.setTokenServices(tokenServices); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationProcessingFilter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationProcessingFilter.java index 825cfd7a0..b10def1a5 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationProcessingFilter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationProcessingFilter.java @@ -30,7 +30,7 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.OAuth2Authentication; /** @@ -45,8 +45,8 @@ public class TestOAuth2AuthenticationProcessingFilter { private Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala"); - private OAuth2Authentication authentication = new OAuth2Authentication(new DefaultAuthorizationRequest( - Collections. emptyMap()), userAuthentication); + private OAuth2Authentication authentication = new OAuth2Authentication(new OAuth2Request( + Collections. emptyMap(), null, null, null, null, null, false, null, null, null), userAuthentication); private FilterChain chain = Mockito.mock(FilterChain.class); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeServicesBase.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeServicesBase.java index 61604ef2f..1ae392dec 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeServicesBase.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeServicesBase.java @@ -7,7 +7,7 @@ import org.junit.Test; import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; -import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Request; public abstract class TestAuthorizationCodeServicesBase { @@ -16,7 +16,7 @@ public abstract class TestAuthorizationCodeServicesBase { @Test public void testCreateAuthorizationCode() { AuthorizationRequestHolder expectedAuthentication = new AuthorizationRequestHolder( - new DefaultAuthorizationRequest("id", null), new TestAuthentication( + new OAuth2Request("id", null), new TestAuthentication( "test2", false)); String code = getAuthorizationCodeServices().createAuthorizationCode(expectedAuthentication); assertNotNull(code); @@ -29,7 +29,7 @@ public void testCreateAuthorizationCode() { @Test public void testConsumeRemovesCode() { AuthorizationRequestHolder expectedAuthentication = new AuthorizationRequestHolder( - new DefaultAuthorizationRequest("id", null), new TestAuthentication( + new OAuth2Request("id", null), new TestAuthentication( "test2", false)); String code = getAuthorizationCodeServices().createAuthorizationCode(expectedAuthentication); assertNotNull(code); @@ -57,6 +57,8 @@ public void testConsumeNonExistingCode() { } protected static class TestAuthentication extends AbstractAuthenticationToken { + + private static final long serialVersionUID = 1L; private String principal; public TestAuthentication(String name, boolean authenticated) { super(null); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeTokenGranter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeTokenGranter.java index 48baf2956..c55fcc8f6 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeTokenGranter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeTokenGranter.java @@ -16,7 +16,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import static org.springframework.security.oauth2.provider.AuthorizationRequest.REDIRECT_URI; +import static org.springframework.security.oauth2.provider.OAuth2Request.REDIRECT_URI; import java.util.Arrays; import java.util.Collections; @@ -31,11 +31,11 @@ import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.common.exceptions.RedirectMismatchException; -import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.common.util.OAuth2Utils; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; -import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; import org.springframework.security.oauth2.provider.token.DefaultTokenServices; import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; import org.springframework.util.StringUtils; @@ -60,6 +60,16 @@ public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exceptio private AuthorizationCodeServices authorizationCodeServices = new InMemoryAuthorizationCodeServices(); private Map parameters = new HashMap(); + + private OAuth2Request createFromParameters(Map authorizationParameters) { + OAuth2Request request = new OAuth2Request(authorizationParameters, Collections. emptyMap(), + authorizationParameters.get(OAuth2Request.CLIENT_ID), + OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Request.SCOPE)), null, + null, false, authorizationParameters.get(OAuth2Request.STATE), + authorizationParameters.get(OAuth2Request.REDIRECT_URI), + OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Request.RESPONSE_TYPE))); + return request; + } public TestAuthorizationCodeTokenGranter() { providerTokenServices.setTokenStore(new InMemoryTokenStore()); @@ -67,60 +77,60 @@ public TestAuthorizationCodeTokenGranter() { @Test public void testAuthorizationCodeGrant() { - DefaultAuthorizationRequest authorizationRequest = new DefaultAuthorizationRequest("foo", + OAuth2Request oAuth2Request = new OAuth2Request("foo", Arrays.asList("scope")); - authorizationRequest.setApproved(true); + oAuth2Request.setApproved(true); Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); String code = authorizationCodeServices.createAuthorizationCode(new AuthorizationRequestHolder( - authorizationRequest, userAuthentication)); - parameters.putAll(authorizationRequest.getAuthorizationParameters()); + oAuth2Request, userAuthentication)); + parameters.putAll(oAuth2Request.getRequestParameters()); parameters.put("code", code); - authorizationRequest.setAuthorizationParameters(parameters); + oAuth2Request.setRequestParameters(parameters); AuthorizationCodeTokenGranter granter = new AuthorizationCodeTokenGranter(providerTokenServices, authorizationCodeServices, clientDetailsService); - OAuth2AccessToken token = granter.grant("authorization_code", authorizationRequest); + OAuth2AccessToken token = granter.grant("authorization_code", oAuth2Request); assertTrue(providerTokenServices.loadAuthentication(token.getValue()).isAuthenticated()); } @Test public void testAuthorizationParametersPreserved() { - DefaultAuthorizationRequest authorizationRequest = new DefaultAuthorizationRequest( + OAuth2Request oAuth2Request = createFromParameters( commaDelimitedStringToMap("foo=bar,client_id=foo")); - authorizationRequest.setApproved(true); + oAuth2Request.setApproved(true); Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); String code = authorizationCodeServices.createAuthorizationCode(new AuthorizationRequestHolder( - authorizationRequest, userAuthentication)); - parameters.putAll(authorizationRequest.getAuthorizationParameters()); + oAuth2Request, userAuthentication)); + parameters.putAll(oAuth2Request.getRequestParameters()); parameters.put("code", code); - authorizationRequest.setAuthorizationParameters(parameters); + oAuth2Request.setRequestParameters(parameters); AuthorizationCodeTokenGranter granter = new AuthorizationCodeTokenGranter(providerTokenServices, authorizationCodeServices, clientDetailsService); - OAuth2AccessToken token = granter.grant("authorization_code", authorizationRequest); - AuthorizationRequest finalRequest = providerTokenServices.loadAuthentication(token.getValue()) + OAuth2AccessToken token = granter.grant("authorization_code", oAuth2Request); + OAuth2Request finalRequest = providerTokenServices.loadAuthentication(token.getValue()) .getAuthorizationRequest(); - assertEquals(code, finalRequest.getAuthorizationParameters().get("code")); - assertEquals("bar", finalRequest.getAuthorizationParameters().get("foo")); + assertEquals(code, finalRequest.getRequestParameters().get("code")); + assertEquals("bar", finalRequest.getRequestParameters().get("foo")); } @Test public void testAuthorizationRequestPreserved() { - DefaultAuthorizationRequest authorizationRequest = new DefaultAuthorizationRequest( + OAuth2Request oAuth2Request = createFromParameters( commaDelimitedStringToMap("client_id=foo,scope=read")); - authorizationRequest.setResourceIds(Collections.singleton("resource")); - authorizationRequest.setApproved(true); + oAuth2Request.setResourceIds(Collections.singleton("resource")); + oAuth2Request.setApproved(true); Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); String code = authorizationCodeServices.createAuthorizationCode(new AuthorizationRequestHolder( - authorizationRequest, userAuthentication)); + oAuth2Request, userAuthentication)); parameters.put("client_id", "foo"); parameters.put("code", code); - authorizationRequest.setAuthorizationParameters(parameters); + oAuth2Request.setRequestParameters(parameters); AuthorizationCodeTokenGranter granter = new AuthorizationCodeTokenGranter(providerTokenServices, authorizationCodeServices, clientDetailsService); - OAuth2AccessToken token = granter.grant("authorization_code", authorizationRequest); - AuthorizationRequest finalRequest = providerTokenServices.loadAuthentication(token.getValue()) + OAuth2AccessToken token = granter.grant("authorization_code", oAuth2Request); + OAuth2Request finalRequest = providerTokenServices.loadAuthentication(token.getValue()) .getAuthorizationRequest(); assertEquals("[read]", finalRequest.getScope().toString()); assertEquals("[resource]", finalRequest.getResourceIds().toString()); @@ -139,19 +149,19 @@ private static Map commaDelimitedStringToMap(String string) { @Test public void testAuthorizationCodeGrantWithNoClientAuthorities() { client.setAuthorities(Collections. emptySet()); - DefaultAuthorizationRequest authorizationRequest = new DefaultAuthorizationRequest("foo", + OAuth2Request oAuth2Request = new OAuth2Request("foo", Arrays.asList("scope")); - authorizationRequest.setApproved(true); + oAuth2Request.setApproved(true); Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); String code = authorizationCodeServices.createAuthorizationCode(new AuthorizationRequestHolder( - authorizationRequest, userAuthentication)); - parameters.putAll(authorizationRequest.getAuthorizationParameters()); + oAuth2Request, userAuthentication)); + parameters.putAll(oAuth2Request.getRequestParameters()); parameters.put("code", code); - authorizationRequest.setAuthorizationParameters(parameters); + oAuth2Request.setRequestParameters(parameters); AuthorizationCodeTokenGranter granter = new AuthorizationCodeTokenGranter(providerTokenServices, authorizationCodeServices, clientDetailsService); - OAuth2AccessToken token = granter.grant("authorization_code", authorizationRequest); + OAuth2AccessToken token = granter.grant("authorization_code", oAuth2Request); assertTrue(providerTokenServices.loadAuthentication(token.getValue()).isAuthenticated()); } @@ -159,7 +169,7 @@ public void testAuthorizationCodeGrantWithNoClientAuthorities() { public void testAuthorizationRedirectMismatch() { Map initialParameters = new HashMap(); initialParameters.put(REDIRECT_URI, "https://redirectme/"); - DefaultAuthorizationRequest initialRequest = new DefaultAuthorizationRequest(initialParameters); + OAuth2Request initialRequest = createFromParameters(initialParameters); // we fake a valid resolvedRedirectUri because without the client would never come this far initialRequest.setRedirectUri(initialParameters.get(REDIRECT_URI)); @@ -170,13 +180,13 @@ public void testAuthorizationRedirectMismatch() { Map authorizationParameters = new HashMap(); authorizationParameters.put("code", code); - DefaultAuthorizationRequest authorizationRequest = new DefaultAuthorizationRequest(initialParameters); - authorizationRequest.setAuthorizationParameters(authorizationParameters); + OAuth2Request oAuth2Request = createFromParameters(initialParameters); + oAuth2Request.setRequestParameters(authorizationParameters); AuthorizationCodeTokenGranter granter = new AuthorizationCodeTokenGranter(providerTokenServices, authorizationCodeServices, clientDetailsService); try { - granter.getOAuth2Authentication(authorizationRequest); + granter.getOAuth2Authentication(oAuth2Request); fail("RedirectMismatchException because of null redirect_uri in authorizationRequest"); } catch (RedirectMismatchException e) { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationRequestHolder.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationRequestHolder.java index c98cdbd7a..84ab395d0 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationRequestHolder.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationRequestHolder.java @@ -20,7 +20,7 @@ import org.junit.Test; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.oauth2.common.util.SerializationUtils; -import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Request; /** * @author Dave Syer @@ -28,7 +28,7 @@ */ public class TestAuthorizationRequestHolder { - private AuthorizationRequestHolder holder = new AuthorizationRequestHolder(new DefaultAuthorizationRequest( + private AuthorizationRequestHolder holder = new AuthorizationRequestHolder(new OAuth2Request( "client", Arrays.asList("read")), new UsernamePasswordAuthenticationToken("user", "pwd")); @Test diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestAuthorizationEndpoint.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestAuthorizationEndpoint.java index d78593c02..bd08e9767 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestAuthorizationEndpoint.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestAuthorizationEndpoint.java @@ -16,13 +16,15 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.springframework.security.oauth2.provider.AuthorizationRequest.REDIRECT_URI; +import static org.springframework.security.oauth2.provider.OAuth2Request.REDIRECT_URI; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; import org.junit.Before; import org.junit.Test; @@ -32,14 +34,14 @@ import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; +import org.springframework.security.oauth2.common.exceptions.InvalidRequestException; import org.springframework.security.oauth2.common.exceptions.InvalidScopeException; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; -import org.springframework.security.oauth2.common.exceptions.RedirectMismatchException; -import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.common.util.OAuth2Utils; import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; -import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.TokenGranter; import org.springframework.security.oauth2.provider.approval.UserApprovalHandler; import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; @@ -66,20 +68,28 @@ public class TestAuthorizationEndpoint { private BaseClientDetails client; - private DefaultAuthorizationRequest getAuthorizationRequest(String clientId, String redirectUri, String state, - String scope) { + private OAuth2Request getOAuth2Request(String clientId, String redirectUri, String state, + String scope, Set responseTypes) { HashMap parameters = new HashMap(); - parameters.put("client_id", clientId); + parameters.put(OAuth2Request.CLIENT_ID, clientId); if (redirectUri != null) { - parameters.put("redirect_uri", redirectUri); + parameters.put(OAuth2Request.REDIRECT_URI, redirectUri); } if (state != null) { - parameters.put("state", state); + parameters.put(OAuth2Request.STATE, state); } if (scope != null) { - parameters.put("scope", scope); + parameters.put(OAuth2Request.SCOPE, scope); } - return new DefaultAuthorizationRequest(parameters); + if (responseTypes != null) { + parameters.put(OAuth2Request.RESPONSE_TYPE, OAuth2Utils.formatParameterList(responseTypes)); + } + return new OAuth2Request(parameters, Collections. emptyMap(), + parameters.get(OAuth2Request.CLIENT_ID), + OAuth2Utils.parseParameterList(parameters.get(OAuth2Request.SCOPE)), null, + null, false, parameters.get(OAuth2Request.STATE), + parameters.get(OAuth2Request.REDIRECT_URI), + OAuth2Utils.parseParameterList(parameters.get(OAuth2Request.RESPONSE_TYPE))); } @Before @@ -93,7 +103,7 @@ public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exceptio } }); endpoint.setTokenGranter(new TokenGranter() { - public OAuth2AccessToken grant(String grantType, AuthorizationRequest authorizationRequest) { + public OAuth2AccessToken grant(String grantType, OAuth2Request oAuth2Request) { return null; } }); @@ -109,25 +119,26 @@ public void testMandatoryProperties() throws Exception { @Test public void testStartAuthorizationCodeFlow() throws Exception { - ModelAndView result = endpoint.authorize(model, "code", getAuthorizationRequest("foo", null, null, null) - .getAuthorizationParameters(), sessionStatus, principal); + + ModelAndView result = endpoint.authorize(model, getOAuth2Request("foo", null, null, null, Collections.singleton("code")) + .getRequestParameters(), sessionStatus, principal); assertEquals("forward:/oauth/confirm_access", result.getViewName()); } @Test(expected = OAuth2Exception.class) public void testStartAuthorizationCodeFlowForClientCredentialsFails() throws Exception { client.setAuthorizedGrantTypes(Collections.singleton("client_credentials")); - ModelAndView result = endpoint.authorize(model, "code", getAuthorizationRequest("foo", null, null, null) - .getAuthorizationParameters(), sessionStatus, principal); + ModelAndView result = endpoint.authorize(model, getOAuth2Request("foo", null, null, null, Collections.singleton("code")) + .getRequestParameters(), sessionStatus, principal); assertEquals("forward:/oauth/confirm_access", result.getViewName()); } @Test public void testAuthorizationCodeWithFragment() throws Exception { endpoint.setAuthorizationCodeServices(new StubAuthorizationCodeServices()); - model.put("authorizationRequest", getAuthorizationRequest("foo", "http://anywhere.com/#bar", null, null)); + model.put("authorizationRequest", getOAuth2Request("foo", "http://anywhere.com/#bar", null, null, Collections.singleton("code"))); View result = endpoint.approveOrDeny( - Collections.singletonMap(AuthorizationRequest.USER_OAUTH_APPROVAL, "true"), model, sessionStatus, + Collections.singletonMap(OAuth2Request.USER_OAUTH_APPROVAL, "true"), model, sessionStatus, principal); assertEquals("http://anywhere.com/?code=thecode#bar", ((RedirectView) result).getUrl()); } @@ -135,12 +146,16 @@ public void testAuthorizationCodeWithFragment() throws Exception { @Test public void testAuthorizationCodeError() throws Exception { endpoint.setUserApprovalHandler(new UserApprovalHandler() { - public AuthorizationRequest updateBeforeApproval(AuthorizationRequest authorizationRequest, + public OAuth2Request checkForPreApproval(OAuth2Request oAuth2Request, Authentication userAuthentication) { + return oAuth2Request; + } + + public OAuth2Request updateAfterApproval(OAuth2Request oAuth2Request, Authentication userAuthentication) { - return authorizationRequest; + return oAuth2Request; } - public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { + public boolean isApproved(OAuth2Request oAuth2Request, Authentication userAuthentication) { return true; } }); @@ -150,9 +165,9 @@ public String createAuthorizationCode(AuthorizationRequestHolder authentication) throw new InvalidScopeException("FOO"); } }); - ModelAndView result = endpoint.authorize(model, "code", - getAuthorizationRequest("foo", "http://anywhere.com/", "mystate", "myscope") - .getAuthorizationParameters(), sessionStatus, principal); + ModelAndView result = endpoint.authorize(model, + getOAuth2Request("foo", "http://anywhere.com/", "mystate", "myscope", Collections.singleton("code")) + .getRequestParameters(), sessionStatus, principal); String url = ((RedirectView) result.getView()).getUrl(); assertTrue("Wrong view: " + result, url.startsWith("http://anywhere.com/")); assertTrue("No error: " + result, url.contains("?error=")); @@ -162,33 +177,42 @@ public String createAuthorizationCode(AuthorizationRequestHolder authentication) @Test public void testAuthorizationCodeWithMultipleResponseTypes() throws Exception { - ModelAndView result = endpoint.authorize(model, "code other", getAuthorizationRequest("foo", null, null, null) - .getAuthorizationParameters(), sessionStatus, principal); + Set responseTypes = new HashSet(); + responseTypes.add("code"); + responseTypes.add("other"); + ModelAndView result = endpoint.authorize(model, getOAuth2Request("foo", null, null, null, responseTypes) + .getRequestParameters(), sessionStatus, principal); assertEquals("forward:/oauth/confirm_access", result.getViewName()); } @Test public void testImplicitPreApproved() throws Exception { endpoint.setTokenGranter(new TokenGranter() { - public OAuth2AccessToken grant(String grantType, AuthorizationRequest authorizationRequest) { + + public OAuth2AccessToken grant(String grantType, OAuth2Request authorizationRequest) { DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken("FOO"); token.setAdditionalInformation(Collections.singletonMap("foo", (Object)"bar")); return token; + } }); endpoint.setUserApprovalHandler(new UserApprovalHandler() { - public AuthorizationRequest updateBeforeApproval(AuthorizationRequest authorizationRequest, + public OAuth2Request checkForPreApproval(OAuth2Request oAuth2Request, Authentication userAuthentication) { + return oAuth2Request; + } + + public OAuth2Request updateAfterApproval(OAuth2Request oAuth2Request, Authentication userAuthentication) { - return authorizationRequest; + return oAuth2Request; } - public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { + public boolean isApproved(OAuth2Request oAuth2Request, Authentication userAuthentication) { return true; } }); - AuthorizationRequest authorizationRequest = getAuthorizationRequest("foo", "http://anywhere.com/", "mystate", - "myscope"); - ModelAndView result = endpoint.authorize(model, "token", authorizationRequest.getAuthorizationParameters(), + OAuth2Request oAuth2Request = getOAuth2Request("foo", "http://anywhere.com/", "mystate", + "myscope", Collections.singleton("token")); + ModelAndView result = endpoint.authorize(model, oAuth2Request.getRequestParameters(), sessionStatus, principal); String url = ((RedirectView) result.getView()).getUrl(); assertTrue("Wrong view: " + result, url.startsWith("http://anywhere.com/")); @@ -200,25 +224,29 @@ public boolean isApproved(AuthorizationRequest authorizationRequest, Authenticat @Test public void testImplicitAppendsScope() throws Exception { endpoint.setTokenGranter(new TokenGranter() { - public OAuth2AccessToken grant(String grantType, AuthorizationRequest authorizationRequest) { + public OAuth2AccessToken grant(String grantType, OAuth2Request authorizationRequest) { DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken("FOO"); token.setScope(Collections.singleton("read")); return token; } }); endpoint.setUserApprovalHandler(new UserApprovalHandler() { - public AuthorizationRequest updateBeforeApproval(AuthorizationRequest authorizationRequest, + public OAuth2Request checkForPreApproval(OAuth2Request oAuth2Request, Authentication userAuthentication) { + return oAuth2Request; + } + + public OAuth2Request updateAfterApproval(OAuth2Request oAuth2Request, Authentication userAuthentication) { - return authorizationRequest; + return oAuth2Request; } - public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { + public boolean isApproved(OAuth2Request oAuth2Request, Authentication userAuthentication) { return true; } }); - AuthorizationRequest authorizationRequest = getAuthorizationRequest("foo", "http://anywhere.com/", "mystate", - "myscope"); - ModelAndView result = endpoint.authorize(model, "token", authorizationRequest.getAuthorizationParameters(), + OAuth2Request authorizationRequest = getOAuth2Request("foo", "http://anywhere.com/", "mystate", + "myscope", Collections.singleton("token")); + ModelAndView result = endpoint.authorize(model, authorizationRequest.getRequestParameters(), sessionStatus, principal); String url = ((RedirectView) result.getView()).getUrl(); assertTrue("Wrong scope: " + result, url.contains("&scope=read")); @@ -227,25 +255,32 @@ public boolean isApproved(AuthorizationRequest authorizationRequest, Authenticat @Test public void testImplicitAppendsScopeWhenDefaulting() throws Exception { endpoint.setTokenGranter(new TokenGranter() { - public OAuth2AccessToken grant(String grantType, AuthorizationRequest authorizationRequest) { + public OAuth2AccessToken grant(String grantType, OAuth2Request authorizationRequest) { DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken("FOO"); token.setScope(new LinkedHashSet(Arrays.asList("read", "write"))); return token; } }); endpoint.setUserApprovalHandler(new UserApprovalHandler() { - public AuthorizationRequest updateBeforeApproval(AuthorizationRequest authorizationRequest, + public boolean isApproved(OAuth2Request authorizationRequest, Authentication userAuthentication) { + return true; + } + + public OAuth2Request checkForPreApproval( + OAuth2Request oAuth2Request, Authentication userAuthentication) { - return authorizationRequest; + return oAuth2Request; } - public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { - return true; + public OAuth2Request updateAfterApproval( + OAuth2Request oAuth2Request, + Authentication userAuthentication) { + return oAuth2Request; } }); - AuthorizationRequest authorizationRequest = getAuthorizationRequest("foo", "http://anywhere.com/", "mystate", - null); - ModelAndView result = endpoint.authorize(model, "token", authorizationRequest.getAuthorizationParameters(), + OAuth2Request authorizationRequest = getOAuth2Request("foo", "http://anywhere.com/", "mystate", + null, Collections.singleton("token")); + ModelAndView result = endpoint.authorize(model,authorizationRequest.getRequestParameters(), sessionStatus, principal); String url = ((RedirectView) result.getView()).getUrl(); assertTrue("Wrong scope: " + result, url.contains("&scope=read%20write")); @@ -254,24 +289,30 @@ public boolean isApproved(AuthorizationRequest authorizationRequest, Authenticat @Test(expected = InvalidScopeException.class) public void testImplicitPreApprovedButInvalid() throws Exception { endpoint.setTokenGranter(new TokenGranter() { - public OAuth2AccessToken grant(String grantType, AuthorizationRequest authorizationRequest) { + public OAuth2AccessToken grant(String grantType, OAuth2Request authorizationRequest) { throw new IllegalStateException("Shouldn't be called"); } }); endpoint.setUserApprovalHandler(new UserApprovalHandler() { - public AuthorizationRequest updateBeforeApproval(AuthorizationRequest authorizationRequest, + public boolean isApproved(OAuth2Request authorizationRequest, Authentication userAuthentication) { + return true; + } + public OAuth2Request checkForPreApproval( + OAuth2Request oAuth2Request, Authentication userAuthentication) { - return authorizationRequest; + return oAuth2Request; } - public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { - return true; + public OAuth2Request updateAfterApproval( + OAuth2Request oAuth2Request, + Authentication userAuthentication) { + return oAuth2Request; } }); client.setScope(Collections.singleton("smallscope")); - AuthorizationRequest authorizationRequest = getAuthorizationRequest("foo", "http://anywhere.com/", "mystate", - "bigscope"); - ModelAndView result = endpoint.authorize(model, "token", authorizationRequest.getAuthorizationParameters(), + OAuth2Request oAuth2Request = getOAuth2Request("foo", "http://anywhere.com/", "mystate", + "bigscope", Collections.singleton("token")); + ModelAndView result = endpoint.authorize(model, oAuth2Request.getRequestParameters(), sessionStatus, principal); String url = ((RedirectView) result.getView()).getUrl(); assertTrue("Wrong view: " + result, url.startsWith("http://anywhere.com/")); @@ -280,13 +321,13 @@ public boolean isApproved(AuthorizationRequest authorizationRequest, Authenticat @Test public void testImplicitUnapproved() throws Exception { endpoint.setTokenGranter(new TokenGranter() { - public OAuth2AccessToken grant(String grantType, AuthorizationRequest authorizationRequest) { + public OAuth2AccessToken grant(String grantType, OAuth2Request oAuth2Request) { return null; } }); - AuthorizationRequest authorizationRequest = getAuthorizationRequest("foo", "http://anywhere.com/", "mystate", - "myscope"); - ModelAndView result = endpoint.authorize(model, "token", authorizationRequest.getAuthorizationParameters(), + OAuth2Request oAuth2Request = getOAuth2Request("foo", "http://anywhere.com/", "mystate", + "myscope", Collections.singleton("token")); + ModelAndView result = endpoint.authorize(model, oAuth2Request.getRequestParameters(), sessionStatus, principal); assertEquals("forward:/oauth/confirm_access", result.getViewName()); } @@ -294,23 +335,27 @@ public OAuth2AccessToken grant(String grantType, AuthorizationRequest authorizat @Test public void testImplicitError() throws Exception { endpoint.setUserApprovalHandler(new UserApprovalHandler() { - public AuthorizationRequest updateBeforeApproval(AuthorizationRequest authorizationRequest, + public OAuth2Request checkForPreApproval(OAuth2Request oAuth2Request, Authentication userAuthentication) { + return oAuth2Request; + } + + public OAuth2Request updateAfterApproval(OAuth2Request oAuth2Request, Authentication userAuthentication) { - return authorizationRequest; + return oAuth2Request; } - public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { + public boolean isApproved(OAuth2Request oAuth2Request, Authentication userAuthentication) { return true; } }); endpoint.setTokenGranter(new TokenGranter() { - public OAuth2AccessToken grant(String grantType, AuthorizationRequest authorizationRequest) { + public OAuth2AccessToken grant(String grantType, OAuth2Request oAuth2Request) { return null; } }); - AuthorizationRequest authorizationRequest = getAuthorizationRequest("foo", "http://anywhere.com/", "mystate", - "myscope"); - ModelAndView result = endpoint.authorize(model, "token", authorizationRequest.getAuthorizationParameters(), + OAuth2Request oAuth2Request = getOAuth2Request("foo", "http://anywhere.com/", "mystate", + "myscope", Collections.singleton("token")); + ModelAndView result = endpoint.authorize(model, oAuth2Request.getRequestParameters(), sessionStatus, principal); String url = ((RedirectView) result.getView()).getUrl(); @@ -322,17 +367,21 @@ public OAuth2AccessToken grant(String grantType, AuthorizationRequest authorizat @Test public void testApproveOrDeny() throws Exception { - DefaultAuthorizationRequest request = getAuthorizationRequest("foo", "http://anywhere.com/", null, null); + OAuth2Request request = getOAuth2Request("foo", "http://anywhere.com/", null, null, Collections.singleton("code")); request.setApproved(true); + Map approvalParameters = new HashMap(); + approvalParameters.put("user_oauth_approval", "true"); model.put("authorizationRequest", request); - View result = endpoint.approveOrDeny(null, model, sessionStatus, principal); + View result = endpoint.approveOrDeny(approvalParameters, model, sessionStatus, principal); assertTrue("Wrong view: " + result, ((RedirectView) result).getUrl().startsWith("http://anywhere.com/")); } @Test public void testApprovalDenied() throws Exception { - model.put("authorizationRequest", getAuthorizationRequest("foo", "http://anywhere.com/", null, null)); - View result = endpoint.approveOrDeny(null, model, sessionStatus, principal); + model.put("authorizationRequest", getOAuth2Request("foo", "http://anywhere.com/", null, null, Collections.singleton("code"))); + Map approvalParameters = new HashMap(); + approvalParameters.put("user_oauth_approval", "false"); + View result = endpoint.approveOrDeny(approvalParameters, model, sessionStatus, principal); String url = ((RedirectView) result).getUrl(); assertTrue("Wrong view: " + result, url.startsWith("http://anywhere.com/")); assertTrue("Wrong view: " + result, url.contains("error=access_denied")); @@ -340,8 +389,8 @@ public void testApprovalDenied() throws Exception { @Test public void testDirectApproval() throws Exception { - ModelAndView result = endpoint.authorize(model, "code", - getAuthorizationRequest("foo", "http://anywhere.com/", null, null).getAuthorizationParameters(), + ModelAndView result = endpoint.authorize(model, + getOAuth2Request("foo", "http://anywhere.com/", null, null, Collections.singleton("code")).getRequestParameters(), sessionStatus, principal); // Should go to approval page (SECOAUTH-191) assertFalse(result.getView() instanceof RedirectView); @@ -349,41 +398,27 @@ public void testDirectApproval() throws Exception { @Test public void testRedirectUriOptionalForAuthorization() throws Exception { - ModelAndView result = endpoint.authorize(model, "code", getAuthorizationRequest("foo", null, null, null) - .getAuthorizationParameters(), sessionStatus, principal); + ModelAndView result = endpoint.authorize(model, getOAuth2Request("foo", null, null, null, Collections.singleton("code")) + .getRequestParameters(), sessionStatus, principal); // RedirectUri parameter should be null (SECOAUTH-333), however the resolvedRedirectUri not - DefaultAuthorizationRequest authorizationRequest = (DefaultAuthorizationRequest) result.getModelMap().get( + OAuth2Request oAuth2Request = (OAuth2Request) result.getModelMap().get( "authorizationRequest"); - assertNull(authorizationRequest.getAuthorizationParameters().get(REDIRECT_URI)); - assertEquals("http://anywhere.com/", authorizationRequest.getRedirectUri()); + assertNull(oAuth2Request.getRequestParameters().get(REDIRECT_URI)); + assertEquals("http://anywhere.com/", oAuth2Request.getRedirectUri()); } - @Test - public void testApproveOrDenyWithAuthorizationRequestWithoutRedirectUri() throws Exception { - DefaultAuthorizationRequest request = getAuthorizationRequest("foo", null, null, null); + /** + * Ensure that if the approval endpoint is called without a resolved redirect URI, the request fails. + * @throws Exception + */ + @Test(expected = InvalidRequestException.class) + public void testApproveOrDenyWithOAuth2RequestWithoutRedirectUri() throws Exception { + OAuth2Request request = getOAuth2Request("foo", null, null, null, Collections.singleton("code")); request.setApproved(true); + Map approvalParameters = new HashMap(); + approvalParameters.put("user_oauth_approval", "true"); model.put("authorizationRequest", request); - View result = endpoint.approveOrDeny(null, model, sessionStatus, principal); - assertTrue("Redirect view with code: " + result, - ((RedirectView) result).getUrl().startsWith("http://anywhere.com/?code=")); - } - - @Test - public void testAuthorizeWithNoRedirectUri() { - client.setRegisteredRedirectUri(Collections. emptySet()); - DefaultAuthorizationRequest request = getAuthorizationRequest("foo", null, null, null); - endpoint.setRedirectResolver(new RedirectResolver() { - public String resolveRedirect(String requestedRedirect, ClientDetails client) throws OAuth2Exception { - return null; - } - }); - try { - model.put("authorizationRequest", request); - endpoint.approveOrDeny(null, model, sessionStatus, principal); - fail("Contract of RedirectResolver is to return not-null redirecturi"); - } - catch (RedirectMismatchException e) { - } + endpoint.approveOrDeny(approvalParameters, model, sessionStatus, principal); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestTokenEndpoint.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestTokenEndpoint.java index 792ce4611..a5c5ec121 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestTokenEndpoint.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestTokenEndpoint.java @@ -37,10 +37,11 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.provider.AuthorizationRequest; -import org.springframework.security.oauth2.provider.AuthorizationRequestManager; +import org.springframework.security.oauth2.common.util.OAuth2Utils; +import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; -import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; import org.springframework.security.oauth2.provider.TokenGranter; /** @@ -54,28 +55,38 @@ public class TestTokenEndpoint { private TokenGranter tokenGranter; @Mock - private AuthorizationRequestManager authorizationRequestFactory; + private OAuth2RequestFactory authorizationRequestFactory; @Mock private ClientDetailsService clientDetailsService; + private OAuth2Request createFromParameters(Map authorizationParameters) { + OAuth2Request request = new OAuth2Request(authorizationParameters, Collections. emptyMap(), + authorizationParameters.get(OAuth2Request.CLIENT_ID), + OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Request.SCOPE)), null, + null, false, authorizationParameters.get(OAuth2Request.STATE), + authorizationParameters.get(OAuth2Request.REDIRECT_URI), + OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Request.RESPONSE_TYPE))); + return request; + } + @Test public void testGetAccessTokenWithNoClientId() { TokenEndpoint endpoint = new TokenEndpoint(); endpoint.setTokenGranter(tokenGranter); - endpoint.setAuthorizationRequestManager(authorizationRequestFactory); + endpoint.setOAuth2RequestFactory(authorizationRequestFactory); endpoint.setClientDetailsService(clientDetailsService); HashMap parameters = new HashMap(); OAuth2AccessToken expectedToken = new DefaultOAuth2AccessToken("FOO"); - when(tokenGranter.grant(Mockito.eq("authorization_code"), Mockito.any(AuthorizationRequest.class))).thenReturn( + when(tokenGranter.grant(Mockito.eq("authorization_code"), Mockito.any(OAuth2Request.class))).thenReturn( expectedToken); @SuppressWarnings("unchecked") Map anyMap = Mockito.any(Map.class); - when(authorizationRequestFactory.createAuthorizationRequest(anyMap)).thenReturn( - new DefaultAuthorizationRequest(parameters)); + when(authorizationRequestFactory.createOAuth2Request(anyMap)).thenReturn( + createFromParameters(parameters)); ResponseEntity response = endpoint.getAccessToken(new UsernamePasswordAuthenticationToken( null, null, Collections.singleton(new SimpleGrantedAuthority("ROLE_CLIENT"))), "authorization_code", @@ -91,24 +102,31 @@ public void testGetAccessTokenWithNoClientId() { @Test public void testGetAccessTokenWithScope() { + String clientId = "client"; + BaseClientDetails clientDetails = new BaseClientDetails(); + clientDetails.setClientId(clientId); + + when(clientDetailsService.loadClientByClientId(clientId)).thenReturn(clientDetails); + TokenEndpoint endpoint = new TokenEndpoint(); endpoint.setTokenGranter(tokenGranter); - endpoint.setAuthorizationRequestManager(authorizationRequestFactory); + endpoint.setOAuth2RequestFactory(authorizationRequestFactory); endpoint.setClientDetailsService(clientDetailsService); HashMap parameters = new HashMap(); + parameters.put("client_id", clientId); parameters.put("scope", "read"); parameters.put("grant_type", "authorization_code"); parameters.put("code", "kJAHDFG"); OAuth2AccessToken expectedToken = new DefaultOAuth2AccessToken("FOO"); - ArgumentCaptor captor = ArgumentCaptor.forClass(AuthorizationRequest.class); + ArgumentCaptor captor = ArgumentCaptor.forClass(OAuth2Request.class); when(tokenGranter.grant(Mockito.eq("authorization_code"), captor.capture())).thenReturn(expectedToken); @SuppressWarnings("unchecked") Map anyMap = Mockito.any(Map.class); - when(authorizationRequestFactory.createAuthorizationRequest(anyMap)).thenReturn( - new DefaultAuthorizationRequest(parameters)); - + when(authorizationRequestFactory.createOAuth2Request(anyMap)).thenReturn( + createFromParameters(parameters)); + ResponseEntity response = endpoint.getAccessToken(new UsernamePasswordAuthenticationToken( null, null, Collections.singleton(new SimpleGrantedAuthority("ROLE_CLIENT"))), "authorization_code", parameters); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestTokenEndpointAuthenticationFilter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestTokenEndpointAuthenticationFilter.java index 80ec66dd4..58bdaaf07 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestTokenEndpointAuthenticationFilter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestTokenEndpointAuthenticationFilter.java @@ -31,6 +31,12 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; +import org.springframework.security.oauth2.provider.BaseClientDetails; +import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.DefaultOAuth2RequestFactory; import org.springframework.security.oauth2.provider.OAuth2Authentication; /** @@ -46,6 +52,17 @@ public class TestTokenEndpointAuthenticationFilter { private MockFilterChain chain = new MockFilterChain(); private AuthenticationManager authenticationManager = Mockito.mock(AuthenticationManager.class); + + private BaseClientDetails client = new BaseClientDetails("foo", "resource", "scope", "authorization_code", + "ROLE_CLIENT"); + + private ClientDetailsService clientDetailsService = new ClientDetailsService() { + public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exception { + return client; + } + }; + + private OAuth2RequestFactory oAuth2RequestFactory = new DefaultOAuth2RequestFactory(clientDetailsService); @Before public void init() { @@ -63,10 +80,11 @@ public void close() { @Test public void testPasswordGrant() throws Exception { request.setParameter("grant_type", "password"); + request.setParameter("client_id", "foo"); Mockito.when(authenticationManager.authenticate(Mockito. any())).thenReturn( new UsernamePasswordAuthenticationToken("foo", "bar", AuthorityUtils .commaSeparatedStringToAuthorityList("ROLE_USER"))); - TokenEndpointAuthenticationFilter filter = new TokenEndpointAuthenticationFilter(authenticationManager); + TokenEndpointAuthenticationFilter filter = new TokenEndpointAuthenticationFilter(authenticationManager, oAuth2RequestFactory); filter.doFilter(request, response, chain); Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); assertTrue(authentication instanceof OAuth2Authentication); @@ -81,7 +99,7 @@ public void testPasswordGrantWithUnAuthenticatedClient() throws Exception { Mockito.when(authenticationManager.authenticate(Mockito. any())).thenReturn( new UsernamePasswordAuthenticationToken("foo", "bar", AuthorityUtils .commaSeparatedStringToAuthorityList("ROLE_USER"))); - TokenEndpointAuthenticationFilter filter = new TokenEndpointAuthenticationFilter(authenticationManager); + TokenEndpointAuthenticationFilter filter = new TokenEndpointAuthenticationFilter(authenticationManager, oAuth2RequestFactory); filter.doFilter(request, response, chain); Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); assertTrue(authentication instanceof OAuth2Authentication); @@ -90,7 +108,7 @@ public void testPasswordGrantWithUnAuthenticatedClient() throws Exception { @Test public void testNoGrantType() throws Exception { - TokenEndpointAuthenticationFilter filter = new TokenEndpointAuthenticationFilter(authenticationManager); + TokenEndpointAuthenticationFilter filter = new TokenEndpointAuthenticationFilter(authenticationManager, oAuth2RequestFactory); filter.doFilter(request, response, chain); // Just the client assertTrue(SecurityContextHolder.getContext().getAuthentication() instanceof UsernamePasswordAuthenticationToken); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestWhitelabelApprovalEndpoint.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestWhitelabelApprovalEndpoint.java index b7e56b57d..dbc91e4dd 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestWhitelabelApprovalEndpoint.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestWhitelabelApprovalEndpoint.java @@ -16,6 +16,7 @@ import static org.junit.Assert.assertTrue; +import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -23,7 +24,8 @@ import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.security.oauth2.common.exceptions.InvalidClientException; -import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; +import org.springframework.security.oauth2.common.util.OAuth2Utils; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.web.servlet.ModelAndView; /** @@ -37,12 +39,22 @@ public class TestWhitelabelApprovalEndpoint { private MockHttpServletRequest request = new MockHttpServletRequest(); private MockHttpServletResponse response = new MockHttpServletResponse(); + private OAuth2Request createFromParameters(Map authorizationParameters) { + OAuth2Request request = new OAuth2Request(authorizationParameters, Collections. emptyMap(), + authorizationParameters.get(OAuth2Request.CLIENT_ID), + OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Request.SCOPE)), null, + null, false, authorizationParameters.get(OAuth2Request.STATE), + authorizationParameters.get(OAuth2Request.REDIRECT_URI), + OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Request.RESPONSE_TYPE))); + return request; + } + @Test public void testApprovalPage() throws Exception { request.setContextPath("/foo"); parameters.put("client_id", "client"); HashMap model = new HashMap(); - model.put("authorizationRequest",new DefaultAuthorizationRequest(parameters)); + model.put("authorizationRequest", createFromParameters(parameters)); ModelAndView result = endpoint.getAccessConfirmation(model); result.getView().render(result.getModel(), request , response); String content = response.getContentAsString(); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2MethodSecurityExpressionHandler.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2MethodSecurityExpressionHandler.java index c383cd3c9..9d235dd5f 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2MethodSecurityExpressionHandler.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2MethodSecurityExpressionHandler.java @@ -27,9 +27,8 @@ import org.springframework.expression.Expression; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.BaseClientDetails; -import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.util.SimpleMethodInvocation; import org.springframework.util.ReflectionUtils; @@ -44,10 +43,10 @@ public class TestOAuth2MethodSecurityExpressionHandler { @Test public void testOauthClient() throws Exception { - DefaultAuthorizationRequest clientAuthentication = new DefaultAuthorizationRequest("foo", + OAuth2Request clientAuthentication = new OAuth2Request("foo", Collections.singleton("read")); clientAuthentication - .addClientDetails(new BaseClientDetails("foo", "", "", "client_credentials", "ROLE_CLIENT")); + .setResourceIdsAndAuthoritiesFromClientDetails(new BaseClientDetails("foo", "", "", "client_credentials", "ROLE_CLIENT")); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); MethodInvocation invocation = new SimpleMethodInvocation(this, ReflectionUtils.findMethod(getClass(), @@ -60,7 +59,7 @@ public void testOauthClient() throws Exception { @Test public void testScopes() throws Exception { - AuthorizationRequest clientAuthentication = new DefaultAuthorizationRequest("foo", + OAuth2Request clientAuthentication = new OAuth2Request("foo", Collections.singleton("read")); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); @@ -100,10 +99,10 @@ public void testReEvaluationWithDifferentRoot() throws Exception { Authentication clientAuthentication = new UsernamePasswordAuthenticationToken("foo", "bar"); EvaluationContext context = handler.createEvaluationContext(clientAuthentication, invocation); assertFalse((Boolean) expression.getValue(context)); - DefaultAuthorizationRequest authorizationRequest = new DefaultAuthorizationRequest("foo", + OAuth2Request oAuth2Request = new OAuth2Request("foo", Collections.singleton("read")); - authorizationRequest.setApproved(true); - OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(authorizationRequest, null); + oAuth2Request.setApproved(true); + OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request, null); EvaluationContext anotherContext = handler.createEvaluationContext(oAuth2Authentication, invocation); assertTrue((Boolean) expression.getValue(anotherContext)); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2SecurityExpressionMethods.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2SecurityExpressionMethods.java index 671584e18..7bce296fb 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2SecurityExpressionMethods.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2SecurityExpressionMethods.java @@ -26,9 +26,8 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.BaseClientDetails; -import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; import org.springframework.security.oauth2.provider.OAuth2Authentication; /** @@ -39,10 +38,10 @@ public class TestOAuth2SecurityExpressionMethods { @Test public void testOauthClient() throws Exception { - DefaultAuthorizationRequest clientAuthentication = new DefaultAuthorizationRequest("foo", + OAuth2Request clientAuthentication = new OAuth2Request("foo", Collections.singleton("read")); clientAuthentication - .addClientDetails(new BaseClientDetails("foo", "", "", "client_credentials", "ROLE_CLIENT")); + .setResourceIdsAndAuthoritiesFromClientDetails(new BaseClientDetails("foo", "", "", "client_credentials", "ROLE_CLIENT")); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); assertTrue(new OAuth2SecurityExpressionMethods(oAuth2Authentication, true).clientHasAnyRole("ROLE_CLIENT")); @@ -50,7 +49,7 @@ public void testOauthClient() throws Exception { @Test public void testScopes() throws Exception { - AuthorizationRequest clientAuthentication = new DefaultAuthorizationRequest("foo", + OAuth2Request clientAuthentication = new OAuth2Request("foo", Collections.singleton("read")); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); @@ -60,7 +59,7 @@ public void testScopes() throws Exception { @Test public void testScopesFalse() throws Exception { - AuthorizationRequest clientAuthentication = new DefaultAuthorizationRequest("foo", + OAuth2Request clientAuthentication = new OAuth2Request("foo", Collections.singleton("read")); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); @@ -70,7 +69,7 @@ public void testScopesFalse() throws Exception { @Test(expected = AccessDeniedException.class) public void testScopesWithException() throws Exception { - AuthorizationRequest clientAuthentication = new DefaultAuthorizationRequest("foo", + OAuth2Request clientAuthentication = new OAuth2Request("foo", Collections.singleton("read")); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); @@ -79,7 +78,7 @@ public void testScopesWithException() throws Exception { @Test(expected = AccessDeniedException.class) public void testInsufficientScope() throws Exception { - AuthorizationRequest clientAuthentication = new DefaultAuthorizationRequest("foo", + OAuth2Request clientAuthentication = new OAuth2Request("foo", Collections.singleton("read")); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); @@ -89,7 +88,7 @@ public void testInsufficientScope() throws Exception { @Test public void testSufficientScope() throws Exception { - AuthorizationRequest clientAuthentication = new DefaultAuthorizationRequest("foo", + OAuth2Request clientAuthentication = new OAuth2Request("foo", Collections.singleton("read")); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); @@ -99,7 +98,7 @@ public void testSufficientScope() throws Exception { @Test public void testSufficientScopeWithNoPreviousScopeDecision() throws Exception { - DefaultAuthorizationRequest clientAuthentication = new DefaultAuthorizationRequest("foo", + OAuth2Request clientAuthentication = new OAuth2Request("foo", Collections.singleton("read")); clientAuthentication.setApproved(true); Authentication userAuthentication = null; @@ -116,7 +115,7 @@ public void testNonOauthClient() throws Exception { @Test public void testClientOnly() throws Exception { - DefaultAuthorizationRequest request = new DefaultAuthorizationRequest("foo", Collections.singleton("read")); + OAuth2Request request = new OAuth2Request("foo", Collections.singleton("read")); request.setApproved(true); Authentication userAuthentication = new UsernamePasswordAuthenticationToken("foo", "bar", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"))); @@ -127,7 +126,7 @@ public void testClientOnly() throws Exception { @Test public void testOAuthUser() throws Exception { - DefaultAuthorizationRequest clientAuthentication = new DefaultAuthorizationRequest("foo", + OAuth2Request clientAuthentication = new OAuth2Request("foo", Collections.singleton("read")); clientAuthentication.setApproved(true); Authentication userAuthentication = new UsernamePasswordAuthenticationToken("foo", "bar", diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2WebSecurityExpressionHandler.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2WebSecurityExpressionHandler.java index 2dadda223..aeb40fa5a 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2WebSecurityExpressionHandler.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2WebSecurityExpressionHandler.java @@ -25,9 +25,8 @@ import org.springframework.expression.Expression; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.BaseClientDetails; -import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.web.FilterInvocation; @@ -41,8 +40,8 @@ public class TestOAuth2WebSecurityExpressionHandler { @Test public void testOauthClient() throws Exception { - DefaultAuthorizationRequest clientAuthentication = new DefaultAuthorizationRequest("foo", Collections.singleton("read")); - clientAuthentication.addClientDetails(new BaseClientDetails("foo", "", "", "client_credentials", "ROLE_CLIENT")); + OAuth2Request clientAuthentication = new OAuth2Request("foo", Collections.singleton("read")); + clientAuthentication.setResourceIdsAndAuthoritiesFromClientDetails(new BaseClientDetails("foo", "", "", "client_credentials", "ROLE_CLIENT")); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); FilterInvocation invocation = new FilterInvocation("/foo", "GET"); @@ -52,7 +51,7 @@ public void testOauthClient() throws Exception { @Test public void testScopes() throws Exception { - AuthorizationRequest clientAuthentication = new DefaultAuthorizationRequest("foo", Collections.singleton("read")); + OAuth2Request clientAuthentication = new OAuth2Request("foo", Collections.singleton("read")); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); FilterInvocation invocation = new FilterInvocation("/foo", "GET"); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/TestResourceOwnerPasswordTokenGranter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/TestResourceOwnerPasswordTokenGranter.java index 747e353d1..a84e274be 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/TestResourceOwnerPasswordTokenGranter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/TestResourceOwnerPasswordTokenGranter.java @@ -15,6 +15,7 @@ import static org.junit.Assert.assertTrue; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -29,11 +30,11 @@ import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; -import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.common.util.OAuth2Utils; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; -import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.token.DefaultTokenServices; import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; @@ -61,7 +62,17 @@ public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exceptio } }; - private AuthorizationRequest authorizationRequest; + private OAuth2Request createFromParameters(Map authorizationParameters) { + OAuth2Request request = new OAuth2Request(authorizationParameters, Collections. emptyMap(), + authorizationParameters.get(OAuth2Request.CLIENT_ID), + OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Request.SCOPE)), null, + null, false, authorizationParameters.get(OAuth2Request.STATE), + authorizationParameters.get(OAuth2Request.REDIRECT_URI), + OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Request.RESPONSE_TYPE))); + return request; + } + + private OAuth2Request oAuth2Request; public TestResourceOwnerPasswordTokenGranter() { providerTokenServices.setTokenStore(new InMemoryTokenStore()); @@ -69,14 +80,14 @@ public TestResourceOwnerPasswordTokenGranter() { parameters.put("username", "foo"); parameters.put("password", "bar"); parameters.put("client_id", "client"); - authorizationRequest = new DefaultAuthorizationRequest(parameters); + oAuth2Request = createFromParameters(parameters); } @Test public void testSunnyDay() { ResourceOwnerPasswordTokenGranter granter = new ResourceOwnerPasswordTokenGranter(authenticationManager, providerTokenServices, clientDetailsService); - OAuth2AccessToken token = granter.grant("password", authorizationRequest); + OAuth2AccessToken token = granter.grant("password", oAuth2Request); OAuth2Authentication authentication = providerTokenServices.loadAuthentication(token.getValue()); assertTrue(authentication.isAuthenticated()); } @@ -88,7 +99,7 @@ public Authentication authenticate(Authentication authentication) throws Authent throw new BadCredentialsException("test"); } }, providerTokenServices, clientDetailsService); - granter.grant("password", authorizationRequest); + granter.grant("password", oAuth2Request); } @Test(expected = InvalidGrantException.class) @@ -98,7 +109,7 @@ public Authentication authenticate(Authentication authentication) throws Authent throw new LockedException("test"); } }, providerTokenServices, clientDetailsService); - granter.grant("password", authorizationRequest); + granter.grant("password", oAuth2Request); } @Test(expected = InvalidGrantException.class) @@ -106,7 +117,7 @@ public void testUnauthenticated() { validUser = new UsernamePasswordAuthenticationToken("foo", "bar"); ResourceOwnerPasswordTokenGranter granter = new ResourceOwnerPasswordTokenGranter(authenticationManager, providerTokenServices, clientDetailsService); - granter.grant("password", authorizationRequest); + granter.grant("password", oAuth2Request); } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractTestDefaultTokenServices.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractTestDefaultTokenServices.java index e3f603d46..e5b9cd6ca 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractTestDefaultTokenServices.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractTestDefaultTokenServices.java @@ -18,10 +18,10 @@ import org.springframework.security.oauth2.common.OAuth2RefreshToken; import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; -import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; import org.springframework.security.oauth2.provider.OAuth2Authentication; /** @@ -81,7 +81,7 @@ public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentica OAuth2AccessToken accessToken = getTokenServices().createAccessToken(createAuthentication()); assertTrue(accessToken.getValue().startsWith("I'mEnhanced")); OAuth2AccessToken refreshedAccessToken = getTokenServices().refreshAccessToken( - accessToken.getRefreshToken().getValue(), new DefaultAuthorizationRequest("id", null)); + accessToken.getRefreshToken().getValue(), new OAuth2Request("id", null)); assertTrue(refreshedAccessToken.getValue().startsWith("I'mEnhanced")); } @@ -91,7 +91,7 @@ public void testRefreshedTokenHasScopes() throws Exception { new Date(System.currentTimeMillis() + 100000)); tokenStore.storeRefreshToken(expectedExpiringRefreshToken, createAuthentication()); OAuth2AccessToken refreshedAccessToken = getTokenServices().refreshAccessToken( - expectedExpiringRefreshToken.getValue(), new DefaultAuthorizationRequest("id", null)); + expectedExpiringRefreshToken.getValue(), new OAuth2Request("id", null)); assertEquals("[read]", refreshedAccessToken.getScope().toString()); } @@ -101,7 +101,7 @@ public void testRefreshedTokenInvalidWithWrongClient() throws Exception { new Date(System.currentTimeMillis() + 100000)); tokenStore.storeRefreshToken(expectedExpiringRefreshToken, createAuthentication()); OAuth2AccessToken refreshedAccessToken = getTokenServices().refreshAccessToken( - expectedExpiringRefreshToken.getValue(), new DefaultAuthorizationRequest("wrong", null)); + expectedExpiringRefreshToken.getValue(), new OAuth2Request("wrong", null)); assertEquals("[read]", refreshedAccessToken.getScope().toString()); } @@ -167,11 +167,11 @@ public void testOneAccessTokenPerAuthentication() throws Exception { @Test public void testOneAccessTokenPerUniqueAuthentication() throws Exception { getTokenServices().createAccessToken( - new OAuth2Authentication(new DefaultAuthorizationRequest("id", Collections.singleton("read")), + new OAuth2Authentication(new OAuth2Request("id", Collections.singleton("read")), new TestAuthentication("test2", false))); assertEquals(1, getAccessTokenCount()); getTokenServices().createAccessToken( - new OAuth2Authentication(new DefaultAuthorizationRequest("id", Collections.singleton("write")), + new OAuth2Authentication(new OAuth2Request("id", Collections.singleton("write")), new TestAuthentication("test2", false))); assertEquals(2, getAccessTokenCount()); } @@ -182,7 +182,7 @@ public void testRefreshTokenMaintainsState() throws Exception { OAuth2AccessToken accessToken = getTokenServices().createAccessToken(createAuthentication()); OAuth2RefreshToken expectedExpiringRefreshToken = accessToken.getRefreshToken(); OAuth2AccessToken refreshedAccessToken = getTokenServices().refreshAccessToken( - expectedExpiringRefreshToken.getValue(), new DefaultAuthorizationRequest("id", null)); + expectedExpiringRefreshToken.getValue(), new OAuth2Request("id", null)); assertNotNull(refreshedAccessToken); assertEquals(1, getAccessTokenCount()); } @@ -194,14 +194,14 @@ public void testNotReuseRefreshTokenMaintainsState() throws Exception { OAuth2AccessToken accessToken = getTokenServices().createAccessToken(createAuthentication()); OAuth2RefreshToken expectedExpiringRefreshToken = accessToken.getRefreshToken(); OAuth2AccessToken refreshedAccessToken = getTokenServices().refreshAccessToken( - expectedExpiringRefreshToken.getValue(), new DefaultAuthorizationRequest("id", null)); + expectedExpiringRefreshToken.getValue(), new OAuth2Request("id", null)); assertNotNull(refreshedAccessToken); assertEquals(1, getRefreshTokenCount()); } private OAuth2Authentication createAuthentication() { - return new OAuth2Authentication(new DefaultAuthorizationRequest("id", + return new OAuth2Authentication(new OAuth2Request("id", Collections.singleton("read")), new TestAuthentication("test2", false)); } @@ -214,6 +214,8 @@ protected DefaultTokenServices getTokenServices() { } protected static class TestAuthentication extends AbstractAuthenticationToken { + + private static final long serialVersionUID = 1L; private String principal; public TestAuthentication(String name, boolean authenticated) { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestDefaultTokenServicesWithInMemory.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestDefaultTokenServicesWithInMemory.java index 2c38cffde..02aaf9c15 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestDefaultTokenServicesWithInMemory.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestDefaultTokenServicesWithInMemory.java @@ -19,10 +19,10 @@ import org.springframework.security.oauth2.common.OAuth2RefreshToken; import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; -import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.test.util.ReflectionTestUtils; @@ -40,7 +40,7 @@ public class TestDefaultTokenServicesWithInMemory extends AbstractTestDefaultTok @Test public void testExpiredToken() throws Exception { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new DefaultAuthorizationRequest("id", + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new OAuth2Request("id", Collections.singleton("read")), new TestAuthentication("test2", false)); DefaultOAuth2AccessToken firstAccessToken = (DefaultOAuth2AccessToken) getTokenServices().createAccessToken( expectedAuthentication); @@ -53,7 +53,7 @@ public void testExpiredToken() throws Exception { @Test public void testExpiredRefreshToken() throws Exception { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new DefaultAuthorizationRequest("id", + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new OAuth2Request("id", Collections.singleton("read")), new TestAuthentication("test2", false)); DefaultOAuth2AccessToken firstAccessToken = (DefaultOAuth2AccessToken) getTokenServices().createAccessToken( expectedAuthentication); @@ -64,12 +64,12 @@ public void testExpiredRefreshToken() throws Exception { firstAccessToken.setExpiration(new Date(System.currentTimeMillis() - 1000)); expected.expect(InvalidTokenException.class); expected.expectMessage("refresh token (expired)"); - getTokenServices().refreshAccessToken(firstAccessToken.getRefreshToken().getValue(), new DefaultAuthorizationRequest("id", null)); + getTokenServices().refreshAccessToken(firstAccessToken.getRefreshToken().getValue(), new OAuth2Request("id", null)); } @Test public void testExpiredRefreshTokenIsRenewedWithNewAccessToken() throws Exception { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new DefaultAuthorizationRequest("id", + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new OAuth2Request("id", Collections.singleton("read")), new TestAuthentication("test2", false)); DefaultOAuth2AccessToken firstAccessToken = (DefaultOAuth2AccessToken) getTokenServices().createAccessToken( expectedAuthentication); @@ -97,7 +97,7 @@ public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exceptio return client; } }); - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new DefaultAuthorizationRequest("id", + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new OAuth2Request("id", Collections.singleton("read")), new TestAuthentication("test2", false)); DefaultOAuth2AccessToken firstAccessToken = (DefaultOAuth2AccessToken) getTokenServices().createAccessToken( expectedAuthentication); @@ -128,7 +128,7 @@ public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exceptio return client; } }); - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new DefaultAuthorizationRequest("id", + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new OAuth2Request("id", Collections.singleton("read")), new TestAuthentication("test2", false)); DefaultOAuth2AccessToken token = (DefaultOAuth2AccessToken) getTokenServices().createAccessToken( expectedAuthentication); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestInMemoryTokenStore.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestInMemoryTokenStore.java index dffb67417..3ff984c13 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestInMemoryTokenStore.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestInMemoryTokenStore.java @@ -7,7 +7,7 @@ import org.junit.Before; import org.junit.Test; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; -import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.OAuth2Authentication; /** @@ -31,7 +31,7 @@ public void createStore() { @Test public void testTokenCountConsistency() throws Exception { for (int i = 0; i <= 10; i++) { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new DefaultAuthorizationRequest("id" + i, + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new OAuth2Request("id" + i, null), new TestAuthentication("test", false)); DefaultOAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken" + i); expectedOAuth2AccessToken.setExpiration(new Date(System.currentTimeMillis() - 1000)); @@ -44,7 +44,7 @@ public void testTokenCountConsistency() throws Exception { @Test public void testTokenCountConsistentWithExpiryQueue() throws Exception { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new DefaultAuthorizationRequest("id", null), new TestAuthentication("test", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new OAuth2Request("id", null), new TestAuthentication("test", false)); DefaultOAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); expectedOAuth2AccessToken.setExpiration(new Date(System.currentTimeMillis()+10000)); for (int i = 0; i <= 10; i++) { @@ -57,7 +57,7 @@ public void testTokenCountConsistentWithExpiryQueue() throws Exception { public void testAutoFlush() throws Exception { getTokenStore().setFlushInterval(3); for (int i = 0; i <= 10; i++) { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new DefaultAuthorizationRequest("id" + i, + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new OAuth2Request("id" + i, null), new TestAuthentication("test", false)); DefaultOAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken" + i); expectedOAuth2AccessToken.setExpiration(new Date(System.currentTimeMillis() - 1000)); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestTokenStoreBase.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestTokenStoreBase.java index e0c65ca7b..b5331e67e 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestTokenStoreBase.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestTokenStoreBase.java @@ -27,7 +27,7 @@ import org.springframework.security.oauth2.common.DefaultOAuth2RefreshToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2RefreshToken; -import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.OAuth2Authentication; /** @@ -45,7 +45,7 @@ public void testReadingAuthenticationForTokenThatDoesNotExist() { @Test public void testStoreAccessToken() { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new DefaultAuthorizationRequest("id", null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new OAuth2Request("id", null), new TestAuthentication("test2", false)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); @@ -59,20 +59,20 @@ public void testStoreAccessToken() { @Test public void testRetrieveAccessToken() { - DefaultAuthorizationRequest authorizationRequest = new DefaultAuthorizationRequest("id", null); - authorizationRequest.setApproved(true); // normally the case for a persisted token - OAuth2Authentication authentication = new OAuth2Authentication(authorizationRequest, new TestAuthentication("test2", true)); + OAuth2Request oAuth2Request = new OAuth2Request("id", null); + oAuth2Request.setApproved(true); // normally the case for a persisted token + OAuth2Authentication authentication = new OAuth2Authentication(oAuth2Request, new TestAuthentication("test2", true)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, authentication); - authorizationRequest = new DefaultAuthorizationRequest("id", null); - authorizationRequest.setApproved(false); - authentication = new OAuth2Authentication(authorizationRequest, new TestAuthentication("test2", true)); + oAuth2Request = new OAuth2Request("id", null); + oAuth2Request.setApproved(false); + authentication = new OAuth2Authentication(oAuth2Request, new TestAuthentication("test2", true)); OAuth2AccessToken actualOAuth2AccessToken = getTokenStore().getAccessToken(authentication); assertEquals(expectedOAuth2AccessToken, actualOAuth2AccessToken); assertEquals(authentication.getUserAuthentication(), getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue()).getUserAuthentication()); // The authorizationRequest does not match because it is unapproved, but the token was granted to an approved request - assertFalse(authorizationRequest.equals(getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue()).getAuthorizationRequest())); + assertFalse(oAuth2Request.equals(getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue()).getAuthorizationRequest())); actualOAuth2AccessToken = getTokenStore().getAccessToken(authentication); assertEquals(expectedOAuth2AccessToken, actualOAuth2AccessToken); getTokenStore().removeAccessToken(expectedOAuth2AccessToken); @@ -83,7 +83,7 @@ public void testRetrieveAccessToken() { @Test public void testFindAccessTokensByUserName() { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new DefaultAuthorizationRequest("id", null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new OAuth2Request("id", null), new TestAuthentication("test2", false)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); @@ -93,7 +93,7 @@ public void testFindAccessTokensByUserName() { @Test public void testFindAccessTokensByClientId() { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new DefaultAuthorizationRequest("id", null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new OAuth2Request("id", null), new TestAuthentication("test2", false)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); @@ -108,7 +108,7 @@ public void testReadingAccessTokenForTokenThatDoesNotExist() { @Test public void testRefreshTokenIsNotStoredDuringAccessToken() { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new DefaultAuthorizationRequest("id", null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new OAuth2Request("id", null), new TestAuthentication("test2", false)); DefaultOAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); expectedOAuth2AccessToken.setRefreshToken(new DefaultOAuth2RefreshToken("refreshToken")); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); @@ -123,7 +123,7 @@ public void testRefreshTokenIsNotStoredDuringAccessToken() { public void testStoreRefreshToken() { DefaultOAuth2RefreshToken expectedExpiringRefreshToken = new DefaultExpiringOAuth2RefreshToken("testToken", new Date()); - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new DefaultAuthorizationRequest("id", null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new OAuth2Request("id", null), new TestAuthentication("test2", false)); getTokenStore().storeRefreshToken(expectedExpiringRefreshToken, expectedAuthentication); OAuth2RefreshToken actualExpiringRefreshToken = getTokenStore().readRefreshToken("testToken"); @@ -141,30 +141,30 @@ public void testReadingRefreshTokenForTokenThatDoesNotExist() { @Test public void testGetAccessTokenForDeletedUser() throws Exception { - DefaultAuthorizationRequest authorizationRequest = new DefaultAuthorizationRequest("id", null); - authorizationRequest.setApproved(true); // normally the case for a token being persisted - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(authorizationRequest, new TestAuthentication("test", true)); + OAuth2Request oAuth2Request = new OAuth2Request("id", null); + oAuth2Request.setApproved(true); // normally the case for a token being persisted + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(oAuth2Request, new TestAuthentication("test", true)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); assertEquals(expectedOAuth2AccessToken, getTokenStore().getAccessToken(expectedAuthentication)); assertEquals(expectedAuthentication, getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue())); - authorizationRequest = new DefaultAuthorizationRequest("id", null); - authorizationRequest.setApproved(false); // normally the case for a token being checked for approval - OAuth2Authentication anotherAuthentication = new OAuth2Authentication(authorizationRequest, new TestAuthentication("test", true)); + oAuth2Request = new OAuth2Request("id", null); + oAuth2Request.setApproved(false); // normally the case for a token being checked for approval + OAuth2Authentication anotherAuthentication = new OAuth2Authentication(oAuth2Request, new TestAuthentication("test", true)); assertEquals(expectedOAuth2AccessToken, getTokenStore().getAccessToken(anotherAuthentication)); // The generated key for the authentication is the same as before, but the two auths are not equal. This could // happen if there are 2 users in a system with the same username, or (more likely), if a user account was // deleted and re-created. assertEquals(anotherAuthentication.getUserAuthentication(), getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue()).getUserAuthentication()); // The authorizationRequest does not match because it is unapproved, but the token was granted to an approved request - assertFalse(authorizationRequest.equals(getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue()).getAuthorizationRequest())); + assertFalse(oAuth2Request.equals(getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue()).getAuthorizationRequest())); } @Test public void testRemoveRefreshToken() { OAuth2RefreshToken expectedExpiringRefreshToken = new DefaultExpiringOAuth2RefreshToken("testToken", new Date()); - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new DefaultAuthorizationRequest("id", null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new OAuth2Request("id", null), new TestAuthentication("test2", false)); getTokenStore().storeRefreshToken(expectedExpiringRefreshToken, expectedAuthentication); getTokenStore().removeRefreshToken(expectedExpiringRefreshToken); @@ -172,6 +172,8 @@ public void testRemoveRefreshToken() { } protected static class TestAuthentication extends AbstractAuthenticationToken { + + private static final long serialVersionUID = 1L; private String principal; public TestAuthentication(String name, boolean authenticated) { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/TestScopeVoter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/TestScopeVoter.java index 6ebf4d73d..312aaf48e 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/TestScopeVoter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/TestScopeVoter.java @@ -27,8 +27,7 @@ import org.springframework.security.access.SecurityConfig; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.provider.AuthorizationRequest; -import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.OAuth2Authentication; /** @@ -50,7 +49,7 @@ public void testAbstainIfNotOAuth2() throws Exception { @Test public void testDenyIfOAuth2AndExplictlyDenied() throws Exception { - AuthorizationRequest clientAuthentication = new DefaultAuthorizationRequest("foo", Collections.singleton("read")); + OAuth2Request clientAuthentication = new OAuth2Request("foo", Collections.singleton("read")); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); assertEquals( @@ -61,7 +60,7 @@ public void testDenyIfOAuth2AndExplictlyDenied() throws Exception { @Test public void testAccessGrantedIfScopesPresent() throws Exception { - AuthorizationRequest clientAuthentication = new DefaultAuthorizationRequest("foo", Collections.singleton("read")); + OAuth2Request clientAuthentication = new OAuth2Request("foo", Collections.singleton("read")); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); assertEquals( @@ -73,7 +72,7 @@ public void testAccessGrantedIfScopesPresent() throws Exception { @Test public void testAccessGrantedIfScopesPresentWithPrefix() throws Exception { voter.setScopePrefix("scope="); - AuthorizationRequest clientAuthentication = new DefaultAuthorizationRequest("foo", Collections.singleton("read")); + OAuth2Request clientAuthentication = new OAuth2Request("foo", Collections.singleton("read")); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); assertEquals( @@ -84,7 +83,7 @@ public void testAccessGrantedIfScopesPresentWithPrefix() throws Exception { @Test public void testAccessDeniedIfWrongScopesPresent() throws Exception { - AuthorizationRequest clientAuthentication = new DefaultAuthorizationRequest("foo", Collections.singleton("read")); + OAuth2Request clientAuthentication = new OAuth2Request("foo", Collections.singleton("read")); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); voter.setThrowException(false); @@ -96,7 +95,7 @@ public void testAccessDeniedIfWrongScopesPresent() throws Exception { @Test(expected = AccessDeniedException.class) public void testExceptionThrownIfWrongScopesPresent() throws Exception { - AuthorizationRequest clientAuthentication = new DefaultAuthorizationRequest("foo", Collections.singleton("read")); + OAuth2Request clientAuthentication = new OAuth2Request("foo", Collections.singleton("read")); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); assertEquals( diff --git a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/authorization-server-extras.xml b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/authorization-server-extras.xml index 005c1ced1..94c52daaa 100644 --- a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/authorization-server-extras.xml +++ b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/authorization-server-extras.xml @@ -7,7 +7,7 @@ @@ -34,7 +34,7 @@ - + From e90183603d63198975ccd430d25e56fe356175a6 Mon Sep 17 00:00:00 2001 From: Amanda Anganes Date: Wed, 5 Jun 2013 13:25:25 -0400 Subject: [PATCH 052/831] Updated samples to reflect auth request changes. --- .../sparklr/mvc/AccessConfirmationController.java | 4 ++-- .../sparklr/oauth/SparklrUserApprovalHandler.java | 11 +++-------- .../provider/TestAuthorizationCodeProvider.java | 4 ++-- .../oauth2/provider/TestImplicitProvider.java | 2 +- .../oauth/signature/TestGoogleCodeCompatibility.java | 4 ++-- 5 files changed, 10 insertions(+), 15 deletions(-) diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AccessConfirmationController.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AccessConfirmationController.java index 6d0980eb0..f241e4c2f 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AccessConfirmationController.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AccessConfirmationController.java @@ -3,9 +3,9 @@ import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.SessionAttributes; @@ -24,7 +24,7 @@ public class AccessConfirmationController { @RequestMapping("/oauth/confirm_access") public ModelAndView getAccessConfirmation(Map model) throws Exception { - AuthorizationRequest clientAuth = (AuthorizationRequest) model.remove("authorizationRequest"); + OAuth2Request clientAuth = (OAuth2Request) model.remove("authorizationRequest"); ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId()); model.put("auth_request", clientAuth); model.put("client", client); diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrUserApprovalHandler.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrUserApprovalHandler.java index 8911c7e81..3e5f319b1 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrUserApprovalHandler.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrUserApprovalHandler.java @@ -20,7 +20,7 @@ import java.util.HashSet; import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.approval.TokenServicesUserApprovalHandler; /** @@ -46,11 +46,6 @@ public void setUseTokenServices(boolean useTokenServices) { public void setAutoApproveClients(Collection autoApproveClients) { this.autoApproveClients = autoApproveClients; } - - @Override - public AuthorizationRequest updateBeforeApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { - return super.updateBeforeApproval(authorizationRequest, userAuthentication); - } /** * Allows automatic approval for a white list of clients in the implicit grant case. @@ -61,7 +56,7 @@ public AuthorizationRequest updateBeforeApproval(AuthorizationRequest authorizat * @return Whether the specified request has been approved by the current user. */ @Override - public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { + public boolean isApproved(OAuth2Request authorizationRequest, Authentication userAuthentication) { // If we are allowed to check existing approvals this will short circuit the decision if (useTokenServices && super.isApproved(authorizationRequest, userAuthentication)) { @@ -72,7 +67,7 @@ public boolean isApproved(AuthorizationRequest authorizationRequest, Authenticat return false; } - String flag = authorizationRequest.getApprovalParameters().get(AuthorizationRequest.USER_OAUTH_APPROVAL); + String flag = authorizationRequest.getApprovalParameters().get(OAuth2Request.USER_OAUTH_APPROVAL); boolean approved = flag != null && flag.toLowerCase().equals("true"); return approved diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationCodeProvider.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationCodeProvider.java index 446d33bfe..25b83b431 100755 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationCodeProvider.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationCodeProvider.java @@ -146,7 +146,7 @@ public void testUnauthenticatedAuthorizationRequestRedirectsToLogin() throws Exc AccessTokenRequest request = context.getAccessTokenRequest(); request.setCurrentUri("http://anywhere/"); - request.add(AuthorizationRequest.USER_OAUTH_APPROVAL, "true"); + request.add(OAuth2Request.USER_OAUTH_APPROVAL, "true"); String location = null; @@ -446,7 +446,7 @@ private void approveAccessTokenGrant(String currentUri, boolean approved) { assertNull(request.getAuthorizationCode()); // The approval (will be processed on the next attempt to obtain an access token)... - request.set(AuthorizationRequest.USER_OAUTH_APPROVAL, "" + approved); + request.set(OAuth2Request.USER_OAUTH_APPROVAL, "" + approved); } diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestImplicitProvider.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestImplicitProvider.java index 12c8819c4..02d2f334f 100644 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestImplicitProvider.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestImplicitProvider.java @@ -98,7 +98,7 @@ public void testPostForNonAutomaticApprovalToken() throws Exception { // ignore } // add user approval parameter for the second request - context.getAccessTokenRequest().add(AuthorizationRequest.USER_OAUTH_APPROVAL, "true"); + context.getAccessTokenRequest().add(OAuth2Request.USER_OAUTH_APPROVAL, "true"); assertNotNull(context.getAccessToken()); } diff --git a/spring-security-oauth/src/test/java/net/oauth/signature/TestGoogleCodeCompatibility.java b/spring-security-oauth/src/test/java/net/oauth/signature/TestGoogleCodeCompatibility.java index 4aa19520b..3d1d3af67 100644 --- a/spring-security-oauth/src/test/java/net/oauth/signature/TestGoogleCodeCompatibility.java +++ b/spring-security-oauth/src/test/java/net/oauth/signature/TestGoogleCodeCompatibility.java @@ -1,4 +1,4 @@ -/* +/** * Copyright 2008 Web Cohesion * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,7 +12,7 @@ * 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 net.oauth.signature; From 8bc1a43e3ea597714094c1dec45b260e9e4ecb77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionu=C8=9B=20G=2E=20Stan?= Date: Fri, 24 May 2013 15:13:32 +0300 Subject: [PATCH 053/831] Log IllegalArgumentException when failing to deserialize token --- .../oauth2/provider/token/JdbcTokenStore.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JdbcTokenStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JdbcTokenStore.java index e2766bb34..27e9edf71 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JdbcTokenStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JdbcTokenStore.java @@ -27,7 +27,7 @@ /** * Implementation of token services that stores tokens in a database. - * + * * @author Ken Dombeck * @author Luke Taylor * @author Dave Syer @@ -115,7 +115,7 @@ public OAuth2AccessToken mapRow(ResultSet rs, int rowNum) throws SQLException { } } catch (IllegalArgumentException e) { - LOG.error("Could not extract access token for authentication " + authentication); + LOG.error("Could not extract access token for authentication " + authentication, e); } if (accessToken != null @@ -158,7 +158,7 @@ public OAuth2AccessToken mapRow(ResultSet rs, int rowNum) throws SQLException { } } catch (IllegalArgumentException e) { - LOG.warn("Failed to deserialize access token for " + tokenValue); + LOG.warn("Failed to deserialize access token for " + tokenValue, e); removeAccessToken(tokenValue); } @@ -194,7 +194,7 @@ public OAuth2Authentication mapRow(ResultSet rs, int rowNum) throws SQLException } } catch (IllegalArgumentException e) { - LOG.warn("Failed to deserialize authentication for " + token); + LOG.warn("Failed to deserialize authentication for " + token, e); removeAccessToken(token); } @@ -224,7 +224,7 @@ public OAuth2RefreshToken mapRow(ResultSet rs, int rowNum) throws SQLException { } } catch (IllegalArgumentException e) { - LOG.warn("Failed to deserialize refresh token for token " + token); + LOG.warn("Failed to deserialize refresh token for token " + token, e); removeRefreshToken(token); } @@ -260,7 +260,7 @@ public OAuth2Authentication mapRow(ResultSet rs, int rowNum) throws SQLException } } catch (IllegalArgumentException e) { - LOG.warn("Failed to deserialize access token for " + value); + LOG.warn("Failed to deserialize access token for " + value, e); removeRefreshToken(value); } From 38c4f41a6d7781e97646b0a689ec64f322c87c77 Mon Sep 17 00:00:00 2001 From: Casey Lucas Date: Mon, 10 Jun 2013 13:53:46 -0500 Subject: [PATCH 054/831] fixes SECOAUTH-409 Prevent IllegalArgument exceptions when invalid requests (including invalid query strings) are encountered. An implication is that invalid requests cannot be redirected for oauth purposes. --- .../oauth2/client/filter/OAuth2ClientContextFilter.java | 9 ++++++++- .../client/filter/TestOAuth2ClientContextFilter.java | 8 ++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilter.java index 079a62b8d..8bb345548 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilter.java @@ -127,7 +127,14 @@ protected String calculateCurrentUri(HttpServletRequest request) throws Unsuppor if (legalSpaces) { builder.replaceQuery(queryString.replace("+", "%20")); } - UriComponents uri = builder.replaceQueryParam("code").build(true); + UriComponents uri = null; + try { + uri = builder.replaceQueryParam("code").build(true); + } catch (IllegalArgumentException ex) { + // ignore failures to parse the url (including query string). does't make sense + // for redirection purposes anyway. + return null; + } String query = uri.getQuery(); if (legalSpaces) { query = query.replace("%20", "+"); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/TestOAuth2ClientContextFilter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/TestOAuth2ClientContextFilter.java index c17505639..a1c025a49 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/TestOAuth2ClientContextFilter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/TestOAuth2ClientContextFilter.java @@ -56,4 +56,12 @@ public void testCurrentUriRemovingCodeInSecond() throws Exception { request.setQueryString("foo=bar&code=XXXX"); assertEquals("http://localhost/?foo=bar", filter.calculateCurrentUri(request)); } + + @Test + public void testCurrentUriWithInvalidQueryString() throws Exception { + OAuth2ClientContextFilter filter = new OAuth2ClientContextFilter(); + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setQueryString("foo=bar&code=XXXX&parm=%xx"); + assertEquals(null, filter.calculateCurrentUri(request)); + } } From 53c4095486d449b5d3aa22d4bf28afdf1c199d2a Mon Sep 17 00:00:00 2001 From: Amanda Anganes Date: Mon, 8 Jul 2013 14:31:25 +0100 Subject: [PATCH 055/831] Refactored request lifecycle Refactored AuthorizationRequest into three distinct classes, AuthorizationRequest, StoredRequest, and TokenRequest. Removed AuthorizationRequestHolder, now storing OAuth2Authentication everywhere. (Squashed pull request #79 by aanganes) --- .../mvc/AccessConfirmationController.java | 4 +- .../oauth/SparklrUserApprovalHandler.java | 7 +- .../main/webapp/WEB-INF/spring-servlet.xml | 5 + .../TestAuthorizationCodeProvider.java | 5 +- .../oauth2/provider/TestImplicitProvider.java | 3 +- .../AuthorizationCodeAccessTokenProvider.java | 9 +- .../oauth2/common/util/OAuth2Utils.java | 17 ++ ...thorizationServerBeanDefinitionParser.java | 27 +-- ...Request.java => AuthorizationRequest.java} | 29 +-- .../provider/CompositeTokenGranter.java | 2 +- .../provider/DefaultOAuth2RequestFactory.java | 43 ++++- .../oauth2/provider/OAuth2Authentication.java | 20 +-- .../oauth2/provider/OAuth2RequestFactory.java | 49 ++++- .../provider/OAuth2RequestValidator.java | 2 +- .../oauth2/provider/StoredOAuth2Request.java | 170 ++++++++++++++++++ .../oauth2/provider/TokenGranter.java | 2 +- .../oauth2/provider/TokenRequest.java | 87 +++++++++ .../approval/DefaultUserApprovalHandler.java | 19 +- .../TokenServicesUserApprovalHandler.java | 36 ++-- .../approval/UserApprovalHandler.java | 20 +-- .../OAuth2AuthenticationManager.java | 6 +- .../client/ClientCredentialsTokenGranter.java | 9 +- .../code/AuthorizationCodeServices.java | 5 +- .../code/AuthorizationCodeTokenGranter.java | 34 ++-- .../code/AuthorizationRequestHolder.java | 83 --------- .../InMemoryAuthorizationCodeServices.java | 10 +- .../code/JdbcAuthorizationCodeServices.java | 11 +- .../RandomValueAuthorizationCodeServices.java | 11 +- .../endpoint/AuthorizationEndpoint.java | 151 ++++++++-------- .../FrameworkEndpointHandlerMapping.java | 11 +- .../provider/endpoint/TokenEndpoint.java | 24 +-- .../TokenEndpointAuthenticationFilter.java | 17 +- .../expression/OAuth2ExpressionUtils.java | 6 +- .../implicit/ImplicitTokenGranter.java | 14 +- .../ResourceOwnerPasswordTokenGranter.java | 19 +- .../provider/refresh/RefreshTokenGranter.java | 13 +- .../provider/token/AbstractTokenGranter.java | 24 ++- .../AuthorizationServerTokenServices.java | 6 +- .../DefaultAuthenticationKeyGenerator.java | 4 +- .../provider/token/DefaultTokenServices.java | 39 ++-- .../provider/token/InMemoryTokenStore.java | 4 +- .../oauth2/provider/token/JdbcTokenStore.java | 2 +- .../oauth2/provider/vote/ScopeVoter.java | 9 +- ...2ClientAuthenticationProcessingFilter.java | 10 +- ...tAuthorizationServerCustomGrantParser.java | 4 +- .../provider/TestAuthorizationRequest.java | 67 ++++--- .../TestDefaultAuthorizationRequest.java | 66 +++---- ...estDefaultAuthorizationRequestManager.java | 4 +- .../provider/TestOAuth2Authentication.java | 7 +- .../TestDefaultUserApprovalHandler.java | 4 +- .../TestTokenServicesUserApprovalHandler.java | 27 ++- .../TestOAuth2AuthenticationManager.java | 7 +- ...tOAuth2AuthenticationProcessingFilter.java | 7 +- .../TestAuthorizationCodeServicesBase.java | 17 +- .../TestAuthorizationCodeTokenGranter.java | 154 ++++++++-------- .../code/TestAuthorizationRequestHolder.java | 13 +- .../endpoint/TestAuthorizationEndpoint.java | 168 ++++++++--------- .../provider/endpoint/TestTokenEndpoint.java | 38 ++-- .../TestWhitelabelApprovalEndpoint.java | 16 +- ...OAuth2MethodSecurityExpressionHandler.java | 24 ++- .../TestOAuth2SecurityExpressionMethods.java | 49 ++--- ...estOAuth2WebSecurityExpressionHandler.java | 13 +- ...TestResourceOwnerPasswordTokenGranter.java | 36 ++-- .../AbstractTestDefaultTokenServices.java | 30 ++-- .../TestDefaultTokenServicesWithInMemory.java | 31 ++-- .../token/TestInMemoryTokenStore.java | 13 +- .../provider/token/TestTokenStoreBase.java | 46 ++--- .../oauth2/provider/vote/TestScopeVoter.java | 13 +- .../config/authorization-server-extras.xml | 1 + 69 files changed, 1138 insertions(+), 795 deletions(-) rename spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/{OAuth2Request.java => AuthorizationRequest.java} (92%) create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/StoredOAuth2Request.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java delete mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationRequestHolder.java diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AccessConfirmationController.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AccessConfirmationController.java index f241e4c2f..30a50d18d 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AccessConfirmationController.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AccessConfirmationController.java @@ -5,7 +5,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; -import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.SessionAttributes; @@ -24,7 +24,7 @@ public class AccessConfirmationController { @RequestMapping("/oauth/confirm_access") public ModelAndView getAccessConfirmation(Map model) throws Exception { - OAuth2Request clientAuth = (OAuth2Request) model.remove("authorizationRequest"); + AuthorizationRequest clientAuth = (AuthorizationRequest) model.remove("authorizationRequest"); ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId()); model.put("auth_request", clientAuth); model.put("client", client); diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrUserApprovalHandler.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrUserApprovalHandler.java index 3e5f319b1..546491efb 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrUserApprovalHandler.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrUserApprovalHandler.java @@ -20,7 +20,8 @@ import java.util.HashSet; import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.common.util.OAuth2Utils; +import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.approval.TokenServicesUserApprovalHandler; /** @@ -56,7 +57,7 @@ public void setAutoApproveClients(Collection autoApproveClients) { * @return Whether the specified request has been approved by the current user. */ @Override - public boolean isApproved(OAuth2Request authorizationRequest, Authentication userAuthentication) { + public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { // If we are allowed to check existing approvals this will short circuit the decision if (useTokenServices && super.isApproved(authorizationRequest, userAuthentication)) { @@ -67,7 +68,7 @@ public boolean isApproved(OAuth2Request authorizationRequest, Authentication use return false; } - String flag = authorizationRequest.getApprovalParameters().get(OAuth2Request.USER_OAUTH_APPROVAL); + String flag = authorizationRequest.getApprovalParameters().get(OAuth2Utils.USER_OAUTH_APPROVAL); boolean approved = flag != null && flag.toLowerCase().equals("true"); return approved diff --git a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml index d34b56576..d9996d15c 100644 --- a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml +++ b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml @@ -124,6 +124,10 @@ + + + + @@ -131,6 +135,7 @@ + form = new LinkedMultiValueMap(); - if (request.containsKey(OAuth2Request.USER_OAUTH_APPROVAL)) { - form.set(OAuth2Request.USER_OAUTH_APPROVAL, - request.getFirst(OAuth2Request.USER_OAUTH_APPROVAL)); + if (request.containsKey(OAuth2Utils.USER_OAUTH_APPROVAL)) { + form.set(OAuth2Utils.USER_OAUTH_APPROVAL, + request.getFirst(OAuth2Utils.USER_OAUTH_APPROVAL)); } else { form.putAll(getParametersForAuthorizeRequest(resource, request)); @@ -320,7 +319,7 @@ protected UserApprovalRequiredException getUserApprovalSignal(AuthorizationCodeR String message = String.format("Do you approve the client '%s' to access your resources with scope=%s", resource.getClientId(), resource.getScope()); return new UserApprovalRequiredException(resource.getUserAuthorizationUri(), Collections.singletonMap( - OAuth2Request.USER_OAUTH_APPROVAL, message), resource.getClientId(), resource.getScope()); + OAuth2Utils.USER_OAUTH_APPROVAL, message), resource.getClientId(), resource.getScope()); } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/OAuth2Utils.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/OAuth2Utils.java index 7d91cab78..57d53d41b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/OAuth2Utils.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/OAuth2Utils.java @@ -31,6 +31,23 @@ */ public abstract class OAuth2Utils { + /** + * Constants to use while parsing parameter maps for OAuth2 requests + */ + public static final String CLIENT_ID = "client_id"; + + public static final String STATE = "state"; + + public static final String SCOPE = "scope"; + + public static final String REDIRECT_URI = "redirect_uri"; + + public static final String RESPONSE_TYPE = "response_type"; + + public static final String USER_OAUTH_APPROVAL = "user_oauth_approval"; + + public static final String GRANT_TYPE = "grant_type"; + /** * Parses a string parameter value into a set of strings. * diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/AuthorizationServerBeanDefinitionParser.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/AuthorizationServerBeanDefinitionParser.java index 53d42a024..459a64e0f 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/AuthorizationServerBeanDefinitionParser.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/AuthorizationServerBeanDefinitionParser.java @@ -16,13 +16,13 @@ import java.util.List; import org.springframework.beans.BeanMetadataElement; +import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.config.TypedStringValue; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.support.ManagedMap; import org.springframework.beans.factory.xml.ParserContext; -import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.security.config.BeanIds; import org.springframework.security.oauth2.provider.CompositeTokenGranter; import org.springframework.security.oauth2.provider.DefaultOAuth2RequestFactory; @@ -70,6 +70,15 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P BeanDefinitionBuilder authorizationEndpointBean = BeanDefinitionBuilder .rootBeanDefinition(AuthorizationEndpoint.class); + if (!StringUtils.hasText(oAuth2RequestFactoryRef)) { + oAuth2RequestFactoryRef = "oAuth2AuthorizationRequestManager"; + BeanDefinitionBuilder oAuth2RequestManager = BeanDefinitionBuilder + .rootBeanDefinition(DefaultOAuth2RequestFactory.class); + oAuth2RequestManager.addConstructorArgReference(clientDetailsRef); + parserContext.getRegistry().registerBeanDefinition(oAuth2RequestFactoryRef, + oAuth2RequestManager.getBeanDefinition()); + } + ManagedList tokenGranters = null; if (!StringUtils.hasText(tokenGranterRef)) { tokenGranterRef = "oauth2TokenGranter"; @@ -84,6 +93,7 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P boolean registerAuthorizationEndpoint = false; Element authorizationCodeElement = DomUtils.getChildElementByTagName(element, "authorization-code"); + if (authorizationCodeElement != null && !"true".equalsIgnoreCase(authorizationCodeElement.getAttribute("disabled"))) { // authorization code grant configuration. @@ -108,6 +118,7 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P authorizationEndpointBean.addPropertyReference("authorizationCodeServices", authorizationCodeServices); authorizationCodeTokenGranterBean.addConstructorArgReference(authorizationCodeServices); authorizationCodeTokenGranterBean.addConstructorArgReference(clientDetailsRef); + authorizationCodeTokenGranterBean.addConstructorArgReference(oAuth2RequestFactoryRef); if (StringUtils.hasText(clientTokenCacheRef)) { authorizationEndpointBean.addPropertyReference("clientTokenCache", clientTokenCacheRef); @@ -124,22 +135,15 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P registerAuthorizationEndpoint = true; } - if (!StringUtils.hasText(oAuth2RequestFactoryRef)) { - oAuth2RequestFactoryRef = "oAuth2AuthorizationRequestManager"; - BeanDefinitionBuilder oAuth2RequestManager = BeanDefinitionBuilder - .rootBeanDefinition(DefaultOAuth2RequestFactory.class); - oAuth2RequestManager.addConstructorArgReference(clientDetailsRef); - parserContext.getRegistry().registerBeanDefinition(oAuth2RequestFactoryRef, - oAuth2RequestManager.getBeanDefinition()); - } - if (tokenGranters != null) { Element refreshTokenElement = DomUtils.getChildElementByTagName(element, "refresh-token"); + if (refreshTokenElement != null && !"true".equalsIgnoreCase(refreshTokenElement.getAttribute("disabled"))) { BeanDefinitionBuilder refreshTokenGranterBean = BeanDefinitionBuilder .rootBeanDefinition(RefreshTokenGranter.class); refreshTokenGranterBean.addConstructorArgReference(tokenServicesRef); refreshTokenGranterBean.addConstructorArgReference(clientDetailsRef); + refreshTokenGranterBean.addConstructorArgReference(oAuth2RequestFactoryRef); tokenGranters.add(refreshTokenGranterBean.getBeanDefinition()); } Element implicitElement = DomUtils.getChildElementByTagName(element, "implicit"); @@ -148,6 +152,7 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P .rootBeanDefinition(ImplicitTokenGranter.class); implicitGranterBean.addConstructorArgReference(tokenServicesRef); implicitGranterBean.addConstructorArgReference(clientDetailsRef); + implicitGranterBean.addConstructorArgReference(oAuth2RequestFactoryRef); tokenGranters.add(implicitGranterBean.getBeanDefinition()); registerAuthorizationEndpoint = true; } @@ -158,6 +163,7 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P .rootBeanDefinition(ClientCredentialsTokenGranter.class); clientCredentialsGranterBean.addConstructorArgReference(tokenServicesRef); clientCredentialsGranterBean.addConstructorArgReference(clientDetailsRef); + clientCredentialsGranterBean.addConstructorArgReference(oAuth2RequestFactoryRef); tokenGranters.add(clientCredentialsGranterBean.getBeanDefinition()); } Element clientPasswordElement = DomUtils.getChildElementByTagName(element, "password"); @@ -172,6 +178,7 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P clientPasswordTokenGranter.addConstructorArgReference(authenticationManagerRef); clientPasswordTokenGranter.addConstructorArgReference(tokenServicesRef); clientPasswordTokenGranter.addConstructorArgReference(clientDetailsRef); + clientPasswordTokenGranter.addConstructorArgReference(oAuth2RequestFactoryRef); tokenGranters.add(clientPasswordTokenGranter.getBeanDefinition()); } List customGrantElements = DomUtils.getChildElementsByTagName(element, "custom-grant"); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java similarity index 92% rename from spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java rename to spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java index 8ac4b99ab..6ab430797 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java @@ -13,7 +13,7 @@ import org.springframework.security.oauth2.common.util.OAuth2Utils; /** - * Base class representing an OAuth2 authorization or token request. HTTP request parameters are stored in + * Base class representing an OAuth2 Authorization Request. HTTP request parameters are stored in * the parameters map, and any processing the server makes throughout the lifecycle of a request are stored * on individual properties. The original request parameters will remain available through the parameters * map. For convenience, constants are defined in order to get at those original values. However, the @@ -23,24 +23,12 @@ * @author Dave Syer * @author Amanda Anganes */ -public class OAuth2Request implements Serializable { +public class AuthorizationRequest implements Serializable { private static final long serialVersionUID = 1L; - - public static final String CLIENT_ID = "client_id"; - - public static final String STATE = "state"; - - public static final String SCOPE = "scope"; - - public static final String REDIRECT_URI = "redirect_uri"; - - public static final String RESPONSE_TYPE = "response_type"; - - public static final String USER_OAUTH_APPROVAL = "user_oauth_approval"; /** - * Map of parameters passed in to the Authorizatoin Endpoint or Token + * Map of parameters passed in to the Authorization Endpoint or Token * Endpoint, preserved unchanged from the original request. This map should * not be modified after initialization. In general, classes should not * retrieve values from this map directly, and should instead use the @@ -123,7 +111,7 @@ public class OAuth2Request implements Serializable { /** * Default constructor. */ - public OAuth2Request() { + public AuthorizationRequest() { } @@ -141,12 +129,11 @@ public OAuth2Request() { * @param redirectUri * @param responseTypes */ - public OAuth2Request(Map authorizationParameters, Map approvalParameters, + public AuthorizationRequest(Map authorizationParameters, Map approvalParameters, String clientId, Set scope, Set resourceIds, Collection authorities, boolean approved, String state, String redirectUri, Set responseTypes){ if (authorizationParameters != null) { - //this.authorizationParameters.putAll(authorizationParameters); this.requestParameters = Collections.unmodifiableMap(authorizationParameters); } if (approvalParameters != null) { @@ -177,7 +164,7 @@ public OAuth2Request(Map authorizationParameters, Map scopes) { + public AuthorizationRequest(String clientId, Collection scopes) { this.clientId = clientId; if (scopes!= null) { this.scope.addAll(scopes); @@ -356,10 +343,10 @@ public boolean equals(Object obj) { if (obj == null) { return false; } - if (!(obj instanceof OAuth2Request)) { + if (!(obj instanceof AuthorizationRequest)) { return false; } - OAuth2Request other = (OAuth2Request) obj; + AuthorizationRequest other = (AuthorizationRequest) obj; if (approvalParameters == null) { if (other.approvalParameters != null) { return false; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/CompositeTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/CompositeTokenGranter.java index 7c1ab4656..8cae0bdd1 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/CompositeTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/CompositeTokenGranter.java @@ -33,7 +33,7 @@ public CompositeTokenGranter(List tokenGranters) { this.tokenGranters = new ArrayList(tokenGranters); } - public OAuth2AccessToken grant(String grantType, OAuth2Request tokenRequest) { + public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) { for (TokenGranter granter : tokenGranters) { OAuth2AccessToken grant = granter.grant(grantType, tokenRequest); if (grant!=null) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestFactory.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestFactory.java index 447d632ed..962a8ff2b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestFactory.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestFactory.java @@ -29,18 +29,18 @@ public class DefaultOAuth2RequestFactory implements OAuth2RequestFactory { private final ClientDetailsService clientDetailsService; - + public DefaultOAuth2RequestFactory(ClientDetailsService clientDetailsService) { this.clientDetailsService = clientDetailsService; } - public OAuth2Request createOAuth2Request(Map authorizationParameters) { + public AuthorizationRequest createAuthorizationRequest(Map authorizationParameters) { - String clientId = authorizationParameters.get(OAuth2Request.CLIENT_ID); - Set scopes = OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Request.SCOPE)); - String state = authorizationParameters.get(OAuth2Request.STATE); - String redirectUri = authorizationParameters.get(OAuth2Request.REDIRECT_URI); - Set responseTypes = OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Request.RESPONSE_TYPE)); + String clientId = authorizationParameters.get(OAuth2Utils.CLIENT_ID); + Set scopes = OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Utils.SCOPE)); + String state = authorizationParameters.get(OAuth2Utils.STATE); + String redirectUri = authorizationParameters.get(OAuth2Utils.REDIRECT_URI); + Set responseTypes = OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Utils.RESPONSE_TYPE)); ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId); @@ -51,7 +51,7 @@ public OAuth2Request createOAuth2Request(Map authorizationParame scopes = clientDetails.getScope(); } - OAuth2Request request = new OAuth2Request(authorizationParameters, Collections. emptyMap(), + AuthorizationRequest request = new AuthorizationRequest(authorizationParameters, Collections. emptyMap(), clientId, scopes, null, null, false, state, redirectUri, responseTypes); request.setResourceIdsAndAuthoritiesFromClientDetails(clientDetails); @@ -60,4 +60,31 @@ public OAuth2Request createOAuth2Request(Map authorizationParame } + public StoredOAuth2Request createStoredAuthorizationRequest(AuthorizationRequest request) { + StoredOAuth2Request storedOAuth2Request = new StoredOAuth2Request(request.getRequestParameters(), request.getClientId(), request.getAuthorities(), + request.isApproved(), request.getScope(), request.getResourceIds(), request.getRedirectUri(), request.getExtensionProperties()); + return storedOAuth2Request; + } + + public TokenRequest createTokenRequest(Map requestParameters) { + + String clientId = requestParameters.get(OAuth2Utils.CLIENT_ID); + Set scopes = OAuth2Utils.parseParameterList(requestParameters.get(OAuth2Utils.SCOPE)); + String grantType = requestParameters.get(OAuth2Utils.GRANT_TYPE); + + TokenRequest tokenRequest = new TokenRequest(requestParameters, clientId, scopes, grantType); + + return tokenRequest; + } + + public TokenRequest createTokenRequestFromAuthorizationRequest(AuthorizationRequest authorizationRequest) { + TokenRequest tokenRequest = new TokenRequest(authorizationRequest.getRequestParameters(), authorizationRequest.getClientId(), authorizationRequest.getScope(), "implicit"); + return tokenRequest; + } + + public StoredOAuth2Request createStoredTokenRequest(TokenRequest tokenRequest) { + StoredOAuth2Request storedOAuth2Request = new StoredOAuth2Request(tokenRequest.getRequestParameters(), tokenRequest.getClientId(), null, true, tokenRequest.getScope(), null, null, null); + return storedOAuth2Request; + } + } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Authentication.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Authentication.java index ab0e5c3e3..162b49f06 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Authentication.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Authentication.java @@ -13,7 +13,7 @@ public class OAuth2Authentication extends AbstractAuthenticationToken { private static final long serialVersionUID = -4809832298438307309L; - private final OAuth2Request clientAuthentication; + private final StoredOAuth2Request storedRequest; private final Authentication userAuthentication; @@ -24,9 +24,9 @@ public class OAuth2Authentication extends AbstractAuthenticationToken { * @param authorizationRequest The authorization request (must not be null). * @param userAuthentication The user authentication (possibly null). */ - public OAuth2Authentication(OAuth2Request authorizationRequest, Authentication userAuthentication) { - super(userAuthentication == null ? authorizationRequest.getAuthorities() : userAuthentication.getAuthorities()); - this.clientAuthentication = authorizationRequest; + public OAuth2Authentication(StoredOAuth2Request clientAuthentication, Authentication userAuthentication) { + super(userAuthentication == null ? clientAuthentication.getAuthorities() : userAuthentication.getAuthorities()); + this.storedRequest = clientAuthentication; this.userAuthentication = userAuthentication; } @@ -35,7 +35,7 @@ public Object getCredentials() { } public Object getPrincipal() { - return this.userAuthentication == null ? this.clientAuthentication.getClientId() : this.userAuthentication + return this.userAuthentication == null ? this.storedRequest.getClientId() : this.userAuthentication .getPrincipal(); } @@ -53,8 +53,8 @@ public boolean isClientOnly() { * * @return The client authentication. */ - public OAuth2Request getAuthorizationRequest() { - return clientAuthentication; + public StoredOAuth2Request getStoredRequest() { + return storedRequest; } /** @@ -68,7 +68,7 @@ public Authentication getUserAuthentication() { @Override public boolean isAuthenticated() { - return this.clientAuthentication.isApproved() + return this.storedRequest.isApproved() && (this.userAuthentication == null || this.userAuthentication.isAuthenticated()); } @@ -86,7 +86,7 @@ public boolean equals(Object o) { OAuth2Authentication that = (OAuth2Authentication) o; - if (!clientAuthentication.equals(that.clientAuthentication)) { + if (!storedRequest.equals(that.storedRequest)) { return false; } if (userAuthentication != null ? !userAuthentication.equals(that.userAuthentication) @@ -100,7 +100,7 @@ public boolean equals(Object o) { @Override public int hashCode() { int result = super.hashCode(); - result = 31 * result + clientAuthentication.hashCode(); + result = 31 * result + storedRequest.hashCode(); result = 31 * result + (userAuthentication != null ? userAuthentication.hashCode() : 0); return result; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestFactory.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestFactory.java index 851f2115c..22767fa32 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestFactory.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestFactory.java @@ -16,7 +16,7 @@ import java.util.Map; /** - * Strategy for managing OAuth2Request instances during a token grant. + * Strategy for managing OAuth2 requests: {@link AuthorizationRequest}, {@link TokenRequest}, {@link StoredRequest}. * * @author Dave Syer * @author Amanda Anganes @@ -25,17 +25,52 @@ public interface OAuth2RequestFactory { /** - * Create a new {@link OAuth2Request} extracting all the needed information from the incoming parameter map, and - * initializing all individual fields on the {@link OAuth2Request} to reasonable values. When a class uses - * the factory to create an {@link OAuth2Request}, it should not need to access the parameter map directly afterwards. + * Create a new {@link AuthorizationRequest} extracting all the needed information from the incoming parameter map, and + * initializing all individual fields on the {@link AuthorizationRequest} to reasonable values. When a class uses + * the factory to create an {@link AuthorizationRequest}, it should not need to access the parameter map directly afterwards. * - * Typical implementations would initialize the individual fields on the {@link OAuth2Request} with the values + * Typical implementations would initialize the individual fields on the {@link AuthorizationRequest} with the values * requested in the original parameter map. It may also load the client details from the client id provided and * validate the grant type and scopes, populating any fields in the request that are known only to the authorization server. * * @param authorizationParameters the parameters in the request - * @return a new OAuth2Request + * @return a new AuthorizationRequest */ - OAuth2Request createOAuth2Request(Map authorizationParameters); + AuthorizationRequest createAuthorizationRequest(Map authorizationParameters); + + /** + * Create a new {@link StoredOAuth2Request} by extracting the needed information from the current {@link AuthorizationRequest} object. + * + * @param request the request to be converted + * @return an immutable object for storage + */ + StoredOAuth2Request createStoredAuthorizationRequest(AuthorizationRequest request); + + /** + * Create a new {@link StoredOAuth2Request} by extracting the needed information from the current {@link TokenRequest} object. + * + * @param tokenRequest the request to be converted + * @return am immutable object for storage + */ + StoredOAuth2Request createStoredTokenRequest(TokenRequest tokenRequest); + + /** + * Create a new {@link TokenRequest} by extracted the needed information from the incoming request parameter map. + * + * @param requestParameters the parameters in the request + * @return a new TokenRequest + */ + TokenRequest createTokenRequest(Map requestParameters); + + /** + * Create a new {@link TokenRequest} from an {@link AuthorizationRequest}. Used by the AuthorizationEndpoint during the + * implicit flow. + * + * @param authorizationRequest the incoming request + * @return a new TokenRequest + */ + TokenRequest createTokenRequestFromAuthorizationRequest(AuthorizationRequest authorizationRequest); + + } \ No newline at end of file diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestValidator.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestValidator.java index fc6214fbe..3330f033e 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestValidator.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestValidator.java @@ -16,7 +16,7 @@ public interface OAuth2RequestValidator { /** * Ensure that the client has requested a valid set of scopes. * - * @param parameters the parameters on the OAuth2Request, including scope + * @param parameters the parameters on the request, including scope * @param clientScopes the requesting client's registered, allowed scopes * @throws InvalidScopeException if a requested scope is invalid */ diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/StoredOAuth2Request.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/StoredOAuth2Request.java new file mode 100644 index 000000000..cc2c7ec3f --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/StoredOAuth2Request.java @@ -0,0 +1,170 @@ +package org.springframework.security.oauth2.provider; + +import java.io.Serializable; +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.springframework.security.core.GrantedAuthority; + +/** + * Represents a stored authorization or token request. Used as part of the OAuth2Authentication object to store + * a request's authentication information. + * + * @author Amanda Anganes + * + */ +public class StoredOAuth2Request implements Serializable { + + private static final long serialVersionUID = 1L; + + private String clientId; + private Set authorities; + private boolean approved; + private Set scope; + private Set resourceIds; + private Map requestParameters; + private String redirectUri; + private Map extensionProperties; + + public StoredOAuth2Request(Map requestParameters, String clientId, Collection authorities, boolean approved, Set scope, Set resourceIds, String redirectUri, Map extensionProperties) { + this.requestParameters = requestParameters; + this.clientId = clientId; + this.authorities = (authorities!=null ? new HashSet(authorities) : null); + this.approved = approved; + this.scope = scope; + this.resourceIds = resourceIds; + this.redirectUri = redirectUri; + this.extensionProperties = extensionProperties; + } + + public String getClientId() { + return clientId; + } + + public String getRedirectUri() { + return redirectUri; + } + + public Set getAuthorities() { + return authorities; + } + + public boolean isApproved() { + return approved; + } + + public Set getScope() { + return scope; + } + + public Set getResourceIds() { + return resourceIds; + } + + public Map getRequestParameters() { + return requestParameters; + } + + public Map getExtensionProperties() { + return extensionProperties; + } + + public void setExtensionProperties(Map extensionProperties) { + this.extensionProperties = extensionProperties; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (approved ? 1231 : 1237); + result = prime * result + + ((authorities == null) ? 0 : authorities.hashCode()); + result = prime * result + + ((clientId == null) ? 0 : clientId.hashCode()); + result = prime + * result + + ((extensionProperties == null) ? 0 : extensionProperties + .hashCode()); + result = prime * result + + ((redirectUri == null) ? 0 : redirectUri.hashCode()); + result = prime + * result + + ((requestParameters == null) ? 0 : requestParameters + .hashCode()); + result = prime * result + + ((resourceIds == null) ? 0 : resourceIds.hashCode()); + result = prime * result + ((scope == null) ? 0 : scope.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof StoredOAuth2Request)) { + return false; + } + StoredOAuth2Request other = (StoredOAuth2Request) obj; + if (approved != other.approved) { + return false; + } + if (authorities == null) { + if (other.authorities != null) { + return false; + } + } else if (!authorities.equals(other.authorities)) { + return false; + } + if (clientId == null) { + if (other.clientId != null) { + return false; + } + } else if (!clientId.equals(other.clientId)) { + return false; + } + if (extensionProperties == null) { + if (other.extensionProperties != null) { + return false; + } + } else if (!extensionProperties.equals(other.extensionProperties)) { + return false; + } + if (redirectUri == null) { + if (other.redirectUri != null) { + return false; + } + } else if (!redirectUri.equals(other.redirectUri)) { + return false; + } + if (requestParameters == null) { + if (other.requestParameters != null) { + return false; + } + } else if (!requestParameters.equals(other.requestParameters)) { + return false; + } + if (resourceIds == null) { + if (other.resourceIds != null) { + return false; + } + } else if (!resourceIds.equals(other.resourceIds)) { + return false; + } + if (scope == null) { + if (other.scope != null) { + return false; + } + } else if (!scope.equals(other.scope)) { + return false; + } + return true; + } + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenGranter.java index 272979985..51b34f3f4 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenGranter.java @@ -27,6 +27,6 @@ */ public interface TokenGranter { - OAuth2AccessToken grant(String grantType, OAuth2Request tokenRequest); + OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java new file mode 100644 index 000000000..1f8697974 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java @@ -0,0 +1,87 @@ +package org.springframework.security.oauth2.provider; + +import java.util.Collections; +import java.util.Map; +import java.util.Set; + +/** + * Represents an OAuth2 token request, made at the {@link TokenEndpoint}. The requestParameters map should + * contain the original, unmodified parameters from the original OAuth2 request. + * + * In the implicit flow, a token is requested through the {@link AuthorizationEndpoint} directly, and in + * that case the {@link AuthorizationRequest} is converted into a {@link TokenRequest} for processing + * through the token granting chain. + * + * @author Amanda Anganes + * + */ +public class TokenRequest { + + private Map requestParameters; + private String clientId; + private Set scope; + private String grantType; + + /** + * Full constructor. Sets this TokenRequest's requestParameters map to an unmodifiable version of the one provided. + * + * @param requestParameters + * @param clientId + * @param scope + * @param grantType + */ + public TokenRequest(Map requestParameters, String clientId, Set scope, String grantType) { + + if (requestParameters != null) { + this.requestParameters = Collections.unmodifiableMap(requestParameters); + } + + this.clientId = clientId; + this.scope = scope; + this.grantType = grantType; + } + + /** + * Warning: most classes should not need to interact with the parameters map directly. + * + * @return the original token request's parameters map + */ + public Map getRequestParameters() { + return requestParameters; + } + + /** + * Warning: This method should not be called during normal usage. Instead, properties that need to be + * altered during processing should be stored on individual property fields on this object. + * + * @param requestParameters the parameter map to set + */ + public void setRequestParameters(Map requestParameters) { + this.requestParameters = requestParameters; + } + + public String getClientId() { + return clientId; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + public Set getScope() { + return scope; + } + + public void setScope(Set scope) { + this.scope = scope; + } + + public String getGrantType() { + return grantType; + } + + public void setGrantType(String grantType) { + this.grantType = grantType; + } + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/DefaultUserApprovalHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/DefaultUserApprovalHandler.java index 9d80aedbf..ff70103aa 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/DefaultUserApprovalHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/DefaultUserApprovalHandler.java @@ -19,7 +19,8 @@ import java.util.Map; import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.common.util.OAuth2Utils; +import org.springframework.security.oauth2.provider.AuthorizationRequest; /** * A default user approval handler that doesn't remember any decisions. @@ -29,7 +30,7 @@ */ public class DefaultUserApprovalHandler implements UserApprovalHandler { - private String approvalParameter = OAuth2Request.USER_OAUTH_APPROVAL; + private String approvalParameter = OAuth2Utils.USER_OAUTH_APPROVAL; /** * @param approvalParameter the approvalParameter to set @@ -42,24 +43,24 @@ public void setApprovalParameter(String approvalParameter) { * Basic implementation just requires the authorization request to be explicitly approved and the user to be * authenticated. * - * @param oAuth2Request The authorization request. + * @param authorizationRequest The authorization request. * @param userAuthentication the current user authentication * * @return Whether the specified request has been approved by the current user. */ - public boolean isApproved(OAuth2Request oAuth2Request, Authentication userAuthentication) { - Map approvalParameters = oAuth2Request.getApprovalParameters(); + public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { + Map approvalParameters = authorizationRequest.getApprovalParameters(); String flag = approvalParameters.get(approvalParameter); boolean approved = flag != null && flag.toLowerCase().equals("true"); return userAuthentication.isAuthenticated() && approved; } - public OAuth2Request checkForPreApproval(OAuth2Request oAuth2Request, Authentication userAuthentication) { - return oAuth2Request; + public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { + return authorizationRequest; } - public OAuth2Request updateAfterApproval(OAuth2Request oAuth2Request, Authentication userAuthentication) { - return oAuth2Request; + public AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { + return authorizationRequest; } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenServicesUserApprovalHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenServicesUserApprovalHandler.java index 31f5a9f88..f3b7a6e36 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenServicesUserApprovalHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenServicesUserApprovalHandler.java @@ -21,8 +21,11 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.common.util.OAuth2Utils; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; +import org.springframework.security.oauth2.provider.StoredOAuth2Request; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; import org.springframework.util.Assert; @@ -36,7 +39,7 @@ public class TokenServicesUserApprovalHandler implements UserApprovalHandler, In private static Log logger = LogFactory.getLog(TokenServicesUserApprovalHandler.class); - private String approvalParameter = OAuth2Request.USER_OAUTH_APPROVAL; + private String approvalParameter = OAuth2Utils.USER_OAUTH_APPROVAL; /** * @param approvalParameter the approvalParameter to set @@ -54,29 +57,38 @@ public void setTokenServices(AuthorizationServerTokenServices tokenServices) { this.tokenServices = tokenServices; } + private OAuth2RequestFactory requestFactory; + + public void setRequestFactory(OAuth2RequestFactory requestFactory) { + this.requestFactory = requestFactory; + } + public void afterPropertiesSet() { Assert.state(tokenServices != null, "AuthorizationServerTokenServices must be provided"); + Assert.state(requestFactory != null, "OAuth2RequestFactory must be provided"); } /** * Basic implementation just requires the authorization request to be explicitly approved and the user to be * authenticated. * - * @param oAuth2Request The authorization request. + * @param authorizationRequest The authorization request. * @param userAuthentication the current user authentication * * @return Whether the specified request has been approved by the current user. */ - public boolean isApproved(OAuth2Request oAuth2Request, Authentication userAuthentication) { + public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { - String flag = oAuth2Request.getApprovalParameters().get(approvalParameter); + String flag = authorizationRequest.getApprovalParameters().get(approvalParameter); boolean approved = flag != null && flag.toLowerCase().equals("true"); - OAuth2Authentication authentication = new OAuth2Authentication(oAuth2Request, userAuthentication); + StoredOAuth2Request storedOAuth2Request = requestFactory.createStoredAuthorizationRequest(authorizationRequest); + + OAuth2Authentication authentication = new OAuth2Authentication(storedOAuth2Request, userAuthentication); if (logger.isDebugEnabled()) { StringBuilder builder = new StringBuilder("Looking up existing token for "); - builder.append("client_id=" + oAuth2Request.getClientId()); - builder.append(", scope=" + oAuth2Request.getScope()); + builder.append("client_id=" + authorizationRequest.getClientId()); + builder.append(", scope=" + authorizationRequest.getScope()); builder.append(" and username=" + userAuthentication.getName()); logger.debug(builder.toString()); } @@ -97,11 +109,11 @@ public boolean isApproved(OAuth2Request oAuth2Request, Authentication userAuthen } - public OAuth2Request checkForPreApproval(OAuth2Request oAuth2Request, Authentication userAuthentication) { - return oAuth2Request; + public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { + return authorizationRequest; } - public OAuth2Request updateAfterApproval(OAuth2Request oAuth2Request, Authentication userAuthentication) { - return oAuth2Request; + public AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { + return authorizationRequest; } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/UserApprovalHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/UserApprovalHandler.java index e579aad33..20547aacb 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/UserApprovalHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/UserApprovalHandler.java @@ -1,7 +1,7 @@ package org.springframework.security.oauth2.provider.approval; import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.AuthorizationRequest; /** * Basic interface for determining whether a given client authentication request has been approved by the current user. @@ -18,11 +18,11 @@ public interface UserApprovalHandler { * Tests whether the specified authorization request has been approved by the current user (if there is one). *

* - * @param oAuth2Request the authorization request. + * @param authorizationRequest the authorization request. * @param userAuthentication the user authentication for the current user. * @return true if the request has been approved, false otherwise */ - boolean isApproved(OAuth2Request oAuth2Request, Authentication userAuthentication); + boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication); /** *

@@ -32,23 +32,23 @@ public interface UserApprovalHandler { * to true, the Approval page will be skipped. *

* - * @param oAuth2Request the authorization request. + * @param authorizationRequest the authorization request. * @param userAuthentication the user authentication - * @return the OAuth2Request, modified if necessary + * @return the AuthorizationRequest, modified if necessary */ - OAuth2Request checkForPreApproval(OAuth2Request oAuth2Request, Authentication userAuthentication); + AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication); /** *

* Provides an opportunity to update the authorization request before it is checked for approval in cases where the * incoming approval parameters contain richer information than just true/false (e.g. some scopes are approved, and - * others are rejected), implementations may need to be able to modify the {@link OAuth2Request} before a + * others are rejected), implementations may need to be able to modify the {@link AuthorizationRequest} before a * token is generated from it. *

* - * @param oAuth2Request the authorization request. + * @param authorizationRequest the authorization request. * @param userAuthentication the user authentication - * @return the OAuth2Request, modified if necessary + * @return the AuthorizationRequest, modified if necessary */ - OAuth2Request updateAfterApproval(OAuth2Request oAuth2Request, Authentication userAuthentication); + AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java index a5aa702ae..78b4d18cc 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java @@ -20,7 +20,7 @@ import org.springframework.security.core.AuthenticationException; import org.springframework.security.oauth2.client.resource.OAuth2AccessDeniedException; import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; -import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices; import org.springframework.util.Assert; @@ -55,7 +55,7 @@ public void afterPropertiesSet() { /** * Expects the incoming authentication request to have a principal value that is an access token value (e.g. from an * authorization header) .Loads an authentication from the {@link ResourceServerTokenServices} and checks that the - * resource id is contained in the {@link OAuth2Request} (if one is specified). Also copies authentication + * resource id is contained in the {@link AuthorizationRequest} (if one is specified). Also copies authentication * details over from the input to the output (e.g. typically so that the access token value and request details can * be reported later). * @@ -72,7 +72,7 @@ public Authentication authenticate(Authentication authentication) throws Authent throw new InvalidTokenException("Invalid token: " + token); } - Collection resourceIds = auth.getAuthorizationRequest().getResourceIds(); + Collection resourceIds = auth.getStoredRequest().getResourceIds(); if (resourceId != null && resourceIds != null && !resourceIds.isEmpty() && !resourceIds.contains(resourceId)) { throw new OAuth2AccessDeniedException("Invalid token does not contain resource id (" + resourceId + ")"); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenGranter.java index 40fb97cd6..c6dff5b2f 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenGranter.java @@ -19,7 +19,8 @@ import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.provider.ClientDetailsService; -import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; +import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.token.AbstractTokenGranter; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; @@ -32,12 +33,12 @@ public class ClientCredentialsTokenGranter extends AbstractTokenGranter { private static final String GRANT_TYPE = "client_credentials"; public ClientCredentialsTokenGranter(AuthorizationServerTokenServices tokenServices, - ClientDetailsService clientDetailsService) { - super(tokenServices, clientDetailsService, GRANT_TYPE); + ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory) { + super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE); } @Override - public OAuth2AccessToken grant(String grantType, OAuth2Request tokenRequest) { + public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) { OAuth2AccessToken token = super.grant(grantType, tokenRequest); if (token != null) { DefaultOAuth2AccessToken norefresh = new DefaultOAuth2AccessToken(token); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeServices.java index 20cf112fa..3c6ee338a 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeServices.java @@ -1,6 +1,7 @@ package org.springframework.security.oauth2.provider.code; import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; +import org.springframework.security.oauth2.provider.OAuth2Authentication; /** * Services for issuing and storing authorization codes. @@ -15,7 +16,7 @@ public interface AuthorizationCodeServices { * @param authentication The authentications to store. * @return The generated code. */ - String createAuthorizationCode(AuthorizationRequestHolder authentication); + String createAuthorizationCode(OAuth2Authentication authentication); /** * Consume a authorization code. @@ -24,7 +25,7 @@ public interface AuthorizationCodeServices { * @return The authentications associated with the code. * @throws InvalidGrantException If the authorization code is invalid or expired. */ - AuthorizationRequestHolder consumeAuthorizationCode(String code) + OAuth2Authentication consumeAuthorizationCode(String code) throws InvalidGrantException; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranter.java index b02a447bb..3699052a2 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranter.java @@ -24,9 +24,12 @@ import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.common.exceptions.RedirectMismatchException; -import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.common.util.OAuth2Utils; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; +import org.springframework.security.oauth2.provider.StoredOAuth2Request; +import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.token.AbstractTokenGranter; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; @@ -43,32 +46,32 @@ public class AuthorizationCodeTokenGranter extends AbstractTokenGranter { private final AuthorizationCodeServices authorizationCodeServices; public AuthorizationCodeTokenGranter(AuthorizationServerTokenServices tokenServices, - AuthorizationCodeServices authorizationCodeServices, ClientDetailsService clientDetailsService) { - super(tokenServices, clientDetailsService, GRANT_TYPE); + AuthorizationCodeServices authorizationCodeServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory) { + super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE); this.authorizationCodeServices = authorizationCodeServices; } @Override - protected OAuth2Authentication getOAuth2Authentication(OAuth2Request oAuth2Request) { + protected OAuth2Authentication getOAuth2Authentication(TokenRequest tokenRequest) { - Map parameters = oAuth2Request.getRequestParameters(); + Map parameters = tokenRequest.getRequestParameters(); String authorizationCode = parameters.get("code"); - String redirectUri = parameters.get(OAuth2Request.REDIRECT_URI); + String redirectUri = parameters.get(OAuth2Utils.REDIRECT_URI); if (authorizationCode == null) { throw new OAuth2Exception("An authorization code must be supplied."); } - AuthorizationRequestHolder storedAuth = authorizationCodeServices.consumeAuthorizationCode(authorizationCode); + OAuth2Authentication storedAuth = authorizationCodeServices.consumeAuthorizationCode(authorizationCode); if (storedAuth == null) { throw new InvalidGrantException("Invalid authorization code: " + authorizationCode); } - OAuth2Request pendingOAuth2Request = storedAuth.getAuthenticationRequest(); + StoredOAuth2Request pendingOAuth2Request = storedAuth.getStoredRequest(); // https://jira.springsource.org/browse/SECOAUTH-333 // This might be null, if the authorization was done without the redirect_uri parameter String redirectUriApprovalParameter = pendingOAuth2Request.getRequestParameters().get( - OAuth2Request.REDIRECT_URI); + OAuth2Utils.REDIRECT_URI); if ((redirectUri != null || redirectUriApprovalParameter != null) && !pendingOAuth2Request.getRedirectUri().equals(redirectUri)) { @@ -76,7 +79,7 @@ protected OAuth2Authentication getOAuth2Authentication(OAuth2Request oAuth2Reque } String pendingClientId = pendingOAuth2Request.getClientId(); - String clientId = oAuth2Request.getClientId(); + String clientId = tokenRequest.getClientId(); if (clientId != null && !clientId.equals(pendingClientId)) { // just a sanity check. throw new InvalidClientException("Client ID mismatch"); @@ -86,15 +89,20 @@ protected OAuth2Authentication getOAuth2Authentication(OAuth2Request oAuth2Reque // in the pendingAuthorizationRequest. We do want to check that a secret is provided // in the token request, but that happens elsewhere. - Map combinedParameters = new HashMap(storedAuth.getAuthenticationRequest() + Map combinedParameters = new HashMap(pendingOAuth2Request .getRequestParameters()); // Combine the parameters adding the new ones last so they override if there are any clashes combinedParameters.putAll(parameters); - pendingOAuth2Request.setRequestParameters(combinedParameters); + //Make a new stored request with the combined parameters + StoredOAuth2Request finalStoredOAuth2Request = new StoredOAuth2Request(combinedParameters, clientId, + pendingOAuth2Request.getAuthorities(), pendingOAuth2Request.isApproved(), + pendingOAuth2Request.getScope(), pendingOAuth2Request.getResourceIds(), pendingOAuth2Request.getRedirectUri(), + pendingOAuth2Request.getExtensionProperties()); Authentication userAuth = storedAuth.getUserAuthentication(); - return new OAuth2Authentication(pendingOAuth2Request, userAuth); + + return new OAuth2Authentication(finalStoredOAuth2Request, userAuth); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationRequestHolder.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationRequestHolder.java deleted file mode 100644 index 218423fed..000000000 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationRequestHolder.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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.code; - -import java.io.Serializable; - -import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.provider.OAuth2Request; - -/** - * Convenience class for {@link AuthorizationCodeServices} to store and retrieve. - * - * @author Dave Syer - * - */ -public class AuthorizationRequestHolder implements Serializable { - - private static final long serialVersionUID = 914967629530462926L; - - private final OAuth2Request oAuth2Request; - - private final Authentication userAuthentication; - - public AuthorizationRequestHolder( - OAuth2Request oAuth2Request, Authentication userAuthentication) { - this.oAuth2Request = oAuth2Request; - this.userAuthentication = userAuthentication; - } - - public OAuth2Request getAuthenticationRequest() { - return oAuth2Request; - } - - public Authentication getUserAuthentication() { - return userAuthentication; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((oAuth2Request == null) ? 0 : oAuth2Request.hashCode()); - result = prime * result + ((userAuthentication == null) ? 0 : userAuthentication.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - AuthorizationRequestHolder other = (AuthorizationRequestHolder) obj; - if (oAuth2Request == null) { - if (other.oAuth2Request != null) - return false; - } else if (!oAuth2Request.equals(other.oAuth2Request)) - return false; - if (userAuthentication == null) { - if (other.userAuthentication != null) - return false; - } else if (!userAuthentication.equals(other.userAuthentication)) - return false; - return true; - } - -} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/InMemoryAuthorizationCodeServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/InMemoryAuthorizationCodeServices.java index 98323827f..d75dfa108 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/InMemoryAuthorizationCodeServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/InMemoryAuthorizationCodeServices.java @@ -2,6 +2,8 @@ import java.util.concurrent.ConcurrentHashMap; +import org.springframework.security.oauth2.provider.OAuth2Authentication; + /** * Implementation of authorization code services that stores the codes and authentication in memory. * @@ -10,16 +12,16 @@ */ public class InMemoryAuthorizationCodeServices extends RandomValueAuthorizationCodeServices { - protected final ConcurrentHashMap authorizationCodeStore = new ConcurrentHashMap(); + protected final ConcurrentHashMap authorizationCodeStore = new ConcurrentHashMap(); @Override - protected void store(String code, AuthorizationRequestHolder authentication) { + protected void store(String code, OAuth2Authentication authentication) { this.authorizationCodeStore.put(code, authentication); } @Override - public AuthorizationRequestHolder remove(String code) { - AuthorizationRequestHolder auth = this.authorizationCodeStore.remove(code); + public OAuth2Authentication remove(String code) { + OAuth2Authentication auth = this.authorizationCodeStore.remove(code); return auth; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/JdbcAuthorizationCodeServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/JdbcAuthorizationCodeServices.java index c1e01f7da..a02fef029 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/JdbcAuthorizationCodeServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/JdbcAuthorizationCodeServices.java @@ -11,6 +11,7 @@ import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.support.SqlLobValue; import org.springframework.security.oauth2.common.util.SerializationUtils; +import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.util.Assert; /** @@ -37,19 +38,19 @@ public JdbcAuthorizationCodeServices(DataSource dataSource) { } @Override - protected void store(String code, AuthorizationRequestHolder authentication) { + protected void store(String code, OAuth2Authentication authentication) { jdbcTemplate.update(insertAuthenticationSql, new Object[] { code, new SqlLobValue(SerializationUtils.serialize(authentication)) }, new int[] { Types.VARCHAR, Types.BLOB }); } - public AuthorizationRequestHolder remove(String code) { - AuthorizationRequestHolder authentication; + public OAuth2Authentication remove(String code) { + OAuth2Authentication authentication; try { authentication = jdbcTemplate.queryForObject(selectAuthenticationSql, - new RowMapper() { - public AuthorizationRequestHolder mapRow(ResultSet rs, int rowNum) + new RowMapper() { + public OAuth2Authentication mapRow(ResultSet rs, int rowNum) throws SQLException { return SerializationUtils.deserialize(rs.getBytes("authentication")); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/RandomValueAuthorizationCodeServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/RandomValueAuthorizationCodeServices.java index bd7dccd9f..be091bab0 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/RandomValueAuthorizationCodeServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/RandomValueAuthorizationCodeServices.java @@ -2,6 +2,7 @@ import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; import org.springframework.security.oauth2.common.util.RandomValueStringGenerator; +import org.springframework.security.oauth2.provider.OAuth2Authentication; /** * Base implementation for authorization code services that generates a random-value authorization code. @@ -13,19 +14,19 @@ public abstract class RandomValueAuthorizationCodeServices implements Authorizat private RandomValueStringGenerator generator = new RandomValueStringGenerator(); - protected abstract void store(String code, AuthorizationRequestHolder authentication); + protected abstract void store(String code, OAuth2Authentication authentication); - protected abstract AuthorizationRequestHolder remove(String code); + protected abstract OAuth2Authentication remove(String code); - public String createAuthorizationCode(AuthorizationRequestHolder authentication) { + public String createAuthorizationCode(OAuth2Authentication authentication) { String code = generator.generate(); store(code, authentication); return code; } - public AuthorizationRequestHolder consumeAuthorizationCode(String code) + public OAuth2Authentication consumeAuthorizationCode(String code) throws InvalidGrantException { - AuthorizationRequestHolder auth = this.remove(code); + OAuth2Authentication auth = this.remove(code); if (auth == null) { throw new InvalidGrantException("Invalid authorization code: " + code); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java index 57afab37d..357d36877 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java @@ -13,8 +13,6 @@ package org.springframework.security.oauth2.provider.endpoint; -import static org.springframework.security.oauth2.provider.OAuth2Request.REDIRECT_URI; - import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.security.Principal; @@ -45,12 +43,14 @@ import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientRegistrationException; import org.springframework.security.oauth2.provider.DefaultOAuth2RequestValidator; -import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.OAuth2RequestValidator; +import org.springframework.security.oauth2.provider.StoredOAuth2Request; +import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.approval.DefaultUserApprovalHandler; import org.springframework.security.oauth2.provider.approval.UserApprovalHandler; import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; -import org.springframework.security.oauth2.provider.code.AuthorizationRequestHolder; import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices; import org.springframework.util.StringUtils; import org.springframework.web.HttpSessionRequiredException; @@ -122,16 +122,16 @@ public ModelAndView authorize(Map model, @RequestParam Map responseTypes = oAuth2Request.getResponseTypes(); + Set responseTypes = authorizationRequest.getResponseTypes(); if (!responseTypes.contains("token") && !responseTypes.contains("code")) { throw new UnsupportedResponseTypeException("Unsupported response types: " + responseTypes); } - if (oAuth2Request.getClientId() == null) { + if (authorizationRequest.getClientId() == null) { throw new InvalidClientException("A client id must be provided"); } @@ -142,45 +142,45 @@ public ModelAndView authorize(Map model, @RequestParam Map model, @RequestParam Map approvalParameters, Map model, SessionStatus sessionStatus, Principal principal) { @@ -200,36 +200,36 @@ public View approveOrDeny(@RequestParam Map approvalParameters, "User must be authenticated with Spring Security before authorizing an access token."); } - OAuth2Request oAuth2Request = (OAuth2Request) model.get("authorizationRequest"); + AuthorizationRequest authorizationRequest = (AuthorizationRequest) model.get("authorizationRequest"); - if (oAuth2Request == null) { + if (authorizationRequest == null) { sessionStatus.setComplete(); throw new InvalidRequestException("Cannot approve uninitialized authorization request."); } try { - Set responseTypes = oAuth2Request.getResponseTypes(); + Set responseTypes = authorizationRequest.getResponseTypes(); - oAuth2Request.setApprovalParameters(approvalParameters); - oAuth2Request = userApprovalHandler.updateAfterApproval(oAuth2Request, (Authentication) principal); - boolean approved = userApprovalHandler.isApproved(oAuth2Request, (Authentication) principal); - oAuth2Request.setApproved(approved); + authorizationRequest.setApprovalParameters(approvalParameters); + authorizationRequest = userApprovalHandler.updateAfterApproval(authorizationRequest, (Authentication) principal); + boolean approved = userApprovalHandler.isApproved(authorizationRequest, (Authentication) principal); + authorizationRequest.setApproved(approved); - if (oAuth2Request.getRedirectUri() == null) { + if (authorizationRequest.getRedirectUri() == null) { sessionStatus.setComplete(); throw new InvalidRequestException("Cannot approve request when no redirect URI is provided."); } - if (!oAuth2Request.isApproved()) { - return new RedirectView(getUnsuccessfulRedirect(oAuth2Request, new UserDeniedAuthorizationException( + if (!authorizationRequest.isApproved()) { + return new RedirectView(getUnsuccessfulRedirect(authorizationRequest, new UserDeniedAuthorizationException( "User denied access"), responseTypes.contains("token")), false); } if (responseTypes.contains("token")) { - return getImplicitGrantResponse(oAuth2Request).getView(); + return getImplicitGrantResponse(authorizationRequest).getView(); } - return getAuthorizationCodeResponse(oAuth2Request, (Authentication) principal); + return getAuthorizationCodeResponse(authorizationRequest, (Authentication) principal); } finally { sessionStatus.setComplete(); @@ -239,42 +239,43 @@ public View approveOrDeny(@RequestParam Map approvalParameters, // We need explicit approval from the user. private ModelAndView getUserApprovalPageResponse(Map model, - OAuth2Request oAuth2Request) { + AuthorizationRequest authorizationRequest) { logger.debug("Loading user approval page: " + userApprovalPage); // In case of a redirect we might want the request parameters to be included - model.putAll(oAuth2Request.getRequestParameters()); + model.putAll(authorizationRequest.getRequestParameters()); return new ModelAndView(userApprovalPage, model); } // We can grant a token and return it with implicit approval. - private ModelAndView getImplicitGrantResponse(OAuth2Request oAuth2Request) { + private ModelAndView getImplicitGrantResponse(AuthorizationRequest authorizationRequest) { try { - OAuth2AccessToken accessToken = getTokenGranter().grant("implicit", oAuth2Request); + TokenRequest tokenRequest = getOAuth2RequestFactory().createTokenRequestFromAuthorizationRequest(authorizationRequest); + OAuth2AccessToken accessToken = getTokenGranter().grant("implicit", tokenRequest); if (accessToken == null) { throw new UnsupportedResponseTypeException("Unsupported response type: token"); } - return new ModelAndView(new RedirectView(appendAccessToken(oAuth2Request, accessToken), false)); + return new ModelAndView(new RedirectView(appendAccessToken(authorizationRequest, accessToken), false)); } catch (OAuth2Exception e) { - return new ModelAndView(new RedirectView(getUnsuccessfulRedirect(oAuth2Request, e, true), false)); + return new ModelAndView(new RedirectView(getUnsuccessfulRedirect(authorizationRequest, e, true), false)); } } - private View getAuthorizationCodeResponse(OAuth2Request oAuth2Request, Authentication authUser) { + private View getAuthorizationCodeResponse(AuthorizationRequest authorizationRequest, Authentication authUser) { try { - return new RedirectView(getSuccessfulRedirect(oAuth2Request, - generateCode(oAuth2Request, authUser)), false); + return new RedirectView(getSuccessfulRedirect(authorizationRequest, + generateCode(authorizationRequest, authUser)), false); } catch (OAuth2Exception e) { - return new RedirectView(getUnsuccessfulRedirect(oAuth2Request, e, false), false); + return new RedirectView(getUnsuccessfulRedirect(authorizationRequest, e, false), false); } } - private String appendAccessToken(OAuth2Request oAuth2Request, OAuth2AccessToken accessToken) { + private String appendAccessToken(AuthorizationRequest authorizationRequest, OAuth2AccessToken accessToken) { Map vars = new HashMap(); - String requestedRedirect = oAuth2Request.getRedirectUri(); + String requestedRedirect = authorizationRequest.getRedirectUri(); if (accessToken == null) { throw new InvalidGrantException("An implicit grant could not be made"); } @@ -290,7 +291,7 @@ private String appendAccessToken(OAuth2Request oAuth2Request, OAuth2AccessToken url.append("&token_type={token_type}"); vars.put("access_token", accessToken.getValue()); vars.put("token_type", accessToken.getTokenType()); - String state = oAuth2Request.getState(); + String state = authorizationRequest.getState(); if (state != null) { url.append("&state={state}"); @@ -302,9 +303,9 @@ private String appendAccessToken(OAuth2Request oAuth2Request, OAuth2AccessToken url.append("&expires_in={expires_in}"); vars.put("expires_in", expires_in); } - String originalScope = oAuth2Request.getRequestParameters().get(OAuth2Request.SCOPE); + String originalScope = authorizationRequest.getRequestParameters().get(OAuth2Utils.SCOPE); if (originalScope==null || !OAuth2Utils.parseParameterList(originalScope).equals(accessToken.getScope())) { - url.append("&" + OAuth2Request.SCOPE + "={scope}"); + url.append("&" + OAuth2Utils.SCOPE + "={scope}"); vars.put("scope", OAuth2Utils.formatParameterList(accessToken.getScope())); } Map additionalInformation = accessToken.getAdditionalInformation(); @@ -320,12 +321,14 @@ private String appendAccessToken(OAuth2Request oAuth2Request, OAuth2AccessToken return template.expand(vars).toString(); } - private String generateCode(OAuth2Request oAuth2Request, Authentication authentication) + private String generateCode(AuthorizationRequest authorizationRequest, Authentication authentication) throws AuthenticationException { try { - - AuthorizationRequestHolder combinedAuth = new AuthorizationRequestHolder(oAuth2Request, + + StoredOAuth2Request storedOAuth2Request = getOAuth2RequestFactory().createStoredAuthorizationRequest(authorizationRequest); + + OAuth2Authentication combinedAuth = new OAuth2Authentication(storedOAuth2Request, authentication); String code = authorizationCodeServices.createAuthorizationCode(combinedAuth); @@ -334,8 +337,8 @@ private String generateCode(OAuth2Request oAuth2Request, Authentication authenti } catch (OAuth2Exception e) { - if (oAuth2Request.getState() != null) { - e.addAdditionalInformation("state", oAuth2Request.getState()); + if (authorizationRequest.getState() != null) { + e.addAdditionalInformation("state", authorizationRequest.getState()); } throw e; @@ -343,15 +346,15 @@ private String generateCode(OAuth2Request oAuth2Request, Authentication authenti } } - private String getSuccessfulRedirect(OAuth2Request oAuth2Request, String authorizationCode) { + private String getSuccessfulRedirect(AuthorizationRequest authorizationRequest, String authorizationCode) { if (authorizationCode == null) { throw new IllegalStateException("No authorization code found in the current request scope."); } - String requestedRedirect = oAuth2Request.getRedirectUri(); + String requestedRedirect = authorizationRequest.getRedirectUri(); String[] fragments = requestedRedirect.split("#"); - String state = oAuth2Request.getState(); + String state = authorizationRequest.getState(); StringBuilder url = new StringBuilder(fragments[0]); if (requestedRedirect.indexOf('?') < 0) { @@ -373,15 +376,15 @@ private String getSuccessfulRedirect(OAuth2Request oAuth2Request, String authori return url.toString(); } - private String getUnsuccessfulRedirect(OAuth2Request oAuth2Request, OAuth2Exception failure, + private String getUnsuccessfulRedirect(AuthorizationRequest authorizationRequest, OAuth2Exception failure, boolean fragment) { - if (oAuth2Request == null || oAuth2Request.getRedirectUri() == null) { + if (authorizationRequest == null || authorizationRequest.getRedirectUri() == null) { // we have no redirect for the user. very sad. throw new UnapprovedClientAuthenticationException("Authorization failure, and no redirect URI.", failure); } - String redirectUri = oAuth2Request.getRedirectUri(); + String redirectUri = authorizationRequest.getRedirectUri(); // extract existing fragments if any String[] fragments = redirectUri.split("#"); @@ -400,8 +403,8 @@ private String getUnsuccessfulRedirect(OAuth2Request oAuth2Request, OAuth2Except url.append("&error_description=").append(URLEncoder.encode(failure.getMessage(), "UTF-8")); - if (oAuth2Request.getState() != null) { - url.append('&').append("state=").append(oAuth2Request.getState()); + if (authorizationRequest.getState() != null) { + url.append('&').append("state=").append(authorizationRequest.getState()); } if (failure.getAdditionalInformation() != null) { @@ -473,14 +476,14 @@ private ModelAndView handleException(Exception e, ServletWebRequest webRequest) return new ModelAndView(errorPage, Collections.singletonMap("error", translate.getBody())); } - OAuth2Request oAuth2Request = null; + AuthorizationRequest authorizationRequest = null; try { - oAuth2Request = getOAuth2RequestForError(webRequest); - String requestedRedirectParam = oAuth2Request.getRequestParameters().get(REDIRECT_URI); + authorizationRequest = getAuthorizationRequestForError(webRequest); + String requestedRedirectParam = authorizationRequest.getRequestParameters().get(OAuth2Utils.REDIRECT_URI); String requestedRedirect = redirectResolver.resolveRedirect(requestedRedirectParam, - getClientDetailsService().loadClientByClientId(oAuth2Request.getClientId())); - oAuth2Request.setRedirectUri(requestedRedirect); - String redirect = getUnsuccessfulRedirect(oAuth2Request, translate.getBody(), oAuth2Request + getClientDetailsService().loadClientByClientId(authorizationRequest.getClientId())); + authorizationRequest.setRedirectUri(requestedRedirect); + String redirect = getUnsuccessfulRedirect(authorizationRequest, translate.getBody(), authorizationRequest .getResponseTypes().contains("token")); return new ModelAndView(new RedirectView(redirect, false)); } @@ -493,13 +496,13 @@ private ModelAndView handleException(Exception e, ServletWebRequest webRequest) } - private OAuth2Request getOAuth2RequestForError(ServletWebRequest webRequest) { + private AuthorizationRequest getAuthorizationRequestForError(ServletWebRequest webRequest) { // If it's already there then we are in the approveOrDeny phase and we can use the saved request - OAuth2Request oAuth2Request = (OAuth2Request) sessionAttributeStore.retrieveAttribute( + AuthorizationRequest authorizationRequest = (AuthorizationRequest) sessionAttributeStore.retrieveAttribute( webRequest, "authorizationRequest"); - if (oAuth2Request != null) { - return oAuth2Request; + if (authorizationRequest != null) { + return authorizationRequest; } Map parameters = new HashMap(); @@ -512,10 +515,10 @@ private OAuth2Request getOAuth2RequestForError(ServletWebRequest webRequest) { } try { - return getOAuth2RequestFactory().createOAuth2Request(parameters); + return getOAuth2RequestFactory().createAuthorizationRequest(parameters); } catch (Exception e) { - return getDefaultOAuth2RequestFactory().createOAuth2Request(parameters); + return getDefaultOAuth2RequestFactory().createAuthorizationRequest(parameters); } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java index ad73b6608..adcb4865c 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java @@ -20,7 +20,8 @@ import org.springframework.core.Ordered; import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.common.util.OAuth2Utils; +import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.web.servlet.mvc.condition.NameValueExpression; import org.springframework.web.servlet.mvc.condition.ParamsRequestCondition; import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition; @@ -37,7 +38,7 @@ public class FrameworkEndpointHandlerMapping extends RequestMappingHandlerMappin private Map mappings = new HashMap(); - private String approvalParameter = OAuth2Request.USER_OAUTH_APPROVAL; + private String approvalParameter = OAuth2Utils.USER_OAUTH_APPROVAL; /** * Custom mappings for framework endpoint paths. The keys in the map are the default framework endpoint path, e.g. @@ -51,7 +52,7 @@ public void setMappings(Map patternMap) { /** * The name of the request parameter that distinguishes a call to approve an authorization. Default is - * {@link OAuth2Request#USER_OAUTH_APPROVAL}. + * {@link AuthorizationRequest#USER_OAUTH_APPROVAL}. * * @param approvalParameter the approvalParameter to set */ @@ -96,14 +97,14 @@ protected RequestMappingInfo getMappingForMethod(Method method, Class handler PatternsRequestCondition patternsInfo = new PatternsRequestCondition(patterns); ParamsRequestCondition paramsInfo = defaultMapping.getParamsCondition(); - if (!approvalParameter.equals(OAuth2Request.USER_OAUTH_APPROVAL) + if (!approvalParameter.equals(OAuth2Utils.USER_OAUTH_APPROVAL) && defaultPatterns.contains("/oauth/authorize")) { String[] params = new String[paramsInfo.getExpressions().size()]; Set> expressions = paramsInfo.getExpressions(); i = 0; for (NameValueExpression expression : expressions) { String param = expression.toString(); - if (OAuth2Request.USER_OAUTH_APPROVAL.equals(param)) { + if (OAuth2Utils.USER_OAUTH_APPROVAL.equals(param)) { params[i] = approvalParameter; } else { params[i] = param; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java index cfbea60d8..6ce085d0a 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java @@ -18,7 +18,6 @@ import java.security.Principal; import java.util.Collections; -import java.util.HashMap; import java.util.Map; import org.springframework.http.HttpHeaders; @@ -36,8 +35,8 @@ import org.springframework.security.oauth2.provider.ClientRegistrationException; import org.springframework.security.oauth2.provider.DefaultOAuth2RequestValidator; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.OAuth2RequestValidator; +import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; @@ -64,11 +63,10 @@ @RequestMapping(value = "/oauth/token") public class TokenEndpoint extends AbstractEndpoint { - private OAuth2RequestValidator oAuth2RequestValidator = new DefaultOAuth2RequestValidator(); + private OAuth2RequestValidator oAuth2RequestValidator = new DefaultOAuth2RequestValidator(); @RequestMapping public ResponseEntity getAccessToken(Principal principal, - @RequestParam(value = "grant_type", required = false) String grantType, @RequestParam Map parameters) { if (!(principal instanceof Authentication)) { @@ -76,10 +74,11 @@ public ResponseEntity getAccessToken(Principal principal, "There is no client authentication. Try adding an appropriate authentication filter."); } - HashMap request = new HashMap(parameters); + TokenRequest tokenRequest = getOAuth2RequestFactory().createTokenRequest(parameters); + String clientId = getClientId(principal); if (clientId != null) { - request.put("client_id", clientId); + tokenRequest.setClientId(clientId); //Only validate the client details if a client authenticated during this //request. ClientDetails client = getClientDetailsService().loadClientByClientId(clientId); @@ -88,11 +87,10 @@ public ResponseEntity getAccessToken(Principal principal, } } - if (!StringUtils.hasText(grantType)) { + if (!StringUtils.hasText(tokenRequest.getGrantType())) { throw new InvalidRequestException("Missing grant type"); } - OAuth2Request tokenRequest = getOAuth2RequestFactory().createOAuth2Request(request); if (isAuthCodeRequest(parameters) || isRefreshTokenRequest(parameters)) { // The scope was requested or determined during the authorization step if (!tokenRequest.getScope().isEmpty()) { @@ -100,13 +98,15 @@ public ResponseEntity getAccessToken(Principal principal, tokenRequest.setScope(Collections. emptySet()); } } + if (isRefreshTokenRequest(parameters)) { // A refresh token has its own default scopes, so we should ignore any added by the factory here. - tokenRequest.setScope(OAuth2Utils.parseParameterList(parameters.get("scope"))); + tokenRequest.setScope(OAuth2Utils.parseParameterList(parameters.get(OAuth2Utils.SCOPE))); } - OAuth2AccessToken token = getTokenGranter().grant(grantType, tokenRequest); + + OAuth2AccessToken token = getTokenGranter().grant(tokenRequest.getGrantType(), tokenRequest); if (token == null) { - throw new UnsupportedGrantTypeException("Unsupported grant type: " + grantType); + throw new UnsupportedGrantTypeException("Unsupported grant type: " + tokenRequest.getGrantType()); } return getResponse(token); @@ -125,7 +125,7 @@ protected String getClientId(Principal principal) { String clientId = client.getName(); if (client instanceof OAuth2Authentication) { // Might be a client and user combined authentication - clientId = ((OAuth2Authentication) client).getAuthorizationRequest().getClientId(); + clientId = ((OAuth2Authentication) client).getStoredRequest().getClientId(); } return clientId; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java index 770674f19..558e034da 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java @@ -41,9 +41,10 @@ import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.oauth2.common.util.OAuth2Utils; -import org.springframework.security.oauth2.provider.OAuth2Request; -import org.springframework.security.oauth2.provider.OAuth2RequestFactory; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; +import org.springframework.security.oauth2.provider.StoredOAuth2Request; import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; @@ -138,17 +139,19 @@ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) "No client authentication found. Remember to put a filter upstream of the TokenEndpointAuthenticationFilter."); } - OAuth2Request oAuth2Request = oAuth2RequestFactory.createOAuth2Request(getSingleValueMap(request)); + AuthorizationRequest authorizationRequest = oAuth2RequestFactory.createAuthorizationRequest(getSingleValueMap(request)); - oAuth2Request.setClientId(clientAuth.getName()); - oAuth2Request.setScope(getScope(request)); + authorizationRequest.setClientId(clientAuth.getName()); + authorizationRequest.setScope(getScope(request)); if (clientAuth.isAuthenticated()) { // Ensure the OAuth2Authentication is authenticated - oAuth2Request.setApproved(true); + authorizationRequest.setApproved(true); } + StoredOAuth2Request storedOAuth2Request = oAuth2RequestFactory.createStoredAuthorizationRequest(authorizationRequest); + SecurityContextHolder.getContext().setAuthentication( - new OAuth2Authentication(oAuth2Request, authResult)); + new OAuth2Authentication(storedOAuth2Request, authResult)); onSuccessfulAuthentication(request, response, authResult); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionUtils.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionUtils.java index 13eafe0c2..3aa678ebf 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionUtils.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionUtils.java @@ -19,7 +19,7 @@ import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.StoredOAuth2Request; /** * @author Dave Syer @@ -29,7 +29,7 @@ public abstract class OAuth2ExpressionUtils { public static boolean clientHasAnyRole(Authentication authentication, String... roles) { if (authentication instanceof OAuth2Authentication) { - OAuth2Request clientAuthentication = ((OAuth2Authentication) authentication).getAuthorizationRequest(); + StoredOAuth2Request clientAuthentication = ((OAuth2Authentication) authentication).getStoredRequest(); Collection clientAuthorities = clientAuthentication.getAuthorities(); if (clientAuthorities != null) { Set roleSet = AuthorityUtils.authorityListToSet(clientAuthorities); @@ -74,7 +74,7 @@ public static boolean isOAuthUserAuth(Authentication authentication) { public static boolean hasAnyScope(Authentication authentication, String[] scopes) { if (authentication instanceof OAuth2Authentication) { - OAuth2Request clientAuthentication = ((OAuth2Authentication) authentication).getAuthorizationRequest(); + StoredOAuth2Request clientAuthentication = ((OAuth2Authentication) authentication).getStoredRequest(); Collection assigned = clientAuthentication.getScope(); if (assigned != null) { for (String scope : scopes) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java index bd685631e..fe920a04f 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java @@ -20,9 +20,11 @@ import org.springframework.security.authentication.InsufficientAuthenticationException; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; +import org.springframework.security.oauth2.provider.StoredOAuth2Request; +import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.token.AbstractTokenGranter; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; @@ -34,19 +36,21 @@ public class ImplicitTokenGranter extends AbstractTokenGranter { private static final String GRANT_TYPE = "implicit"; - public ImplicitTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService) { - super(tokenServices, clientDetailsService, GRANT_TYPE); + public ImplicitTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory) { + super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE); } @Override - protected OAuth2Authentication getOAuth2Authentication(OAuth2Request clientToken) { + protected OAuth2Authentication getOAuth2Authentication(TokenRequest clientToken) { Authentication userAuth = SecurityContextHolder.getContext().getAuthentication(); if (userAuth==null || !userAuth.isAuthenticated()) { throw new InsufficientAuthenticationException("There is no currently logged in user"); } - return new OAuth2Authentication(clientToken, userAuth); + StoredOAuth2Request storedOAuth2Request = getRequestFactory().createStoredTokenRequest(clientToken); + + return new OAuth2Authentication(storedOAuth2Request, userAuth); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java index b647b566d..ccb4f760b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java @@ -16,7 +16,6 @@ package org.springframework.security.oauth2.provider.password; -import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -28,7 +27,9 @@ import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; +import org.springframework.security.oauth2.provider.StoredOAuth2Request; +import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.token.AbstractTokenGranter; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; @@ -43,13 +44,13 @@ public class ResourceOwnerPasswordTokenGranter extends AbstractTokenGranter { private final AuthenticationManager authenticationManager; public ResourceOwnerPasswordTokenGranter(AuthenticationManager authenticationManager, - AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService) { - super(tokenServices, clientDetailsService, GRANT_TYPE); + AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory) { + super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE); this.authenticationManager = authenticationManager; } @Override - protected OAuth2Authentication getOAuth2Authentication(OAuth2Request clientToken) { + protected OAuth2Authentication getOAuth2Authentication(TokenRequest clientToken) { Map parameters = clientToken.getRequestParameters(); String username = parameters.get("username"); @@ -75,9 +76,11 @@ protected OAuth2Authentication getOAuth2Authentication(OAuth2Request clientToken Map requestParameters = clientToken.getRequestParameters(); HashMap modifiable = new HashMap(requestParameters); modifiable.remove("password"); - - clientToken.setRequestParameters(Collections.unmodifiableMap(modifiable)); - return new OAuth2Authentication(clientToken, userAuth); + //Bypass the factory and instead create our own object here, since we want all the properties of the original TokenRequest, + //but with the new requestParameters map that has had the "password" parameter removed. + StoredOAuth2Request storedOAuth2Request = new StoredOAuth2Request(modifiable, clientToken.getClientId(), null, true, clientToken.getScope(), null, null, null); + + return new OAuth2Authentication(storedOAuth2Request, userAuth); } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/refresh/RefreshTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/refresh/RefreshTokenGranter.java index 4709924bd..e02e7163e 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/refresh/RefreshTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/refresh/RefreshTokenGranter.java @@ -17,8 +17,9 @@ package org.springframework.security.oauth2.provider.refresh; import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; +import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.token.AbstractTokenGranter; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; @@ -30,14 +31,14 @@ public class RefreshTokenGranter extends AbstractTokenGranter { private static final String GRANT_TYPE = "refresh_token"; - public RefreshTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService) { - super(tokenServices, clientDetailsService, GRANT_TYPE); + public RefreshTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory) { + super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE); } @Override - protected OAuth2AccessToken getAccessToken(OAuth2Request oAuth2Request) { - String refreshToken = oAuth2Request.getRequestParameters().get("refresh_token"); - return getTokenServices().refreshAccessToken(refreshToken, oAuth2Request); + protected OAuth2AccessToken getAccessToken(TokenRequest tokenRequest) { + String refreshToken = tokenRequest.getRequestParameters().get("refresh_token"); + return getTokenServices().refreshAccessToken(refreshToken, tokenRequest); } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AbstractTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AbstractTokenGranter.java index 1d7f41aeb..6984b1471 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AbstractTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AbstractTokenGranter.java @@ -21,8 +21,10 @@ import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; +import org.springframework.security.oauth2.provider.StoredOAuth2Request; import org.springframework.security.oauth2.provider.TokenGranter; +import org.springframework.security.oauth2.provider.TokenRequest; /** * @author Dave Syer @@ -36,16 +38,19 @@ public abstract class AbstractTokenGranter implements TokenGranter { private final ClientDetailsService clientDetailsService; + private final OAuth2RequestFactory requestFactory; + private final String grantType; protected AbstractTokenGranter(AuthorizationServerTokenServices tokenServices, - ClientDetailsService clientDetailsService, String grantType) { + ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory, String grantType) { this.clientDetailsService = clientDetailsService; this.grantType = grantType; this.tokenServices = tokenServices; + this.requestFactory = requestFactory; } - public OAuth2AccessToken grant(String grantType, OAuth2Request tokenRequest) { + public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) { if (!this.grantType.equals(grantType)) { return null; @@ -58,18 +63,19 @@ public OAuth2AccessToken grant(String grantType, OAuth2Request tokenRequest) { logger.debug("Getting access token for: " + clientId); // FIXME: do we need to explicitly set approved flag here? - tokenRequest.setApproved(true); + //tokenRequest.setApproved(true); return getAccessToken(tokenRequest); } - protected OAuth2AccessToken getAccessToken(OAuth2Request tokenRequest) { + protected OAuth2AccessToken getAccessToken(TokenRequest tokenRequest) { return tokenServices.createAccessToken(getOAuth2Authentication(tokenRequest)); } - protected OAuth2Authentication getOAuth2Authentication(OAuth2Request tokenRequest) { - return new OAuth2Authentication(tokenRequest, null); + protected OAuth2Authentication getOAuth2Authentication(TokenRequest tokenRequest) { + StoredOAuth2Request storedOAuth2Request = requestFactory.createStoredTokenRequest(tokenRequest); + return new OAuth2Authentication(storedOAuth2Request, null); } protected void validateGrantType(String grantType, ClientDetails clientDetails) { @@ -83,5 +89,9 @@ protected void validateGrantType(String grantType, ClientDetails clientDetails) protected AuthorizationServerTokenServices getTokenServices() { return tokenServices; } + + protected OAuth2RequestFactory getRequestFactory() { + return requestFactory; + } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AuthorizationServerTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AuthorizationServerTokenServices.java index c6596555e..5df146db5 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AuthorizationServerTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AuthorizationServerTokenServices.java @@ -19,7 +19,7 @@ import org.springframework.security.core.AuthenticationException; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.TokenRequest; /** * @author Ryan Heaton @@ -42,11 +42,11 @@ public interface AuthorizationServerTokenServices { * (if provided). * * @param refreshToken The details about the refresh token. - * @param request The incoming authorization request. + * @param tokenRequest The incoming token request. * @return The (new) access token. * @throws AuthenticationException If the refresh token is invalid or expired. */ - OAuth2AccessToken refreshAccessToken(String refreshToken, OAuth2Request request) + OAuth2AccessToken refreshAccessToken(String refreshToken, TokenRequest tokenRequest) throws AuthenticationException; /** diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAuthenticationKeyGenerator.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAuthenticationKeyGenerator.java index 4a87fec71..6854b9226 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAuthenticationKeyGenerator.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAuthenticationKeyGenerator.java @@ -21,7 +21,7 @@ import org.springframework.security.oauth2.common.util.OAuth2Utils; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.StoredOAuth2Request; /** * Basic key generator taking into account the client id, scope, reource ids and username (principal name) if they @@ -40,7 +40,7 @@ public class DefaultAuthenticationKeyGenerator implements AuthenticationKeyGener public String extractKey(OAuth2Authentication authentication) { Map values = new LinkedHashMap(); - OAuth2Request authorizationRequest = authentication.getAuthorizationRequest(); + StoredOAuth2Request authorizationRequest = authentication.getStoredRequest(); if (!authentication.isClientOnly()) { values.put(USERNAME, authentication.getName()); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java index 98c6d8ddc..00cd6e99d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java @@ -31,7 +31,8 @@ import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.StoredOAuth2Request; +import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.util.Assert; /** @@ -112,7 +113,7 @@ else if (refreshToken instanceof ExpiringOAuth2RefreshToken) { } - public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, OAuth2Request request) + public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, TokenRequest tokenRequest) throws AuthenticationException { if (!supportRefreshToken) { @@ -125,8 +126,8 @@ public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, OAuth2Requ } OAuth2Authentication authentication = tokenStore.readAuthenticationForRefreshToken(refreshToken); - String clientId = authentication.getAuthorizationRequest().getClientId(); - if (clientId == null || !clientId.equals(request.getClientId())) { + String clientId = authentication.getStoredRequest().getClientId(); + if (clientId == null || !clientId.equals(tokenRequest.getClientId())) { throw new InvalidGrantException("Wrong client for this refresh token: " + refreshTokenValue); } @@ -138,7 +139,7 @@ public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, OAuth2Requ throw new InvalidTokenException("Invalid refresh token (expired): " + refreshToken); } - authentication = createRefreshedAuthentication(authentication, request.getScope()); + authentication = createRefreshedAuthentication(authentication, tokenRequest.getScope()); if (!reuseRefreshToken) { tokenStore.removeRefreshToken(refreshToken); @@ -168,7 +169,7 @@ public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) { private OAuth2Authentication createRefreshedAuthentication(OAuth2Authentication authentication, Set scope) { OAuth2Authentication narrowed = authentication; if (scope != null && !scope.isEmpty()) { - OAuth2Request clientAuth = authentication.getAuthorizationRequest(); + StoredOAuth2Request clientAuth = authentication.getStoredRequest(); Set originalScope = clientAuth.getScope(); if (originalScope == null || !originalScope.containsAll(scope)) { throw new InvalidScopeException("Unable to narrow the scope of the client authentication to " + scope @@ -213,11 +214,11 @@ public String getClientId(String tokenValue) { if (authentication == null) { throw new InvalidTokenException("Invalid access token: " + tokenValue); } - OAuth2Request authorizationRequest = authentication.getAuthorizationRequest(); - if (authorizationRequest == null) { + StoredOAuth2Request clientAuth = authentication.getStoredRequest(); + if (clientAuth == null) { throw new InvalidTokenException("Invalid access token (no client id): " + tokenValue); } - return authorizationRequest.getClientId(); + return clientAuth.getClientId(); } public Collection findTokensByUserName(String userName) { @@ -241,10 +242,10 @@ public boolean revokeToken(String tokenValue) { } private ExpiringOAuth2RefreshToken createRefreshToken(OAuth2Authentication authentication) { - if (!isSupportRefreshToken(authentication.getAuthorizationRequest())) { + if (!isSupportRefreshToken(authentication.getStoredRequest())) { return null; } - int validitySeconds = getRefreshTokenValiditySeconds(authentication.getAuthorizationRequest()); + int validitySeconds = getRefreshTokenValiditySeconds(authentication.getStoredRequest()); ExpiringOAuth2RefreshToken refreshToken = new DefaultExpiringOAuth2RefreshToken(UUID.randomUUID().toString(), new Date(System.currentTimeMillis() + (validitySeconds * 1000L))); return refreshToken; @@ -252,12 +253,12 @@ private ExpiringOAuth2RefreshToken createRefreshToken(OAuth2Authentication authe private OAuth2AccessToken createAccessToken(OAuth2Authentication authentication, OAuth2RefreshToken refreshToken) { DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(UUID.randomUUID().toString()); - int validitySeconds = getAccessTokenValiditySeconds(authentication.getAuthorizationRequest()); + int validitySeconds = getAccessTokenValiditySeconds(authentication.getStoredRequest()); if (validitySeconds > 0) { token.setExpiration(new Date(System.currentTimeMillis() + (validitySeconds * 1000L))); } token.setRefreshToken(refreshToken); - token.setScope(authentication.getAuthorizationRequest().getScope()); + token.setScope(authentication.getStoredRequest().getScope()); return accessTokenEnhancer != null ? accessTokenEnhancer.enhance(token, authentication) : token; } @@ -267,9 +268,9 @@ private OAuth2AccessToken createAccessToken(OAuth2Authentication authentication, * @param authorizationRequest the current authorization request * @return the access token validity period in seconds */ - protected int getAccessTokenValiditySeconds(OAuth2Request authorizationRequest) { + protected int getAccessTokenValiditySeconds(StoredOAuth2Request clientAuth) { if (clientDetailsService != null) { - ClientDetails client = clientDetailsService.loadClientByClientId(authorizationRequest.getClientId()); + ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId()); Integer validity = client.getAccessTokenValiditySeconds(); if (validity != null) { return validity; @@ -283,9 +284,9 @@ protected int getAccessTokenValiditySeconds(OAuth2Request authorizationRequest) * @param authorizationRequest the current authorization request * @return the refresh token validity period in seconds */ - protected int getRefreshTokenValiditySeconds(OAuth2Request authorizationRequest) { + protected int getRefreshTokenValiditySeconds(StoredOAuth2Request clientAuth) { if (clientDetailsService != null) { - ClientDetails client = clientDetailsService.loadClientByClientId(authorizationRequest.getClientId()); + ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId()); Integer validity = client.getRefreshTokenValiditySeconds(); if (validity != null) { return validity; @@ -300,9 +301,9 @@ protected int getRefreshTokenValiditySeconds(OAuth2Request authorizationRequest) * @param authorizationRequest the current authorization request * @return boolean to indicate if refresh token is supported */ - protected boolean isSupportRefreshToken(OAuth2Request authorizationRequest) { + protected boolean isSupportRefreshToken(StoredOAuth2Request clientAuth) { if (clientDetailsService != null) { - ClientDetails client = clientDetailsService.loadClientByClientId(authorizationRequest.getClientId()); + ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId()); return client.getAuthorizedGrantTypes().contains("refresh_token"); } return this.supportRefreshToken; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStore.java index 0f4c76e8c..8dec551c7 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStore.java @@ -150,7 +150,7 @@ public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authe if (!authentication.isClientOnly()) { addToCollection(this.userNameToAccessTokenStore, authentication.getName(), token); } - addToCollection(this.clientIdToAccessTokenStore, authentication.getAuthorizationRequest().getClientId(), token); + addToCollection(this.clientIdToAccessTokenStore, authentication.getStoredRequest().getClientId(), token); if (token.getExpiration() != null) { TokenExpiry expiry = new TokenExpiry(token.getValue(), token.getExpiration()); // Remove existing expiry for this token if present @@ -198,7 +198,7 @@ public void removeAccessToken(String tokenValue) { if (tokens != null) { tokens.remove(removed); } - String clientId = authentication.getAuthorizationRequest().getClientId(); + String clientId = authentication.getStoredRequest().getClientId(); tokens = this.clientIdToAccessTokenStore.get(clientId); if (tokens != null) { tokens.remove(removed); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JdbcTokenStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JdbcTokenStore.java index e2766bb34..bc2695ae0 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JdbcTokenStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JdbcTokenStore.java @@ -137,7 +137,7 @@ public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authe jdbcTemplate.update(insertAccessTokenSql, new Object[] { extractTokenKey(token.getValue()), new SqlLobValue(serializeAccessToken(token)), authenticationKeyGenerator.extractKey(authentication), authentication.isClientOnly() ? null : authentication.getName(), - authentication.getAuthorizationRequest().getClientId(), + authentication.getStoredRequest().getClientId(), new SqlLobValue(serializeAuthentication(authentication)), extractTokenKey(refreshToken) }, new int[] { Types.VARCHAR, Types.BLOB, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.BLOB, Types.VARCHAR }); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/vote/ScopeVoter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/vote/ScopeVoter.java index 6df759a01..eba497400 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/vote/ScopeVoter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/vote/ScopeVoter.java @@ -25,8 +25,9 @@ import org.springframework.security.access.ConfigAttribute; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.common.exceptions.InsufficientScopeException; -import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.StoredOAuth2Request; /** *

@@ -39,8 +40,8 @@ *

* Abstains from voting if no configuration attribute commences with the scope prefix, or if the current * Authentication is not a {@link OAuth2Authentication} or the current client authentication is not a - * {@link OAuth2Request} (which contains teh scope data). Votes to grant access if there is an exact matching - * {@link OAuth2Request#getScope() authorized scope} to a ConfigAttribute starting with the scope + * {@link AuthorizationRequest} (which contains the scope data). Votes to grant access if there is an exact matching + * {@link AuthorizationRequest#getScope() authorized scope} to a ConfigAttribute starting with the scope * prefix. Votes to deny access if there is no exact matching authorized scope to a ConfigAttribute * starting with the scope prefix. *

@@ -131,7 +132,7 @@ public int vote(Authentication authentication, Object object, Collection scopes = new HashSet(); + scopes.addAll(Arrays.asList("read", "write")); + StoredOAuth2Request storedOAuth2Request = new StoredOAuth2Request(null, "client", null, false, scopes, null, null, null); + this.authentication = new OAuth2Authentication(storedOAuth2Request, null); Mockito.when(tokenServices.loadAuthentication("FOO")).thenReturn(authentication); Authentication authentication = filter.attemptAuthentication(null, null); assertEquals(this.authentication, authentication); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/TestAuthorizationServerCustomGrantParser.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/TestAuthorizationServerCustomGrantParser.java index 386524404..caa482d9b 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/TestAuthorizationServerCustomGrantParser.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/TestAuthorizationServerCustomGrantParser.java @@ -10,8 +10,8 @@ import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.provider.CompositeTokenGranter; -import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.TokenGranter; +import org.springframework.security.oauth2.provider.TokenRequest; public class TestAuthorizationServerCustomGrantParser { @@ -37,7 +37,7 @@ public static class CustomTestTokenGranter implements TokenGranter { public CustomTestTokenGranter() {} public OAuth2AccessToken grant(String grantType, - OAuth2Request OAuth2Request) { + TokenRequest tokenRequest) { if (grantType.equals("test-grant")) { return new DefaultOAuth2AccessToken("test"); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationRequest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationRequest.java index 5a014c19b..36db196fb 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationRequest.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationRequest.java @@ -19,7 +19,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import static org.springframework.security.oauth2.provider.OAuth2Request.REDIRECT_URI; import java.util.Arrays; import java.util.Collections; @@ -52,22 +51,22 @@ public void prepare() { parameters.put("redirect_uri", "http://www.callistaenterprise.se/"); } - private OAuth2Request createFromParameters(Map authorizationParameters) { - OAuth2Request request = new OAuth2Request(authorizationParameters, Collections. emptyMap(), - authorizationParameters.get(OAuth2Request.CLIENT_ID), - OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Request.SCOPE)), null, - null, false, authorizationParameters.get(OAuth2Request.STATE), - authorizationParameters.get(OAuth2Request.REDIRECT_URI), - OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Request.RESPONSE_TYPE))); + private AuthorizationRequest createFromParameters(Map authorizationParameters) { + AuthorizationRequest request = new AuthorizationRequest(authorizationParameters, Collections. emptyMap(), + authorizationParameters.get(OAuth2Utils.CLIENT_ID), + OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Utils.SCOPE)), null, + null, false, authorizationParameters.get(OAuth2Utils.STATE), + authorizationParameters.get(OAuth2Utils.REDIRECT_URI), + OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Utils.RESPONSE_TYPE))); return request; } @Test public void testApproval() throws Exception { - OAuth2Request oAuth2Request = createFromParameters(parameters); - assertFalse(oAuth2Request.isApproved()); - oAuth2Request.setApproved(true); - assertTrue(oAuth2Request.isApproved()); + AuthorizationRequest authorizationRequest = createFromParameters(parameters); + assertFalse(authorizationRequest.isApproved()); + authorizationRequest.setApproved(true); + assertTrue(authorizationRequest.isApproved()); } /** @@ -78,31 +77,31 @@ public void testApproval() throws Exception { @Test public void testScopeNotSetInParameters() throws Exception { parameters.put("scope", "read,write"); - OAuth2Request oAuth2Request = createFromParameters(parameters); - oAuth2Request.setScope(StringUtils.commaDelimitedListToSet("foo,bar")); - assertFalse(oAuth2Request.getRequestParameters().get(OAuth2Request.SCOPE).contains("bar")); - assertFalse(oAuth2Request.getRequestParameters().get(OAuth2Request.SCOPE).contains("foo")); + AuthorizationRequest authorizationRequest = createFromParameters(parameters); + authorizationRequest.setScope(StringUtils.commaDelimitedListToSet("foo,bar")); + assertFalse(authorizationRequest.getRequestParameters().get(OAuth2Utils.SCOPE).contains("bar")); + assertFalse(authorizationRequest.getRequestParameters().get(OAuth2Utils.SCOPE).contains("foo")); } @Test public void testClientIdNotOverwitten() throws Exception { - OAuth2Request oAuth2Request = new OAuth2Request("client", Arrays.asList("read")); + AuthorizationRequest authorizationRequest = new AuthorizationRequest("client", Arrays.asList("read")); parameters = new HashMap(); parameters.put("scope", "write"); - oAuth2Request.setRequestParameters(parameters); + authorizationRequest.setRequestParameters(parameters); - assertEquals("client", oAuth2Request.getClientId()); - assertEquals(1, oAuth2Request.getScope().size()); - assertTrue(oAuth2Request.getScope().contains("read")); - assertFalse(oAuth2Request.getRequestParameters().get(OAuth2Request.SCOPE).contains("read")); + assertEquals("client", authorizationRequest.getClientId()); + assertEquals(1, authorizationRequest.getScope().size()); + assertTrue(authorizationRequest.getScope().contains("read")); + assertFalse(authorizationRequest.getRequestParameters().get(OAuth2Utils.SCOPE).contains("read")); } @Test public void testScopeWithSpace() throws Exception { parameters.put("scope", "bar foo"); - OAuth2Request oAuth2Request = createFromParameters(parameters); - oAuth2Request.setScope(Collections.singleton("foo bar")); - assertEquals("bar foo", oAuth2Request.getRequestParameters().get(OAuth2Request.SCOPE)); + AuthorizationRequest authorizationRequest = createFromParameters(parameters); + authorizationRequest.setScope(Collections.singleton("foo bar")); + assertEquals("bar foo", authorizationRequest.getRequestParameters().get(OAuth2Utils.SCOPE)); } /** @@ -121,12 +120,12 @@ public void testScopeSortedOrder() { String sortedScopeString = OAuth2Utils.formatParameterList(sortedSet); parameters.put("scope", scopeString); - OAuth2Request oAuth2Request = createFromParameters(parameters); - oAuth2Request.setScope(sortedSet); + AuthorizationRequest authorizationRequest = createFromParameters(parameters); + authorizationRequest.setScope(sortedSet); // Assert that the scope parameter is still sorted - String fromAR = OAuth2Utils.formatParameterList(oAuth2Request.getScope()); + String fromAR = OAuth2Utils.formatParameterList(authorizationRequest.getScope()); Assert.assertEquals(sortedScopeString, fromAR); } @@ -134,13 +133,13 @@ public void testScopeSortedOrder() { @Test public void testRedirectUriDefaultsToMap() { parameters.put("scope", "one two"); - OAuth2Request oAuth2Request = createFromParameters(parameters); + AuthorizationRequest authorizationRequest = createFromParameters(parameters); - assertEquals("XYZ123", oAuth2Request.getState()); - assertEquals("theClient", oAuth2Request.getClientId()); - assertEquals("http://www.callistaenterprise.se/", oAuth2Request.getRedirectUri()); - assertEquals("http://www.callistaenterprise.se/", oAuth2Request.getRequestParameters().get(REDIRECT_URI)); - assertEquals("[one, two]", oAuth2Request.getScope().toString()); + assertEquals("XYZ123", authorizationRequest.getState()); + assertEquals("theClient", authorizationRequest.getClientId()); + assertEquals("http://www.callistaenterprise.se/", authorizationRequest.getRedirectUri()); + assertEquals("http://www.callistaenterprise.se/", authorizationRequest.getRequestParameters().get(OAuth2Utils.REDIRECT_URI)); + assertEquals("[one, two]", authorizationRequest.getScope().toString()); } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestDefaultAuthorizationRequest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestDefaultAuthorizationRequest.java index 7bf75cec2..83578ba3a 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestDefaultAuthorizationRequest.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestDefaultAuthorizationRequest.java @@ -51,22 +51,22 @@ public void prepare() { parameters.put("redirect_uri", "http://www.callistaenterprise.se/"); } - private OAuth2Request createFromParameters(Map authorizationParameters) { - OAuth2Request request = new OAuth2Request(authorizationParameters, Collections. emptyMap(), - authorizationParameters.get(OAuth2Request.CLIENT_ID), - OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Request.SCOPE)), null, - null, false, authorizationParameters.get(OAuth2Request.STATE), - authorizationParameters.get(OAuth2Request.REDIRECT_URI), - OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Request.RESPONSE_TYPE))); + private AuthorizationRequest createFromParameters(Map authorizationParameters) { + AuthorizationRequest request = new AuthorizationRequest(authorizationParameters, Collections. emptyMap(), + authorizationParameters.get(OAuth2Utils.CLIENT_ID), + OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Utils.SCOPE)), null, + null, false, authorizationParameters.get(OAuth2Utils.STATE), + authorizationParameters.get(OAuth2Utils.REDIRECT_URI), + OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Utils.RESPONSE_TYPE))); return request; } @Test public void testApproval() throws Exception { - OAuth2Request oAuth2Request = createFromParameters(parameters); - assertFalse(oAuth2Request.isApproved()); - oAuth2Request.setApproved(true); - assertTrue(oAuth2Request.isApproved()); + AuthorizationRequest authorizationRequest = createFromParameters(parameters); + assertFalse(authorizationRequest.isApproved()); + authorizationRequest.setApproved(true); + assertTrue(authorizationRequest.isApproved()); } /** @@ -77,31 +77,31 @@ public void testApproval() throws Exception { @Test public void testScopeNotSetInParameters() throws Exception { parameters.put("scope", "read,write"); - OAuth2Request oAuth2Request = createFromParameters(parameters); - oAuth2Request.setScope(StringUtils.commaDelimitedListToSet("foo,bar")); - assertFalse(oAuth2Request.getRequestParameters().get(OAuth2Request.SCOPE).contains("bar")); - assertFalse(oAuth2Request.getRequestParameters().get(OAuth2Request.SCOPE).contains("foo")); + AuthorizationRequest authorizationRequest = createFromParameters(parameters); + authorizationRequest.setScope(StringUtils.commaDelimitedListToSet("foo,bar")); + assertFalse(authorizationRequest.getRequestParameters().get(OAuth2Utils.SCOPE).contains("bar")); + assertFalse(authorizationRequest.getRequestParameters().get(OAuth2Utils.SCOPE).contains("foo")); } @Test public void testClientIdNotOverwitten() throws Exception { - OAuth2Request oAuth2Request = new OAuth2Request("client", Arrays.asList("read")); + AuthorizationRequest authorizationRequest = new AuthorizationRequest("client", Arrays.asList("read")); parameters = new HashMap(); parameters.put("scope", "write"); - oAuth2Request.setRequestParameters(parameters); + authorizationRequest.setRequestParameters(parameters); - assertEquals("client", oAuth2Request.getClientId()); - assertEquals(1, oAuth2Request.getScope().size()); - assertTrue(oAuth2Request.getScope().contains("read")); - assertFalse(oAuth2Request.getRequestParameters().get(OAuth2Request.SCOPE).contains("read")); + assertEquals("client", authorizationRequest.getClientId()); + assertEquals(1, authorizationRequest.getScope().size()); + assertTrue(authorizationRequest.getScope().contains("read")); + assertFalse(authorizationRequest.getRequestParameters().get(OAuth2Utils.SCOPE).contains("read")); } @Test public void testScopeWithSpace() throws Exception { parameters.put("scope", "bar foo"); - OAuth2Request oAuth2Request = createFromParameters(parameters); - oAuth2Request.setScope(Collections.singleton("foo bar")); - assertEquals("bar foo", oAuth2Request.getRequestParameters().get(OAuth2Request.SCOPE)); + AuthorizationRequest authorizationRequest = createFromParameters(parameters); + authorizationRequest.setScope(Collections.singleton("foo bar")); + assertEquals("bar foo", authorizationRequest.getRequestParameters().get(OAuth2Utils.SCOPE)); } /** @@ -120,12 +120,12 @@ public void testScopeSortedOrder() { String sortedScopeString = OAuth2Utils.formatParameterList(sortedSet); parameters.put("scope", scopeString); - OAuth2Request oAuth2Request = createFromParameters(parameters); - oAuth2Request.setScope(sortedSet); + AuthorizationRequest authorizationRequest = createFromParameters(parameters); + authorizationRequest.setScope(sortedSet); // Assert that the scope parameter is still sorted - String fromAR = OAuth2Utils.formatParameterList(oAuth2Request.getScope()); + String fromAR = OAuth2Utils.formatParameterList(authorizationRequest.getScope()); Assert.assertEquals(sortedScopeString, fromAR); } @@ -133,13 +133,13 @@ public void testScopeSortedOrder() { @Test public void testRedirectUriDefaultsToMap() { parameters.put("scope", "one two"); - OAuth2Request oAuth2Request = createFromParameters(parameters); + AuthorizationRequest authorizationRequest = createFromParameters(parameters); - assertEquals("XYZ123", oAuth2Request.getState()); - assertEquals("theClient", oAuth2Request.getClientId()); - assertEquals("http://www.callistaenterprise.se/", oAuth2Request.getRedirectUri()); - assertEquals("http://www.callistaenterprise.se/", oAuth2Request.getRequestParameters().get(OAuth2Request.REDIRECT_URI)); - assertEquals("[one, two]", oAuth2Request.getScope().toString()); + assertEquals("XYZ123", authorizationRequest.getState()); + assertEquals("theClient", authorizationRequest.getClientId()); + assertEquals("http://www.callistaenterprise.se/", authorizationRequest.getRedirectUri()); + assertEquals("http://www.callistaenterprise.se/", authorizationRequest.getRequestParameters().get(OAuth2Utils.REDIRECT_URI)); + assertEquals("[one, two]", authorizationRequest.getScope().toString()); } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestDefaultAuthorizationRequestManager.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestDefaultAuthorizationRequestManager.java index 66a308802..58b950674 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestDefaultAuthorizationRequestManager.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestDefaultAuthorizationRequestManager.java @@ -44,13 +44,13 @@ public void start() { @Test public void testCreateAuthorizationRequest() { - OAuth2Request request = factory.createOAuth2Request(Collections.singletonMap("client_id", "foo")); + AuthorizationRequest request = factory.createAuthorizationRequest(Collections.singletonMap("client_id", "foo")); assertEquals("foo", request.getClientId()); } @Test public void testCreateAuthorizationRequestWithDefaultScopes() { - OAuth2Request request = factory.createOAuth2Request(Collections.singletonMap("client_id", "foo")); + AuthorizationRequest request = factory.createAuthorizationRequest(Collections.singletonMap("client_id", "foo")); assertEquals("[bar]", request.getScope().toString()); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestOAuth2Authentication.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestOAuth2Authentication.java index 6a24d2a06..4895eb952 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestOAuth2Authentication.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestOAuth2Authentication.java @@ -3,24 +3,25 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import java.util.Arrays; import java.util.Collections; import org.codehaus.jackson.map.ObjectMapper; import org.junit.Test; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.test.annotation.Rollback; public class TestOAuth2Authentication { - private OAuth2Request request = new OAuth2Request("id", Arrays.asList("read")); + private StoredOAuth2Request request = new StoredOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null); private UsernamePasswordAuthenticationToken userAuthentication = new UsernamePasswordAuthenticationToken("foo", "bar", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"))); @Test + @Rollback public void testIsAuthenticated() { - request.setApproved(true); + request = new StoredOAuth2Request(null, "id", null, true, Collections.singleton("read"), null, null, null); OAuth2Authentication authentication = new OAuth2Authentication(request, userAuthentication); assertTrue(authentication.isAuthenticated()); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestDefaultUserApprovalHandler.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestDefaultUserApprovalHandler.java index 50045a47b..c51981730 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestDefaultUserApprovalHandler.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestDefaultUserApprovalHandler.java @@ -18,7 +18,7 @@ import org.junit.Test; import org.springframework.security.authentication.AbstractAuthenticationToken; -import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.AuthorizationRequest; /** * @author Dave Syer @@ -30,7 +30,7 @@ public class TestDefaultUserApprovalHandler { @Test public void testBasicApproval() { - OAuth2Request request =new OAuth2Request(new HashMap(), null, null, null, null, null, false, null, null, null); + AuthorizationRequest request =new AuthorizationRequest(new HashMap(), null, null, null, null, null, false, null, null, null); request.setApproved(true); // This isn't enough to be explicitly approved assertFalse(handler.isApproved(request, new TestAuthentication("marissa", true))); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenServicesUserApprovalHandler.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenServicesUserApprovalHandler.java index a141da13c..578b57eb0 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenServicesUserApprovalHandler.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenServicesUserApprovalHandler.java @@ -15,13 +15,15 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import java.util.Collections; import java.util.HashMap; import org.junit.Test; import org.springframework.security.authentication.AbstractAuthenticationToken; -import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.common.util.OAuth2Utils; +import org.springframework.security.oauth2.provider.DefaultOAuth2RequestFactory; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.StoredOAuth2Request; import org.springframework.security.oauth2.provider.token.DefaultTokenServices; import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; @@ -34,10 +36,13 @@ public class TestTokenServicesUserApprovalHandler { private TokenServicesUserApprovalHandler handler = new TokenServicesUserApprovalHandler(); private DefaultTokenServices tokenServices = new DefaultTokenServices(); + + private DefaultOAuth2RequestFactory requestFactory = new DefaultOAuth2RequestFactory(null); { tokenServices.setTokenStore(new InMemoryTokenStore()); handler.setTokenServices(tokenServices); + handler.setRequestFactory(requestFactory); } @Test(expected = IllegalStateException.class) @@ -48,19 +53,25 @@ public void testMandatoryProperties() throws Exception { @Test public void testBasicApproval() { - OAuth2Request request = new OAuth2Request(new HashMap(), null, null, null, null, null, false, null, null, null); + HashMap parameters = new HashMap(); + parameters.put(OAuth2Utils.USER_OAUTH_APPROVAL, "true"); + AuthorizationRequest request = new AuthorizationRequest(parameters, null, null, null, null, null, false, null, null, null); request.setApproved(true); // This isn't enough to be explicitly approved assertFalse(handler.isApproved(request , new TestAuthentication("marissa", true))); } @Test public void testMemorizedApproval() { - OAuth2Request oAuth2Request = new OAuth2Request(Collections.singletonMap( - "client_id", "foo"), null, "foo", null, null, null, false, null, null, null); - oAuth2Request.setApproved(false); + HashMap parameters = new HashMap(); + parameters.put(OAuth2Utils.USER_OAUTH_APPROVAL, "false"); + parameters.put("client_id", "foo"); + AuthorizationRequest authorizationRequest = new AuthorizationRequest(parameters, null, "foo", null, null, null, false, null, null, null); + authorizationRequest.setApproved(false); TestAuthentication userAuthentication = new TestAuthentication("marissa", true); - tokenServices.createAccessToken(new OAuth2Authentication(oAuth2Request, userAuthentication)); - assertTrue(handler.isApproved(oAuth2Request, userAuthentication)); + StoredOAuth2Request storedOAuth2Request = requestFactory.createStoredAuthorizationRequest(authorizationRequest); + + tokenServices.createAccessToken(new OAuth2Authentication(storedOAuth2Request, userAuthentication)); + assertTrue(handler.isApproved(authorizationRequest, userAuthentication)); } protected static class TestAuthentication extends AbstractAuthenticationToken { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationManager.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationManager.java index 60914b5aa..3cbeaf794 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationManager.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationManager.java @@ -16,14 +16,12 @@ import static org.junit.Assert.assertEquals; -import java.util.Collections; - import org.junit.Test; import org.mockito.Mockito; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.StoredOAuth2Request; import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices; import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken; @@ -39,8 +37,7 @@ public class TestOAuth2AuthenticationManager { private Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala"); - private OAuth2Authentication authentication = new OAuth2Authentication(new OAuth2Request( - Collections. emptyMap(), null, null, null, null, null, false, null, null, null), userAuthentication); + private OAuth2Authentication authentication = new OAuth2Authentication(new StoredOAuth2Request(null, "foo", null, false, null, null, null, null), userAuthentication); { manager.setTokenServices(tokenServices); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationProcessingFilter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationProcessingFilter.java index b10def1a5..9a280dc07 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationProcessingFilter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationProcessingFilter.java @@ -17,8 +17,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import java.util.Collections; - import javax.servlet.FilterChain; import org.junit.After; @@ -30,8 +28,8 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.StoredOAuth2Request; /** * @author Dave Syer @@ -45,8 +43,7 @@ public class TestOAuth2AuthenticationProcessingFilter { private Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala"); - private OAuth2Authentication authentication = new OAuth2Authentication(new OAuth2Request( - Collections. emptyMap(), null, null, null, null, null, false, null, null, null), userAuthentication); + private OAuth2Authentication authentication = new OAuth2Authentication(new StoredOAuth2Request(null, "foo", null, false, null, null, null, null), userAuthentication); private FilterChain chain = Mockito.mock(FilterChain.class); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeServicesBase.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeServicesBase.java index 1ae392dec..0f28ddf9d 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeServicesBase.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeServicesBase.java @@ -7,7 +7,8 @@ import org.junit.Test; import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; -import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.StoredOAuth2Request; public abstract class TestAuthorizationCodeServicesBase { @@ -15,26 +16,28 @@ public abstract class TestAuthorizationCodeServicesBase { @Test public void testCreateAuthorizationCode() { - AuthorizationRequestHolder expectedAuthentication = new AuthorizationRequestHolder( - new OAuth2Request("id", null), new TestAuthentication( + StoredOAuth2Request storedOAuth2Request = new StoredOAuth2Request(null, "id", null, false, null, null, null, null); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication( + storedOAuth2Request, new TestAuthentication( "test2", false)); String code = getAuthorizationCodeServices().createAuthorizationCode(expectedAuthentication); assertNotNull(code); - AuthorizationRequestHolder actualAuthentication = getAuthorizationCodeServices() + OAuth2Authentication actualAuthentication = getAuthorizationCodeServices() .consumeAuthorizationCode(code); assertEquals(expectedAuthentication, actualAuthentication); } @Test public void testConsumeRemovesCode() { - AuthorizationRequestHolder expectedAuthentication = new AuthorizationRequestHolder( - new OAuth2Request("id", null), new TestAuthentication( + StoredOAuth2Request storedOAuth2Request = new StoredOAuth2Request(null, "id", null, false, null, null, null, null); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication( + storedOAuth2Request, new TestAuthentication( "test2", false)); String code = getAuthorizationCodeServices().createAuthorizationCode(expectedAuthentication); assertNotNull(code); - AuthorizationRequestHolder actualAuthentication = getAuthorizationCodeServices() + OAuth2Authentication actualAuthentication = getAuthorizationCodeServices() .consumeAuthorizationCode(code); assertEquals(expectedAuthentication, actualAuthentication); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeTokenGranter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeTokenGranter.java index c55fcc8f6..ffeb0c612 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeTokenGranter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeTokenGranter.java @@ -16,9 +16,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import static org.springframework.security.oauth2.provider.OAuth2Request.REDIRECT_URI; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -32,13 +30,16 @@ import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.common.exceptions.RedirectMismatchException; import org.springframework.security.oauth2.common.util.OAuth2Utils; -import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.DefaultOAuth2RequestFactory; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; +import org.springframework.security.oauth2.provider.StoredOAuth2Request; +import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.token.DefaultTokenServices; import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; -import org.springframework.util.StringUtils; /** * @author Dave Syer @@ -58,18 +59,10 @@ public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exceptio }; private AuthorizationCodeServices authorizationCodeServices = new InMemoryAuthorizationCodeServices(); + + private OAuth2RequestFactory requestFactory = new DefaultOAuth2RequestFactory(clientDetailsService); private Map parameters = new HashMap(); - - private OAuth2Request createFromParameters(Map authorizationParameters) { - OAuth2Request request = new OAuth2Request(authorizationParameters, Collections. emptyMap(), - authorizationParameters.get(OAuth2Request.CLIENT_ID), - OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Request.SCOPE)), null, - null, false, authorizationParameters.get(OAuth2Request.STATE), - authorizationParameters.get(OAuth2Request.REDIRECT_URI), - OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Request.RESPONSE_TYPE))); - return request; - } public TestAuthorizationCodeTokenGranter() { providerTokenServices.setTokenStore(new InMemoryTokenStore()); @@ -77,116 +70,131 @@ public TestAuthorizationCodeTokenGranter() { @Test public void testAuthorizationCodeGrant() { - OAuth2Request oAuth2Request = new OAuth2Request("foo", - Arrays.asList("scope")); - oAuth2Request.setApproved(true); + Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); - String code = authorizationCodeServices.createAuthorizationCode(new AuthorizationRequestHolder( - oAuth2Request, userAuthentication)); - parameters.putAll(oAuth2Request.getRequestParameters()); + + parameters.clear(); + parameters.put(OAuth2Utils.CLIENT_ID, "foo"); + parameters.put(OAuth2Utils.SCOPE, "scope"); + StoredOAuth2Request storedOAuth2Request = new StoredOAuth2Request(parameters, "foo", null, true, Collections.singleton("scope"), null, null, null); + + String code = authorizationCodeServices.createAuthorizationCode(new OAuth2Authentication( + storedOAuth2Request, userAuthentication)); + parameters.putAll(storedOAuth2Request.getRequestParameters()); parameters.put("code", code); - oAuth2Request.setRequestParameters(parameters); + + TokenRequest tokenRequest = requestFactory.createTokenRequest(parameters); + AuthorizationCodeTokenGranter granter = new AuthorizationCodeTokenGranter(providerTokenServices, - authorizationCodeServices, clientDetailsService); - OAuth2AccessToken token = granter.grant("authorization_code", oAuth2Request); + authorizationCodeServices, clientDetailsService, requestFactory); + OAuth2AccessToken token = granter.grant("authorization_code", tokenRequest); assertTrue(providerTokenServices.loadAuthentication(token.getValue()).isAuthenticated()); } @Test public void testAuthorizationParametersPreserved() { - OAuth2Request oAuth2Request = createFromParameters( - commaDelimitedStringToMap("foo=bar,client_id=foo")); - oAuth2Request.setApproved(true); + + parameters.clear(); + parameters.put("foo", "bar"); + parameters.put(OAuth2Utils.CLIENT_ID, "foo"); + parameters.put(OAuth2Utils.SCOPE, "scope"); + StoredOAuth2Request storedOAuth2Request = new StoredOAuth2Request(parameters, "foo", null, true, Collections.singleton("scope"), null, null, null); + Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); - String code = authorizationCodeServices.createAuthorizationCode(new AuthorizationRequestHolder( - oAuth2Request, userAuthentication)); - parameters.putAll(oAuth2Request.getRequestParameters()); + String code = authorizationCodeServices.createAuthorizationCode(new OAuth2Authentication( + storedOAuth2Request, userAuthentication)); + parameters.put("code", code); - oAuth2Request.setRequestParameters(parameters); + TokenRequest tokenRequest = requestFactory.createTokenRequest(parameters); + AuthorizationCodeTokenGranter granter = new AuthorizationCodeTokenGranter(providerTokenServices, - authorizationCodeServices, clientDetailsService); - OAuth2AccessToken token = granter.grant("authorization_code", oAuth2Request); - OAuth2Request finalRequest = providerTokenServices.loadAuthentication(token.getValue()) - .getAuthorizationRequest(); + authorizationCodeServices, clientDetailsService, requestFactory); + OAuth2AccessToken token = granter.grant("authorization_code", tokenRequest); + StoredOAuth2Request finalRequest = providerTokenServices.loadAuthentication(token.getValue()) + .getStoredRequest(); assertEquals(code, finalRequest.getRequestParameters().get("code")); assertEquals("bar", finalRequest.getRequestParameters().get("foo")); } @Test public void testAuthorizationRequestPreserved() { - OAuth2Request oAuth2Request = createFromParameters( - commaDelimitedStringToMap("client_id=foo,scope=read")); - oAuth2Request.setResourceIds(Collections.singleton("resource")); - oAuth2Request.setApproved(true); + + parameters.clear(); + parameters.put(OAuth2Utils.CLIENT_ID, "foo"); + parameters.put(OAuth2Utils.SCOPE, "read"); + StoredOAuth2Request storedOAuth2Request = new StoredOAuth2Request(parameters, "foo", null, true, Collections.singleton("read"), Collections.singleton("resource"), null, null); + Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); - String code = authorizationCodeServices.createAuthorizationCode(new AuthorizationRequestHolder( - oAuth2Request, userAuthentication)); - parameters.put("client_id", "foo"); + String code = authorizationCodeServices.createAuthorizationCode(new OAuth2Authentication( + storedOAuth2Request, userAuthentication)); + parameters.put("code", code); - oAuth2Request.setRequestParameters(parameters); + TokenRequest tokenRequest = requestFactory.createTokenRequest(parameters); + AuthorizationCodeTokenGranter granter = new AuthorizationCodeTokenGranter(providerTokenServices, - authorizationCodeServices, clientDetailsService); - OAuth2AccessToken token = granter.grant("authorization_code", oAuth2Request); - OAuth2Request finalRequest = providerTokenServices.loadAuthentication(token.getValue()) - .getAuthorizationRequest(); + authorizationCodeServices, clientDetailsService, requestFactory); + OAuth2AccessToken token = granter.grant("authorization_code", tokenRequest); + StoredOAuth2Request finalRequest = providerTokenServices.loadAuthentication(token.getValue()) + .getStoredRequest(); assertEquals("[read]", finalRequest.getScope().toString()); assertEquals("[resource]", finalRequest.getResourceIds().toString()); assertTrue(finalRequest.isApproved()); } - private static Map commaDelimitedStringToMap(String string) { - Map result = new HashMap(); - for (String entry : StringUtils.commaDelimitedListToSet(string)) { - String[] values = StringUtils.delimitedListToStringArray(entry, "="); - result.put(values[0], values.length < 2 ? null : values[1]); - } - return result; - } - @Test public void testAuthorizationCodeGrantWithNoClientAuthorities() { - client.setAuthorities(Collections. emptySet()); - OAuth2Request oAuth2Request = new OAuth2Request("foo", - Arrays.asList("scope")); - oAuth2Request.setApproved(true); + + parameters.clear(); + parameters.put(OAuth2Utils.CLIENT_ID, "foo"); + parameters.put(OAuth2Utils.SCOPE, "scope"); + StoredOAuth2Request storedOAuth2Request = new StoredOAuth2Request(parameters, "foo", Collections. emptySet(), true, Collections.singleton("scope"), null, null, null); + Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); - String code = authorizationCodeServices.createAuthorizationCode(new AuthorizationRequestHolder( - oAuth2Request, userAuthentication)); - parameters.putAll(oAuth2Request.getRequestParameters()); + String code = authorizationCodeServices.createAuthorizationCode(new OAuth2Authentication( + storedOAuth2Request, userAuthentication)); parameters.put("code", code); - oAuth2Request.setRequestParameters(parameters); + TokenRequest tokenRequest = requestFactory.createTokenRequest(parameters); AuthorizationCodeTokenGranter granter = new AuthorizationCodeTokenGranter(providerTokenServices, - authorizationCodeServices, clientDetailsService); - OAuth2AccessToken token = granter.grant("authorization_code", oAuth2Request); + authorizationCodeServices, clientDetailsService, requestFactory); + OAuth2AccessToken token = granter.grant("authorization_code", tokenRequest); assertTrue(providerTokenServices.loadAuthentication(token.getValue()).isAuthenticated()); } @Test public void testAuthorizationRedirectMismatch() { Map initialParameters = new HashMap(); - initialParameters.put(REDIRECT_URI, "https://redirectme/"); - OAuth2Request initialRequest = createFromParameters(initialParameters); + initialParameters.put(OAuth2Utils.REDIRECT_URI, "https://redirectme/"); + //AuthorizationRequest initialRequest = createFromParameters(initialParameters); // we fake a valid resolvedRedirectUri because without the client would never come this far - initialRequest.setRedirectUri(initialParameters.get(REDIRECT_URI)); + //initialRequest.setRedirectUri(initialParameters.get(REDIRECT_URI)); + parameters.clear(); + parameters.put(OAuth2Utils.REDIRECT_URI, "https://redirectme/"); + parameters.put(OAuth2Utils.CLIENT_ID, "foo"); + StoredOAuth2Request storedOAuth2Request = new StoredOAuth2Request(parameters, "foo", null, true, null, null, "https://redirectme/", null); + Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); - String code = authorizationCodeServices.createAuthorizationCode(new AuthorizationRequestHolder(initialRequest, + String code = authorizationCodeServices.createAuthorizationCode(new OAuth2Authentication(storedOAuth2Request, userAuthentication)); Map authorizationParameters = new HashMap(); authorizationParameters.put("code", code); - OAuth2Request oAuth2Request = createFromParameters(initialParameters); - oAuth2Request.setRequestParameters(authorizationParameters); + + //AuthorizationRequest oAuth2Request = createFromParameters(initialParameters); + //oAuth2Request.setRequestParameters(authorizationParameters); + TokenRequest tokenRequest = requestFactory.createTokenRequest(parameters); + tokenRequest.setRequestParameters(authorizationParameters); + AuthorizationCodeTokenGranter granter = new AuthorizationCodeTokenGranter(providerTokenServices, - authorizationCodeServices, clientDetailsService); + authorizationCodeServices, clientDetailsService, requestFactory); try { - granter.getOAuth2Authentication(oAuth2Request); + granter.getOAuth2Authentication(tokenRequest); fail("RedirectMismatchException because of null redirect_uri in authorizationRequest"); } catch (RedirectMismatchException e) { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationRequestHolder.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationRequestHolder.java index 84ab395d0..b3560ddb9 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationRequestHolder.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationRequestHolder.java @@ -20,21 +20,22 @@ import org.junit.Test; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.oauth2.common.util.SerializationUtils; -import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.AuthorizationRequest; /** * @author Dave Syer * */ +//TOOD: Test serialization of OAuth2Authentication public class TestAuthorizationRequestHolder { - private AuthorizationRequestHolder holder = new AuthorizationRequestHolder(new OAuth2Request( - "client", Arrays.asList("read")), new UsernamePasswordAuthenticationToken("user", "pwd")); + //private OAuth2Authentication holder = new AuthorizationRequestHolder(new AuthorizationRequest( + // "client", Arrays.asList("read")), new UsernamePasswordAuthenticationToken("user", "pwd")); - @Test + //@Test public void test() { - AuthorizationRequestHolder other = SerializationUtils.deserialize(SerializationUtils.serialize(holder)); - assertEquals(holder, other); + //AuthorizationRequestHolder other = SerializationUtils.deserialize(SerializationUtils.serialize(holder)); + //assertEquals(holder, other); } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestAuthorizationEndpoint.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestAuthorizationEndpoint.java index bd08e9767..6c11b0a26 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestAuthorizationEndpoint.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestAuthorizationEndpoint.java @@ -16,7 +16,6 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; -import static org.springframework.security.oauth2.provider.OAuth2Request.REDIRECT_URI; import java.util.Arrays; import java.util.Collections; @@ -41,11 +40,12 @@ import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; -import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.TokenGranter; +import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.approval.UserApprovalHandler; import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; -import org.springframework.security.oauth2.provider.code.AuthorizationRequestHolder; import org.springframework.web.bind.support.SimpleSessionStatus; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.View; @@ -68,28 +68,28 @@ public class TestAuthorizationEndpoint { private BaseClientDetails client; - private OAuth2Request getOAuth2Request(String clientId, String redirectUri, String state, + private AuthorizationRequest getAuthorizationRequest(String clientId, String redirectUri, String state, String scope, Set responseTypes) { HashMap parameters = new HashMap(); - parameters.put(OAuth2Request.CLIENT_ID, clientId); + parameters.put(OAuth2Utils.CLIENT_ID, clientId); if (redirectUri != null) { - parameters.put(OAuth2Request.REDIRECT_URI, redirectUri); + parameters.put(OAuth2Utils.REDIRECT_URI, redirectUri); } if (state != null) { - parameters.put(OAuth2Request.STATE, state); + parameters.put(OAuth2Utils.STATE, state); } if (scope != null) { - parameters.put(OAuth2Request.SCOPE, scope); + parameters.put(OAuth2Utils.SCOPE, scope); } if (responseTypes != null) { - parameters.put(OAuth2Request.RESPONSE_TYPE, OAuth2Utils.formatParameterList(responseTypes)); + parameters.put(OAuth2Utils.RESPONSE_TYPE, OAuth2Utils.formatParameterList(responseTypes)); } - return new OAuth2Request(parameters, Collections. emptyMap(), - parameters.get(OAuth2Request.CLIENT_ID), - OAuth2Utils.parseParameterList(parameters.get(OAuth2Request.SCOPE)), null, - null, false, parameters.get(OAuth2Request.STATE), - parameters.get(OAuth2Request.REDIRECT_URI), - OAuth2Utils.parseParameterList(parameters.get(OAuth2Request.RESPONSE_TYPE))); + return new AuthorizationRequest(parameters, Collections. emptyMap(), + parameters.get(OAuth2Utils.CLIENT_ID), + OAuth2Utils.parseParameterList(parameters.get(OAuth2Utils.SCOPE)), null, + null, false, parameters.get(OAuth2Utils.STATE), + parameters.get(OAuth2Utils.REDIRECT_URI), + OAuth2Utils.parseParameterList(parameters.get(OAuth2Utils.RESPONSE_TYPE))); } @Before @@ -103,7 +103,7 @@ public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exceptio } }); endpoint.setTokenGranter(new TokenGranter() { - public OAuth2AccessToken grant(String grantType, OAuth2Request oAuth2Request) { + public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) { return null; } }); @@ -120,7 +120,7 @@ public void testMandatoryProperties() throws Exception { @Test public void testStartAuthorizationCodeFlow() throws Exception { - ModelAndView result = endpoint.authorize(model, getOAuth2Request("foo", null, null, null, Collections.singleton("code")) + ModelAndView result = endpoint.authorize(model, getAuthorizationRequest("foo", null, null, null, Collections.singleton("code")) .getRequestParameters(), sessionStatus, principal); assertEquals("forward:/oauth/confirm_access", result.getViewName()); } @@ -128,7 +128,7 @@ public void testStartAuthorizationCodeFlow() throws Exception { @Test(expected = OAuth2Exception.class) public void testStartAuthorizationCodeFlowForClientCredentialsFails() throws Exception { client.setAuthorizedGrantTypes(Collections.singleton("client_credentials")); - ModelAndView result = endpoint.authorize(model, getOAuth2Request("foo", null, null, null, Collections.singleton("code")) + ModelAndView result = endpoint.authorize(model, getAuthorizationRequest("foo", null, null, null, Collections.singleton("code")) .getRequestParameters(), sessionStatus, principal); assertEquals("forward:/oauth/confirm_access", result.getViewName()); } @@ -136,9 +136,9 @@ public void testStartAuthorizationCodeFlowForClientCredentialsFails() throws Exc @Test public void testAuthorizationCodeWithFragment() throws Exception { endpoint.setAuthorizationCodeServices(new StubAuthorizationCodeServices()); - model.put("authorizationRequest", getOAuth2Request("foo", "http://anywhere.com/#bar", null, null, Collections.singleton("code"))); + model.put("authorizationRequest", getAuthorizationRequest("foo", "http://anywhere.com/#bar", null, null, Collections.singleton("code"))); View result = endpoint.approveOrDeny( - Collections.singletonMap(OAuth2Request.USER_OAUTH_APPROVAL, "true"), model, sessionStatus, + Collections.singletonMap(OAuth2Utils.USER_OAUTH_APPROVAL, "true"), model, sessionStatus, principal); assertEquals("http://anywhere.com/?code=thecode#bar", ((RedirectView) result).getUrl()); } @@ -146,27 +146,27 @@ public void testAuthorizationCodeWithFragment() throws Exception { @Test public void testAuthorizationCodeError() throws Exception { endpoint.setUserApprovalHandler(new UserApprovalHandler() { - public OAuth2Request checkForPreApproval(OAuth2Request oAuth2Request, Authentication userAuthentication) { - return oAuth2Request; + public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { + return authorizationRequest; } - public OAuth2Request updateAfterApproval(OAuth2Request oAuth2Request, + public AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { - return oAuth2Request; + return authorizationRequest; } - public boolean isApproved(OAuth2Request oAuth2Request, Authentication userAuthentication) { + public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { return true; } }); endpoint.setAuthorizationCodeServices(new StubAuthorizationCodeServices() { @Override - public String createAuthorizationCode(AuthorizationRequestHolder authentication) { + public String createAuthorizationCode(OAuth2Authentication authentication) { throw new InvalidScopeException("FOO"); } }); ModelAndView result = endpoint.authorize(model, - getOAuth2Request("foo", "http://anywhere.com/", "mystate", "myscope", Collections.singleton("code")) + getAuthorizationRequest("foo", "http://anywhere.com/", "mystate", "myscope", Collections.singleton("code")) .getRequestParameters(), sessionStatus, principal); String url = ((RedirectView) result.getView()).getUrl(); assertTrue("Wrong view: " + result, url.startsWith("http://anywhere.com/")); @@ -180,7 +180,7 @@ public void testAuthorizationCodeWithMultipleResponseTypes() throws Exception { Set responseTypes = new HashSet(); responseTypes.add("code"); responseTypes.add("other"); - ModelAndView result = endpoint.authorize(model, getOAuth2Request("foo", null, null, null, responseTypes) + ModelAndView result = endpoint.authorize(model, getAuthorizationRequest("foo", null, null, null, responseTypes) .getRequestParameters(), sessionStatus, principal); assertEquals("forward:/oauth/confirm_access", result.getViewName()); } @@ -189,7 +189,7 @@ public void testAuthorizationCodeWithMultipleResponseTypes() throws Exception { public void testImplicitPreApproved() throws Exception { endpoint.setTokenGranter(new TokenGranter() { - public OAuth2AccessToken grant(String grantType, OAuth2Request authorizationRequest) { + public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) { DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken("FOO"); token.setAdditionalInformation(Collections.singletonMap("foo", (Object)"bar")); return token; @@ -197,22 +197,22 @@ public OAuth2AccessToken grant(String grantType, OAuth2Request authorizationRequ } }); endpoint.setUserApprovalHandler(new UserApprovalHandler() { - public OAuth2Request checkForPreApproval(OAuth2Request oAuth2Request, Authentication userAuthentication) { - return oAuth2Request; + public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { + return authorizationRequest; } - public OAuth2Request updateAfterApproval(OAuth2Request oAuth2Request, + public AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { - return oAuth2Request; + return authorizationRequest; } - public boolean isApproved(OAuth2Request oAuth2Request, Authentication userAuthentication) { + public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { return true; } }); - OAuth2Request oAuth2Request = getOAuth2Request("foo", "http://anywhere.com/", "mystate", + AuthorizationRequest authorizationRequest = getAuthorizationRequest("foo", "http://anywhere.com/", "mystate", "myscope", Collections.singleton("token")); - ModelAndView result = endpoint.authorize(model, oAuth2Request.getRequestParameters(), + ModelAndView result = endpoint.authorize(model, authorizationRequest.getRequestParameters(), sessionStatus, principal); String url = ((RedirectView) result.getView()).getUrl(); assertTrue("Wrong view: " + result, url.startsWith("http://anywhere.com/")); @@ -224,27 +224,27 @@ public boolean isApproved(OAuth2Request oAuth2Request, Authentication userAuthen @Test public void testImplicitAppendsScope() throws Exception { endpoint.setTokenGranter(new TokenGranter() { - public OAuth2AccessToken grant(String grantType, OAuth2Request authorizationRequest) { + public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) { DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken("FOO"); token.setScope(Collections.singleton("read")); return token; } }); endpoint.setUserApprovalHandler(new UserApprovalHandler() { - public OAuth2Request checkForPreApproval(OAuth2Request oAuth2Request, Authentication userAuthentication) { - return oAuth2Request; + public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { + return authorizationRequest; } - public OAuth2Request updateAfterApproval(OAuth2Request oAuth2Request, + public AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { - return oAuth2Request; + return authorizationRequest; } - public boolean isApproved(OAuth2Request oAuth2Request, Authentication userAuthentication) { + public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { return true; } }); - OAuth2Request authorizationRequest = getOAuth2Request("foo", "http://anywhere.com/", "mystate", + AuthorizationRequest authorizationRequest = getAuthorizationRequest("foo", "http://anywhere.com/", "mystate", "myscope", Collections.singleton("token")); ModelAndView result = endpoint.authorize(model, authorizationRequest.getRequestParameters(), sessionStatus, principal); @@ -255,30 +255,30 @@ public boolean isApproved(OAuth2Request oAuth2Request, Authentication userAuthen @Test public void testImplicitAppendsScopeWhenDefaulting() throws Exception { endpoint.setTokenGranter(new TokenGranter() { - public OAuth2AccessToken grant(String grantType, OAuth2Request authorizationRequest) { + public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) { DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken("FOO"); token.setScope(new LinkedHashSet(Arrays.asList("read", "write"))); return token; } }); endpoint.setUserApprovalHandler(new UserApprovalHandler() { - public boolean isApproved(OAuth2Request authorizationRequest, Authentication userAuthentication) { + public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { return true; } - public OAuth2Request checkForPreApproval( - OAuth2Request oAuth2Request, + public AuthorizationRequest checkForPreApproval( + AuthorizationRequest authorizationRequest, Authentication userAuthentication) { - return oAuth2Request; + return authorizationRequest; } - public OAuth2Request updateAfterApproval( - OAuth2Request oAuth2Request, + public AuthorizationRequest updateAfterApproval( + AuthorizationRequest authorizationRequest, Authentication userAuthentication) { - return oAuth2Request; + return authorizationRequest; } }); - OAuth2Request authorizationRequest = getOAuth2Request("foo", "http://anywhere.com/", "mystate", + AuthorizationRequest authorizationRequest = getAuthorizationRequest("foo", "http://anywhere.com/", "mystate", null, Collections.singleton("token")); ModelAndView result = endpoint.authorize(model,authorizationRequest.getRequestParameters(), sessionStatus, principal); @@ -289,30 +289,30 @@ public OAuth2Request updateAfterApproval( @Test(expected = InvalidScopeException.class) public void testImplicitPreApprovedButInvalid() throws Exception { endpoint.setTokenGranter(new TokenGranter() { - public OAuth2AccessToken grant(String grantType, OAuth2Request authorizationRequest) { + public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) { throw new IllegalStateException("Shouldn't be called"); } }); endpoint.setUserApprovalHandler(new UserApprovalHandler() { - public boolean isApproved(OAuth2Request authorizationRequest, Authentication userAuthentication) { + public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { return true; } - public OAuth2Request checkForPreApproval( - OAuth2Request oAuth2Request, + public AuthorizationRequest checkForPreApproval( + AuthorizationRequest authorizationRequest, Authentication userAuthentication) { - return oAuth2Request; + return authorizationRequest; } - public OAuth2Request updateAfterApproval( - OAuth2Request oAuth2Request, + public AuthorizationRequest updateAfterApproval( + AuthorizationRequest authorizationRequest, Authentication userAuthentication) { - return oAuth2Request; + return authorizationRequest; } }); client.setScope(Collections.singleton("smallscope")); - OAuth2Request oAuth2Request = getOAuth2Request("foo", "http://anywhere.com/", "mystate", + AuthorizationRequest authorizationRequest = getAuthorizationRequest("foo", "http://anywhere.com/", "mystate", "bigscope", Collections.singleton("token")); - ModelAndView result = endpoint.authorize(model, oAuth2Request.getRequestParameters(), + ModelAndView result = endpoint.authorize(model, authorizationRequest.getRequestParameters(), sessionStatus, principal); String url = ((RedirectView) result.getView()).getUrl(); assertTrue("Wrong view: " + result, url.startsWith("http://anywhere.com/")); @@ -321,13 +321,13 @@ public OAuth2Request updateAfterApproval( @Test public void testImplicitUnapproved() throws Exception { endpoint.setTokenGranter(new TokenGranter() { - public OAuth2AccessToken grant(String grantType, OAuth2Request oAuth2Request) { + public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) { return null; } }); - OAuth2Request oAuth2Request = getOAuth2Request("foo", "http://anywhere.com/", "mystate", + AuthorizationRequest authorizationRequest = getAuthorizationRequest("foo", "http://anywhere.com/", "mystate", "myscope", Collections.singleton("token")); - ModelAndView result = endpoint.authorize(model, oAuth2Request.getRequestParameters(), + ModelAndView result = endpoint.authorize(model, authorizationRequest.getRequestParameters(), sessionStatus, principal); assertEquals("forward:/oauth/confirm_access", result.getViewName()); } @@ -335,27 +335,27 @@ public OAuth2AccessToken grant(String grantType, OAuth2Request oAuth2Request) { @Test public void testImplicitError() throws Exception { endpoint.setUserApprovalHandler(new UserApprovalHandler() { - public OAuth2Request checkForPreApproval(OAuth2Request oAuth2Request, Authentication userAuthentication) { - return oAuth2Request; + public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { + return authorizationRequest; } - public OAuth2Request updateAfterApproval(OAuth2Request oAuth2Request, + public AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { - return oAuth2Request; + return authorizationRequest; } - public boolean isApproved(OAuth2Request oAuth2Request, Authentication userAuthentication) { + public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { return true; } }); endpoint.setTokenGranter(new TokenGranter() { - public OAuth2AccessToken grant(String grantType, OAuth2Request oAuth2Request) { + public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) { return null; } }); - OAuth2Request oAuth2Request = getOAuth2Request("foo", "http://anywhere.com/", "mystate", + AuthorizationRequest authorizationRequest = getAuthorizationRequest("foo", "http://anywhere.com/", "mystate", "myscope", Collections.singleton("token")); - ModelAndView result = endpoint.authorize(model, oAuth2Request.getRequestParameters(), + ModelAndView result = endpoint.authorize(model, authorizationRequest.getRequestParameters(), sessionStatus, principal); String url = ((RedirectView) result.getView()).getUrl(); @@ -367,7 +367,7 @@ public OAuth2AccessToken grant(String grantType, OAuth2Request oAuth2Request) { @Test public void testApproveOrDeny() throws Exception { - OAuth2Request request = getOAuth2Request("foo", "http://anywhere.com/", null, null, Collections.singleton("code")); + AuthorizationRequest request = getAuthorizationRequest("foo", "http://anywhere.com/", null, null, Collections.singleton("code")); request.setApproved(true); Map approvalParameters = new HashMap(); approvalParameters.put("user_oauth_approval", "true"); @@ -378,7 +378,7 @@ public void testApproveOrDeny() throws Exception { @Test public void testApprovalDenied() throws Exception { - model.put("authorizationRequest", getOAuth2Request("foo", "http://anywhere.com/", null, null, Collections.singleton("code"))); + model.put("authorizationRequest", getAuthorizationRequest("foo", "http://anywhere.com/", null, null, Collections.singleton("code"))); Map approvalParameters = new HashMap(); approvalParameters.put("user_oauth_approval", "false"); View result = endpoint.approveOrDeny(approvalParameters, model, sessionStatus, principal); @@ -390,7 +390,7 @@ public void testApprovalDenied() throws Exception { @Test public void testDirectApproval() throws Exception { ModelAndView result = endpoint.authorize(model, - getOAuth2Request("foo", "http://anywhere.com/", null, null, Collections.singleton("code")).getRequestParameters(), + getAuthorizationRequest("foo", "http://anywhere.com/", null, null, Collections.singleton("code")).getRequestParameters(), sessionStatus, principal); // Should go to approval page (SECOAUTH-191) assertFalse(result.getView() instanceof RedirectView); @@ -398,13 +398,13 @@ public void testDirectApproval() throws Exception { @Test public void testRedirectUriOptionalForAuthorization() throws Exception { - ModelAndView result = endpoint.authorize(model, getOAuth2Request("foo", null, null, null, Collections.singleton("code")) + ModelAndView result = endpoint.authorize(model, getAuthorizationRequest("foo", null, null, null, Collections.singleton("code")) .getRequestParameters(), sessionStatus, principal); // RedirectUri parameter should be null (SECOAUTH-333), however the resolvedRedirectUri not - OAuth2Request oAuth2Request = (OAuth2Request) result.getModelMap().get( + AuthorizationRequest authorizationRequest = (AuthorizationRequest) result.getModelMap().get( "authorizationRequest"); - assertNull(oAuth2Request.getRequestParameters().get(REDIRECT_URI)); - assertEquals("http://anywhere.com/", oAuth2Request.getRedirectUri()); + assertNull(authorizationRequest.getRequestParameters().get(OAuth2Utils.REDIRECT_URI)); + assertEquals("http://anywhere.com/", authorizationRequest.getRedirectUri()); } /** @@ -413,7 +413,7 @@ public void testRedirectUriOptionalForAuthorization() throws Exception { */ @Test(expected = InvalidRequestException.class) public void testApproveOrDenyWithOAuth2RequestWithoutRedirectUri() throws Exception { - OAuth2Request request = getOAuth2Request("foo", null, null, null, Collections.singleton("code")); + AuthorizationRequest request = getAuthorizationRequest("foo", null, null, null, Collections.singleton("code")); request.setApproved(true); Map approvalParameters = new HashMap(); approvalParameters.put("user_oauth_approval", "true"); @@ -423,14 +423,14 @@ public void testApproveOrDenyWithOAuth2RequestWithoutRedirectUri() throws Except } private class StubAuthorizationCodeServices implements AuthorizationCodeServices { - private AuthorizationRequestHolder authentication; + private OAuth2Authentication authentication; - public String createAuthorizationCode(AuthorizationRequestHolder authentication) { + public String createAuthorizationCode(OAuth2Authentication authentication) { this.authentication = authentication; return "thecode"; } - public AuthorizationRequestHolder consumeAuthorizationCode(String code) throws InvalidGrantException { + public OAuth2Authentication consumeAuthorizationCode(String code) throws InvalidGrantException { return authentication; } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestTokenEndpoint.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestTokenEndpoint.java index a5c5ec121..7acaea2cb 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestTokenEndpoint.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestTokenEndpoint.java @@ -40,9 +40,9 @@ import org.springframework.security.oauth2.common.util.OAuth2Utils; import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; -import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; import org.springframework.security.oauth2.provider.TokenGranter; +import org.springframework.security.oauth2.provider.TokenRequest; /** * @author Dave Syer @@ -59,14 +59,10 @@ public class TestTokenEndpoint { @Mock private ClientDetailsService clientDetailsService; - - private OAuth2Request createFromParameters(Map authorizationParameters) { - OAuth2Request request = new OAuth2Request(authorizationParameters, Collections. emptyMap(), - authorizationParameters.get(OAuth2Request.CLIENT_ID), - OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Request.SCOPE)), null, - null, false, authorizationParameters.get(OAuth2Request.STATE), - authorizationParameters.get(OAuth2Request.REDIRECT_URI), - OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Request.RESPONSE_TYPE))); + + private TokenRequest createFromParameters(Map parameters) { + TokenRequest request = new TokenRequest(parameters, parameters.get(OAuth2Utils.CLIENT_ID), + OAuth2Utils.parseParameterList(parameters.get(OAuth2Utils.SCOPE)), parameters.get(OAuth2Utils.GRANT_TYPE)); return request; } @@ -79,18 +75,17 @@ public void testGetAccessTokenWithNoClientId() { endpoint.setClientDetailsService(clientDetailsService); HashMap parameters = new HashMap(); + parameters.put(OAuth2Utils.GRANT_TYPE, "authorization_code"); OAuth2AccessToken expectedToken = new DefaultOAuth2AccessToken("FOO"); - when(tokenGranter.grant(Mockito.eq("authorization_code"), Mockito.any(OAuth2Request.class))).thenReturn( + when(tokenGranter.grant(Mockito.eq("authorization_code"), Mockito.any(TokenRequest.class))).thenReturn( expectedToken); @SuppressWarnings("unchecked") Map anyMap = Mockito.any(Map.class); - when(authorizationRequestFactory.createOAuth2Request(anyMap)).thenReturn( - createFromParameters(parameters)); - + when(authorizationRequestFactory.createTokenRequest(anyMap)).thenReturn(createFromParameters(parameters)); + ResponseEntity response = endpoint.getAccessToken(new UsernamePasswordAuthenticationToken( - null, null, Collections.singleton(new SimpleGrantedAuthority("ROLE_CLIENT"))), "authorization_code", - parameters); + null, null, Collections.singleton(new SimpleGrantedAuthority("ROLE_CLIENT"))), parameters); assertNotNull(response); assertEquals(HttpStatus.OK, response.getStatusCode()); @@ -120,23 +115,22 @@ public void testGetAccessTokenWithScope() { parameters.put("code", "kJAHDFG"); OAuth2AccessToken expectedToken = new DefaultOAuth2AccessToken("FOO"); - ArgumentCaptor captor = ArgumentCaptor.forClass(OAuth2Request.class); - when(tokenGranter.grant(Mockito.eq("authorization_code"), captor.capture())).thenReturn(expectedToken); + ArgumentCaptor captor2 = ArgumentCaptor.forClass(TokenRequest.class); + + when(tokenGranter.grant(Mockito.eq("authorization_code"), captor2.capture())).thenReturn(expectedToken); @SuppressWarnings("unchecked") Map anyMap = Mockito.any(Map.class); - when(authorizationRequestFactory.createOAuth2Request(anyMap)).thenReturn( - createFromParameters(parameters)); + when(authorizationRequestFactory.createTokenRequest(anyMap)).thenReturn(createFromParameters(parameters)); ResponseEntity response = endpoint.getAccessToken(new UsernamePasswordAuthenticationToken( - null, null, Collections.singleton(new SimpleGrantedAuthority("ROLE_CLIENT"))), "authorization_code", - parameters); + null, null, Collections.singleton(new SimpleGrantedAuthority("ROLE_CLIENT"))), parameters); assertNotNull(response); assertEquals(HttpStatus.OK, response.getStatusCode()); OAuth2AccessToken body = response.getBody(); assertEquals(body, expectedToken); assertTrue("Wrong body: " + body, body.getTokenType() != null); - assertTrue("Scope of token request not cleared", captor.getValue().getScope().isEmpty()); + assertTrue("Scope of token request not cleared", captor2.getValue().getScope().isEmpty()); } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestWhitelabelApprovalEndpoint.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestWhitelabelApprovalEndpoint.java index dbc91e4dd..2e2131213 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestWhitelabelApprovalEndpoint.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestWhitelabelApprovalEndpoint.java @@ -25,7 +25,7 @@ import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.security.oauth2.common.exceptions.InvalidClientException; import org.springframework.security.oauth2.common.util.OAuth2Utils; -import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.web.servlet.ModelAndView; /** @@ -39,13 +39,13 @@ public class TestWhitelabelApprovalEndpoint { private MockHttpServletRequest request = new MockHttpServletRequest(); private MockHttpServletResponse response = new MockHttpServletResponse(); - private OAuth2Request createFromParameters(Map authorizationParameters) { - OAuth2Request request = new OAuth2Request(authorizationParameters, Collections. emptyMap(), - authorizationParameters.get(OAuth2Request.CLIENT_ID), - OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Request.SCOPE)), null, - null, false, authorizationParameters.get(OAuth2Request.STATE), - authorizationParameters.get(OAuth2Request.REDIRECT_URI), - OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Request.RESPONSE_TYPE))); + private AuthorizationRequest createFromParameters(Map authorizationParameters) { + AuthorizationRequest request = new AuthorizationRequest(authorizationParameters, Collections. emptyMap(), + authorizationParameters.get(OAuth2Utils.CLIENT_ID), + OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Utils.SCOPE)), null, + null, false, authorizationParameters.get(OAuth2Utils.STATE), + authorizationParameters.get(OAuth2Utils.REDIRECT_URI), + OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Utils.RESPONSE_TYPE))); return request; } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2MethodSecurityExpressionHandler.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2MethodSecurityExpressionHandler.java index 9d235dd5f..2cae80e65 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2MethodSecurityExpressionHandler.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2MethodSecurityExpressionHandler.java @@ -27,9 +27,10 @@ import org.springframework.expression.Expression; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.StoredOAuth2Request; import org.springframework.security.util.SimpleMethodInvocation; import org.springframework.util.ReflectionUtils; @@ -43,11 +44,15 @@ public class TestOAuth2MethodSecurityExpressionHandler { @Test public void testOauthClient() throws Exception { - OAuth2Request clientAuthentication = new OAuth2Request("foo", + AuthorizationRequest request = new AuthorizationRequest("foo", Collections.singleton("read")); - clientAuthentication + request .setResourceIdsAndAuthoritiesFromClientDetails(new BaseClientDetails("foo", "", "", "client_credentials", "ROLE_CLIENT")); Authentication userAuthentication = null; + + StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(request.getRequestParameters(), request.getClientId(), request.getAuthorities(), + request.isApproved(), request.getScope(), request.getResourceIds(), request.getRedirectUri(), request.getExtensionProperties()); + OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); MethodInvocation invocation = new SimpleMethodInvocation(this, ReflectionUtils.findMethod(getClass(), "testOauthClient")); @@ -59,8 +64,9 @@ public void testOauthClient() throws Exception { @Test public void testScopes() throws Exception { - OAuth2Request clientAuthentication = new OAuth2Request("foo", - Collections.singleton("read")); + + StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); + Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); MethodInvocation invocation = new SimpleMethodInvocation(this, ReflectionUtils.findMethod(getClass(), @@ -99,10 +105,10 @@ public void testReEvaluationWithDifferentRoot() throws Exception { Authentication clientAuthentication = new UsernamePasswordAuthenticationToken("foo", "bar"); EvaluationContext context = handler.createEvaluationContext(clientAuthentication, invocation); assertFalse((Boolean) expression.getValue(context)); - OAuth2Request oAuth2Request = new OAuth2Request("foo", - Collections.singleton("read")); - oAuth2Request.setApproved(true); - OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request, null); + + StoredOAuth2Request storedOAuth2Request = new StoredOAuth2Request(null, "foo", null, true, Collections.singleton("read"), null, null, null); + + OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(storedOAuth2Request, null); EvaluationContext anotherContext = handler.createEvaluationContext(oAuth2Authentication, invocation); assertTrue((Boolean) expression.getValue(anotherContext)); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2SecurityExpressionMethods.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2SecurityExpressionMethods.java index 7bce296fb..b89481440 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2SecurityExpressionMethods.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2SecurityExpressionMethods.java @@ -26,9 +26,10 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.StoredOAuth2Request; /** * @author Dave Syer @@ -38,19 +39,23 @@ public class TestOAuth2SecurityExpressionMethods { @Test public void testOauthClient() throws Exception { - OAuth2Request clientAuthentication = new OAuth2Request("foo", + AuthorizationRequest request = new AuthorizationRequest("foo", Collections.singleton("read")); - clientAuthentication + request .setResourceIdsAndAuthoritiesFromClientDetails(new BaseClientDetails("foo", "", "", "client_credentials", "ROLE_CLIENT")); Authentication userAuthentication = null; + + StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(request.getRequestParameters(), request.getClientId(), request.getAuthorities(), + request.isApproved(), request.getScope(), request.getResourceIds(), request.getRedirectUri(), request.getExtensionProperties()); + OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); assertTrue(new OAuth2SecurityExpressionMethods(oAuth2Authentication, true).clientHasAnyRole("ROLE_CLIENT")); } @Test public void testScopes() throws Exception { - OAuth2Request clientAuthentication = new OAuth2Request("foo", - Collections.singleton("read")); + StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); + Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); OAuth2SecurityExpressionMethods root = new OAuth2SecurityExpressionMethods(oAuth2Authentication, false); @@ -59,8 +64,8 @@ public void testScopes() throws Exception { @Test public void testScopesFalse() throws Exception { - OAuth2Request clientAuthentication = new OAuth2Request("foo", - Collections.singleton("read")); + StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); + Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); OAuth2SecurityExpressionMethods root = new OAuth2SecurityExpressionMethods(oAuth2Authentication, false); @@ -69,8 +74,8 @@ public void testScopesFalse() throws Exception { @Test(expected = AccessDeniedException.class) public void testScopesWithException() throws Exception { - OAuth2Request clientAuthentication = new OAuth2Request("foo", - Collections.singleton("read")); + StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); + Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); assertTrue(new OAuth2SecurityExpressionMethods(oAuth2Authentication, true).hasAnyScope("foo")); @@ -78,8 +83,8 @@ public void testScopesWithException() throws Exception { @Test(expected = AccessDeniedException.class) public void testInsufficientScope() throws Exception { - OAuth2Request clientAuthentication = new OAuth2Request("foo", - Collections.singleton("read")); + StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); + Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); assertFalse(new OAuth2SecurityExpressionMethods(oAuth2Authentication, true).hasAnyScope("foo")); @@ -88,8 +93,8 @@ public void testInsufficientScope() throws Exception { @Test public void testSufficientScope() throws Exception { - OAuth2Request clientAuthentication = new OAuth2Request("foo", - Collections.singleton("read")); + StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); + Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); assertTrue(new OAuth2SecurityExpressionMethods(oAuth2Authentication, true).hasAnyScope("read")); @@ -98,9 +103,8 @@ public void testSufficientScope() throws Exception { @Test public void testSufficientScopeWithNoPreviousScopeDecision() throws Exception { - OAuth2Request clientAuthentication = new OAuth2Request("foo", - Collections.singleton("read")); - clientAuthentication.setApproved(true); + StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(null, "foo", null, true, Collections.singleton("read"), null, null, null); + Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); assertTrue(new OAuth2SecurityExpressionMethods(oAuth2Authentication, true).isClient()); @@ -115,20 +119,19 @@ public void testNonOauthClient() throws Exception { @Test public void testClientOnly() throws Exception { - OAuth2Request request = new OAuth2Request("foo", Collections.singleton("read")); - request.setApproved(true); + StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(null, "foo", null, true, Collections.singleton("read"), null, null, null); + Authentication userAuthentication = new UsernamePasswordAuthenticationToken("foo", "bar", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"))); - OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(request, userAuthentication); + OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); assertFalse(new OAuth2SecurityExpressionMethods(oAuth2Authentication, true).isClient()); - assertTrue(new OAuth2SecurityExpressionMethods(new OAuth2Authentication(request, null), true).isClient()); + assertTrue(new OAuth2SecurityExpressionMethods(new OAuth2Authentication(clientAuthentication, null), true).isClient()); } @Test public void testOAuthUser() throws Exception { - OAuth2Request clientAuthentication = new OAuth2Request("foo", - Collections.singleton("read")); - clientAuthentication.setApproved(true); + StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(null, "foo", null, true, Collections.singleton("read"), null, null, null); + Authentication userAuthentication = new UsernamePasswordAuthenticationToken("foo", "bar", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"))); OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2WebSecurityExpressionHandler.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2WebSecurityExpressionHandler.java index aeb40fa5a..248b1253b 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2WebSecurityExpressionHandler.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2WebSecurityExpressionHandler.java @@ -25,9 +25,10 @@ import org.springframework.expression.Expression; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.StoredOAuth2Request; import org.springframework.security.web.FilterInvocation; /** @@ -40,8 +41,12 @@ public class TestOAuth2WebSecurityExpressionHandler { @Test public void testOauthClient() throws Exception { - OAuth2Request clientAuthentication = new OAuth2Request("foo", Collections.singleton("read")); - clientAuthentication.setResourceIdsAndAuthoritiesFromClientDetails(new BaseClientDetails("foo", "", "", "client_credentials", "ROLE_CLIENT")); + AuthorizationRequest request = new AuthorizationRequest("foo", Collections.singleton("read")); + request.setResourceIdsAndAuthoritiesFromClientDetails(new BaseClientDetails("foo", "", "", "client_credentials", "ROLE_CLIENT")); + + StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(request.getRequestParameters(), request.getClientId(), request.getAuthorities(), + request.isApproved(), request.getScope(), request.getResourceIds(), request.getRedirectUri(), request.getExtensionProperties()); + Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); FilterInvocation invocation = new FilterInvocation("/foo", "GET"); @@ -51,7 +56,7 @@ public void testOauthClient() throws Exception { @Test public void testScopes() throws Exception { - OAuth2Request clientAuthentication = new OAuth2Request("foo", Collections.singleton("read")); + StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); FilterInvocation invocation = new FilterInvocation("/foo", "GET"); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/TestResourceOwnerPasswordTokenGranter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/TestResourceOwnerPasswordTokenGranter.java index a84e274be..acf51aefb 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/TestResourceOwnerPasswordTokenGranter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/TestResourceOwnerPasswordTokenGranter.java @@ -15,7 +15,6 @@ import static org.junit.Assert.assertTrue; import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -30,12 +29,13 @@ import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; -import org.springframework.security.oauth2.common.util.OAuth2Utils; -import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.DefaultOAuth2RequestFactory; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; +import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.token.DefaultTokenServices; import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; @@ -62,17 +62,9 @@ public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exceptio } }; - private OAuth2Request createFromParameters(Map authorizationParameters) { - OAuth2Request request = new OAuth2Request(authorizationParameters, Collections. emptyMap(), - authorizationParameters.get(OAuth2Request.CLIENT_ID), - OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Request.SCOPE)), null, - null, false, authorizationParameters.get(OAuth2Request.STATE), - authorizationParameters.get(OAuth2Request.REDIRECT_URI), - OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Request.RESPONSE_TYPE))); - return request; - } + private OAuth2RequestFactory requestFactory = new DefaultOAuth2RequestFactory(clientDetailsService); - private OAuth2Request oAuth2Request; + private TokenRequest tokenRequest; public TestResourceOwnerPasswordTokenGranter() { providerTokenServices.setTokenStore(new InMemoryTokenStore()); @@ -80,14 +72,14 @@ public TestResourceOwnerPasswordTokenGranter() { parameters.put("username", "foo"); parameters.put("password", "bar"); parameters.put("client_id", "client"); - oAuth2Request = createFromParameters(parameters); + tokenRequest = requestFactory.createTokenRequest(parameters); } @Test public void testSunnyDay() { ResourceOwnerPasswordTokenGranter granter = new ResourceOwnerPasswordTokenGranter(authenticationManager, - providerTokenServices, clientDetailsService); - OAuth2AccessToken token = granter.grant("password", oAuth2Request); + providerTokenServices, clientDetailsService, requestFactory); + OAuth2AccessToken token = granter.grant("password", tokenRequest); OAuth2Authentication authentication = providerTokenServices.loadAuthentication(token.getValue()); assertTrue(authentication.isAuthenticated()); } @@ -98,8 +90,8 @@ public void testBadCredentials() { public Authentication authenticate(Authentication authentication) throws AuthenticationException { throw new BadCredentialsException("test"); } - }, providerTokenServices, clientDetailsService); - granter.grant("password", oAuth2Request); + }, providerTokenServices, clientDetailsService, requestFactory); + granter.grant("password", tokenRequest); } @Test(expected = InvalidGrantException.class) @@ -108,16 +100,16 @@ public void testAccountLocked() { public Authentication authenticate(Authentication authentication) throws AuthenticationException { throw new LockedException("test"); } - }, providerTokenServices, clientDetailsService); - granter.grant("password", oAuth2Request); + }, providerTokenServices, clientDetailsService, requestFactory); + granter.grant("password", tokenRequest); } @Test(expected = InvalidGrantException.class) public void testUnauthenticated() { validUser = new UsernamePasswordAuthenticationToken("foo", "bar"); ResourceOwnerPasswordTokenGranter granter = new ResourceOwnerPasswordTokenGranter(authenticationManager, - providerTokenServices, clientDetailsService); - granter.grant("password", oAuth2Request); + providerTokenServices, clientDetailsService, requestFactory); + granter.grant("password", tokenRequest); } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractTestDefaultTokenServices.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractTestDefaultTokenServices.java index e5b9cd6ca..6620110e8 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractTestDefaultTokenServices.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractTestDefaultTokenServices.java @@ -18,11 +18,12 @@ import org.springframework.security.oauth2.common.OAuth2RefreshToken; import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; -import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.StoredOAuth2Request; +import org.springframework.security.oauth2.provider.TokenRequest; /** * @author Dave Syer @@ -67,7 +68,7 @@ public void testTokenRevoked() throws Exception { OAuth2Authentication authentication = createAuthentication(); OAuth2AccessToken original = getTokenServices().createAccessToken(authentication); tokenStore.removeAccessToken(original); - assertEquals(0, tokenStore.findTokensByClientId(authentication.getAuthorizationRequest().getClientId()).size()); + assertEquals(0, tokenStore.findTokensByClientId(authentication.getStoredRequest().getClientId()).size()); } @Test @@ -80,8 +81,9 @@ public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentica OAuth2AccessToken accessToken = getTokenServices().createAccessToken(createAuthentication()); assertTrue(accessToken.getValue().startsWith("I'mEnhanced")); + TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap("client_id", "id"), "id", null, null); OAuth2AccessToken refreshedAccessToken = getTokenServices().refreshAccessToken( - accessToken.getRefreshToken().getValue(), new OAuth2Request("id", null)); + accessToken.getRefreshToken().getValue(), tokenRequest); assertTrue(refreshedAccessToken.getValue().startsWith("I'mEnhanced")); } @@ -90,8 +92,9 @@ public void testRefreshedTokenHasScopes() throws Exception { ExpiringOAuth2RefreshToken expectedExpiringRefreshToken = new DefaultExpiringOAuth2RefreshToken("testToken", new Date(System.currentTimeMillis() + 100000)); tokenStore.storeRefreshToken(expectedExpiringRefreshToken, createAuthentication()); + TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap("client_id", "id"), "id", null, null); OAuth2AccessToken refreshedAccessToken = getTokenServices().refreshAccessToken( - expectedExpiringRefreshToken.getValue(), new OAuth2Request("id", null)); + expectedExpiringRefreshToken.getValue(), tokenRequest); assertEquals("[read]", refreshedAccessToken.getScope().toString()); } @@ -100,8 +103,9 @@ public void testRefreshedTokenInvalidWithWrongClient() throws Exception { ExpiringOAuth2RefreshToken expectedExpiringRefreshToken = new DefaultExpiringOAuth2RefreshToken("testToken", new Date(System.currentTimeMillis() + 100000)); tokenStore.storeRefreshToken(expectedExpiringRefreshToken, createAuthentication()); + TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap("client_id", "wrong"), "wrong", null, null); OAuth2AccessToken refreshedAccessToken = getTokenServices().refreshAccessToken( - expectedExpiringRefreshToken.getValue(), new OAuth2Request("wrong", null)); + expectedExpiringRefreshToken.getValue(), tokenRequest); assertEquals("[read]", refreshedAccessToken.getScope().toString()); } @@ -161,17 +165,17 @@ public void testOneAccessTokenPerAuthentication() throws Exception { OAuth2AccessToken second = getTokenServices().createAccessToken(authentication); assertEquals(first, second); assertEquals(1, getAccessTokenCount()); - assertEquals(1, getRefreshTokenCount()); + assertEquals(1, getRefreshTokenCount()); } @Test public void testOneAccessTokenPerUniqueAuthentication() throws Exception { getTokenServices().createAccessToken( - new OAuth2Authentication(new OAuth2Request("id", Collections.singleton("read")), + new OAuth2Authentication(new StoredOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null), new TestAuthentication("test2", false))); assertEquals(1, getAccessTokenCount()); getTokenServices().createAccessToken( - new OAuth2Authentication(new OAuth2Request("id", Collections.singleton("write")), + new OAuth2Authentication(new StoredOAuth2Request(null, "id", null, false, Collections.singleton("write"), null, null, null), new TestAuthentication("test2", false))); assertEquals(2, getAccessTokenCount()); } @@ -181,8 +185,9 @@ public void testRefreshTokenMaintainsState() throws Exception { getTokenServices().setSupportRefreshToken(true); OAuth2AccessToken accessToken = getTokenServices().createAccessToken(createAuthentication()); OAuth2RefreshToken expectedExpiringRefreshToken = accessToken.getRefreshToken(); + TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap("client_id", "id"), "id", null, null); OAuth2AccessToken refreshedAccessToken = getTokenServices().refreshAccessToken( - expectedExpiringRefreshToken.getValue(), new OAuth2Request("id", null)); + expectedExpiringRefreshToken.getValue(), tokenRequest); assertNotNull(refreshedAccessToken); assertEquals(1, getAccessTokenCount()); } @@ -193,16 +198,17 @@ public void testNotReuseRefreshTokenMaintainsState() throws Exception { getTokenServices().setReuseRefreshToken(false); OAuth2AccessToken accessToken = getTokenServices().createAccessToken(createAuthentication()); OAuth2RefreshToken expectedExpiringRefreshToken = accessToken.getRefreshToken(); + TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap("client_id", "id"), "id", null, null); OAuth2AccessToken refreshedAccessToken = getTokenServices().refreshAccessToken( - expectedExpiringRefreshToken.getValue(), new OAuth2Request("id", null)); + expectedExpiringRefreshToken.getValue(), tokenRequest); assertNotNull(refreshedAccessToken); assertEquals(1, getRefreshTokenCount()); } private OAuth2Authentication createAuthentication() { - return new OAuth2Authentication(new OAuth2Request("id", - Collections.singleton("read")), new TestAuthentication("test2", false)); + return new OAuth2Authentication(new StoredOAuth2Request(null, "id", null, false, + Collections.singleton("read"), null, null, null), new TestAuthentication("test2", false)); } protected abstract int getAccessTokenCount(); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestDefaultTokenServicesWithInMemory.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestDefaultTokenServicesWithInMemory.java index 02aaf9c15..e33b82458 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestDefaultTokenServicesWithInMemory.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestDefaultTokenServicesWithInMemory.java @@ -19,11 +19,12 @@ import org.springframework.security.oauth2.common.OAuth2RefreshToken; import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; -import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.StoredOAuth2Request; +import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.test.util.ReflectionTestUtils; /** @@ -40,8 +41,8 @@ public class TestDefaultTokenServicesWithInMemory extends AbstractTestDefaultTok @Test public void testExpiredToken() throws Exception { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new OAuth2Request("id", - Collections.singleton("read")), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new StoredOAuth2Request(null, "id", null, false, + Collections.singleton("read"), null, null, null), new TestAuthentication("test2", false)); DefaultOAuth2AccessToken firstAccessToken = (DefaultOAuth2AccessToken) getTokenServices().createAccessToken( expectedAuthentication); // Make it expire (and rely on mutable state in volatile token store) @@ -53,8 +54,8 @@ public void testExpiredToken() throws Exception { @Test public void testExpiredRefreshToken() throws Exception { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new OAuth2Request("id", - Collections.singleton("read")), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new StoredOAuth2Request(null, "id", null, false, + Collections.singleton("read"), null, null, null), new TestAuthentication("test2", false)); DefaultOAuth2AccessToken firstAccessToken = (DefaultOAuth2AccessToken) getTokenServices().createAccessToken( expectedAuthentication); assertNotNull(firstAccessToken.getRefreshToken()); @@ -64,13 +65,14 @@ public void testExpiredRefreshToken() throws Exception { firstAccessToken.setExpiration(new Date(System.currentTimeMillis() - 1000)); expected.expect(InvalidTokenException.class); expected.expectMessage("refresh token (expired)"); - getTokenServices().refreshAccessToken(firstAccessToken.getRefreshToken().getValue(), new OAuth2Request("id", null)); + TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap("client_id", "id"), "id", null, null); + getTokenServices().refreshAccessToken(firstAccessToken.getRefreshToken().getValue(), tokenRequest); } @Test public void testExpiredRefreshTokenIsRenewedWithNewAccessToken() throws Exception { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new OAuth2Request("id", - Collections.singleton("read")), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new StoredOAuth2Request(null, "id", null, false, + Collections.singleton("read"), null, null, null), new TestAuthentication("test2", false)); DefaultOAuth2AccessToken firstAccessToken = (DefaultOAuth2AccessToken) getTokenServices().createAccessToken( expectedAuthentication); assertNotNull(firstAccessToken.getRefreshToken()); @@ -97,8 +99,8 @@ public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exceptio return client; } }); - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new OAuth2Request("id", - Collections.singleton("read")), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new StoredOAuth2Request(null, "id", null, false, + Collections.singleton("read"), null, null, null), new TestAuthentication("test2", false)); DefaultOAuth2AccessToken firstAccessToken = (DefaultOAuth2AccessToken) getTokenServices().createAccessToken( expectedAuthentication); OAuth2RefreshToken expectedExpiringRefreshToken = firstAccessToken.getRefreshToken(); @@ -111,8 +113,9 @@ public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exceptio assertEquals("The new access token should have the same refresh token", expectedExpiringRefreshToken.getValue(), secondAccessToken.getRefreshToken().getValue()); // refresh access token with refresh token - getTokenServices().refreshAccessToken(expectedExpiringRefreshToken.getValue(), - expectedAuthentication.getAuthorizationRequest()); + + TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap("client_id", "id"), "id", Collections.singleton("read"), null); + getTokenServices().refreshAccessToken(expectedExpiringRefreshToken.getValue(), tokenRequest); assertEquals(1, getAccessTokenCount()); } @@ -128,8 +131,8 @@ public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exceptio return client; } }); - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new OAuth2Request("id", - Collections.singleton("read")), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new StoredOAuth2Request(null, "id", null, false, + Collections.singleton("read"), null, null, null), new TestAuthentication("test2", false)); DefaultOAuth2AccessToken token = (DefaultOAuth2AccessToken) getTokenServices().createAccessToken( expectedAuthentication); assertNull(token.getRefreshToken()); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestInMemoryTokenStore.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestInMemoryTokenStore.java index 3ff984c13..6f04ff67f 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestInMemoryTokenStore.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestInMemoryTokenStore.java @@ -7,8 +7,8 @@ import org.junit.Before; import org.junit.Test; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; -import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.StoredOAuth2Request; /** * @author Dave Syer @@ -31,8 +31,8 @@ public void createStore() { @Test public void testTokenCountConsistency() throws Exception { for (int i = 0; i <= 10; i++) { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new OAuth2Request("id" + i, - null), new TestAuthentication("test", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new StoredOAuth2Request(null, "id" + i, + null, false, null, null, null, null), new TestAuthentication("test", false)); DefaultOAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken" + i); expectedOAuth2AccessToken.setExpiration(new Date(System.currentTimeMillis() - 1000)); if (i > 1) { @@ -44,7 +44,8 @@ public void testTokenCountConsistency() throws Exception { @Test public void testTokenCountConsistentWithExpiryQueue() throws Exception { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new OAuth2Request("id", null), new TestAuthentication("test", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new StoredOAuth2Request(null, "id", + null, false, null, null, null, null), new TestAuthentication("test", false)); DefaultOAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); expectedOAuth2AccessToken.setExpiration(new Date(System.currentTimeMillis()+10000)); for (int i = 0; i <= 10; i++) { @@ -57,8 +58,8 @@ public void testTokenCountConsistentWithExpiryQueue() throws Exception { public void testAutoFlush() throws Exception { getTokenStore().setFlushInterval(3); for (int i = 0; i <= 10; i++) { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new OAuth2Request("id" + i, - null), new TestAuthentication("test", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new StoredOAuth2Request(null, "id" + i, + null, false, null, null, null, null), new TestAuthentication("test", false)); DefaultOAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken" + i); expectedOAuth2AccessToken.setExpiration(new Date(System.currentTimeMillis() - 1000)); if (i > 2) { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestTokenStoreBase.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestTokenStoreBase.java index b5331e67e..8291faf5a 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestTokenStoreBase.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestTokenStoreBase.java @@ -27,10 +27,10 @@ import org.springframework.security.oauth2.common.DefaultOAuth2RefreshToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2RefreshToken; -import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.StoredOAuth2Request; -/** +/** * @author Dave Syer * */ @@ -45,7 +45,8 @@ public void testReadingAuthenticationForTokenThatDoesNotExist() { @Test public void testStoreAccessToken() { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new OAuth2Request("id", null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new StoredOAuth2Request(null, "id", + null, false, null, null, null, null), new TestAuthentication("test2", false)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); @@ -59,20 +60,20 @@ public void testStoreAccessToken() { @Test public void testRetrieveAccessToken() { - OAuth2Request oAuth2Request = new OAuth2Request("id", null); - oAuth2Request.setApproved(true); // normally the case for a persisted token - OAuth2Authentication authentication = new OAuth2Authentication(oAuth2Request, new TestAuthentication("test2", true)); + //Test approved request + StoredOAuth2Request storedOAuth2Request = new StoredOAuth2Request(null, "id", null, true, null, null, null, null); + OAuth2Authentication authentication = new OAuth2Authentication(storedOAuth2Request, new TestAuthentication("test2", true)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, authentication); - oAuth2Request = new OAuth2Request("id", null); - oAuth2Request.setApproved(false); - authentication = new OAuth2Authentication(oAuth2Request, new TestAuthentication("test2", true)); + //Test unapproved request + storedOAuth2Request = new StoredOAuth2Request(null, "id", null, false, null, null, null, null); + authentication = new OAuth2Authentication(storedOAuth2Request, new TestAuthentication("test2", true)); OAuth2AccessToken actualOAuth2AccessToken = getTokenStore().getAccessToken(authentication); assertEquals(expectedOAuth2AccessToken, actualOAuth2AccessToken); assertEquals(authentication.getUserAuthentication(), getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue()).getUserAuthentication()); // The authorizationRequest does not match because it is unapproved, but the token was granted to an approved request - assertFalse(oAuth2Request.equals(getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue()).getAuthorizationRequest())); + assertFalse(storedOAuth2Request.equals(getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue()).getStoredRequest())); actualOAuth2AccessToken = getTokenStore().getAccessToken(authentication); assertEquals(expectedOAuth2AccessToken, actualOAuth2AccessToken); getTokenStore().removeAccessToken(expectedOAuth2AccessToken); @@ -83,7 +84,7 @@ public void testRetrieveAccessToken() { @Test public void testFindAccessTokensByUserName() { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new OAuth2Request("id", null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new StoredOAuth2Request(null, "id", null, false, null, null, null, null), new TestAuthentication("test2", false)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); @@ -93,7 +94,7 @@ public void testFindAccessTokensByUserName() { @Test public void testFindAccessTokensByClientId() { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new OAuth2Request("id", null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new StoredOAuth2Request(null, "id", null, false, null, null, null, null), new TestAuthentication("test2", false)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); @@ -108,7 +109,7 @@ public void testReadingAccessTokenForTokenThatDoesNotExist() { @Test public void testRefreshTokenIsNotStoredDuringAccessToken() { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new OAuth2Request("id", null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new StoredOAuth2Request(null, "id", null, false, null, null, null, null), new TestAuthentication("test2", false)); DefaultOAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); expectedOAuth2AccessToken.setRefreshToken(new DefaultOAuth2RefreshToken("refreshToken")); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); @@ -123,7 +124,7 @@ public void testRefreshTokenIsNotStoredDuringAccessToken() { public void testStoreRefreshToken() { DefaultOAuth2RefreshToken expectedExpiringRefreshToken = new DefaultExpiringOAuth2RefreshToken("testToken", new Date()); - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new OAuth2Request("id", null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new StoredOAuth2Request(null, "id", null, false, null, null, null, null), new TestAuthentication("test2", false)); getTokenStore().storeRefreshToken(expectedExpiringRefreshToken, expectedAuthentication); OAuth2RefreshToken actualExpiringRefreshToken = getTokenStore().readRefreshToken("testToken"); @@ -141,30 +142,31 @@ public void testReadingRefreshTokenForTokenThatDoesNotExist() { @Test public void testGetAccessTokenForDeletedUser() throws Exception { - OAuth2Request oAuth2Request = new OAuth2Request("id", null); - oAuth2Request.setApproved(true); // normally the case for a token being persisted - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(oAuth2Request, new TestAuthentication("test", true)); + //Test approved request + StoredOAuth2Request storedOAuth2Request = new StoredOAuth2Request(null, "id", null, true, null, null, null, null); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(storedOAuth2Request, new TestAuthentication("test", true)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); assertEquals(expectedOAuth2AccessToken, getTokenStore().getAccessToken(expectedAuthentication)); assertEquals(expectedAuthentication, getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue())); - oAuth2Request = new OAuth2Request("id", null); - oAuth2Request.setApproved(false); // normally the case for a token being checked for approval - OAuth2Authentication anotherAuthentication = new OAuth2Authentication(oAuth2Request, new TestAuthentication("test", true)); + + //Test unapproved request + storedOAuth2Request = new StoredOAuth2Request(null, "id", null, false, null, null, null, null); + OAuth2Authentication anotherAuthentication = new OAuth2Authentication(storedOAuth2Request, new TestAuthentication("test", true)); assertEquals(expectedOAuth2AccessToken, getTokenStore().getAccessToken(anotherAuthentication)); // The generated key for the authentication is the same as before, but the two auths are not equal. This could // happen if there are 2 users in a system with the same username, or (more likely), if a user account was // deleted and re-created. assertEquals(anotherAuthentication.getUserAuthentication(), getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue()).getUserAuthentication()); // The authorizationRequest does not match because it is unapproved, but the token was granted to an approved request - assertFalse(oAuth2Request.equals(getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue()).getAuthorizationRequest())); + assertFalse(storedOAuth2Request.equals(getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue()).getStoredRequest())); } @Test public void testRemoveRefreshToken() { OAuth2RefreshToken expectedExpiringRefreshToken = new DefaultExpiringOAuth2RefreshToken("testToken", new Date()); - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new OAuth2Request("id", null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new StoredOAuth2Request(null, "id", null, false, null, null, null, null), new TestAuthentication("test2", false)); getTokenStore().storeRefreshToken(expectedExpiringRefreshToken, expectedAuthentication); getTokenStore().removeRefreshToken(expectedExpiringRefreshToken); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/TestScopeVoter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/TestScopeVoter.java index 312aaf48e..460f49d9b 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/TestScopeVoter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/TestScopeVoter.java @@ -27,8 +27,8 @@ import org.springframework.security.access.SecurityConfig; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.StoredOAuth2Request; /** * @author Dave Syer @@ -49,7 +49,8 @@ public void testAbstainIfNotOAuth2() throws Exception { @Test public void testDenyIfOAuth2AndExplictlyDenied() throws Exception { - OAuth2Request clientAuthentication = new OAuth2Request("foo", Collections.singleton("read")); + + StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); assertEquals( @@ -60,7 +61,7 @@ public void testDenyIfOAuth2AndExplictlyDenied() throws Exception { @Test public void testAccessGrantedIfScopesPresent() throws Exception { - OAuth2Request clientAuthentication = new OAuth2Request("foo", Collections.singleton("read")); + StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null ,null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); assertEquals( @@ -72,7 +73,7 @@ public void testAccessGrantedIfScopesPresent() throws Exception { @Test public void testAccessGrantedIfScopesPresentWithPrefix() throws Exception { voter.setScopePrefix("scope="); - OAuth2Request clientAuthentication = new OAuth2Request("foo", Collections.singleton("read")); + StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); assertEquals( @@ -83,7 +84,7 @@ public void testAccessGrantedIfScopesPresentWithPrefix() throws Exception { @Test public void testAccessDeniedIfWrongScopesPresent() throws Exception { - OAuth2Request clientAuthentication = new OAuth2Request("foo", Collections.singleton("read")); + StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); voter.setThrowException(false); @@ -95,7 +96,7 @@ public void testAccessDeniedIfWrongScopesPresent() throws Exception { @Test(expected = AccessDeniedException.class) public void testExceptionThrownIfWrongScopesPresent() throws Exception { - OAuth2Request clientAuthentication = new OAuth2Request("foo", Collections.singleton("read")); + StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); assertEquals( diff --git a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/authorization-server-extras.xml b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/authorization-server-extras.xml index 94c52daaa..18c42fcef 100644 --- a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/authorization-server-extras.xml +++ b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/authorization-server-extras.xml @@ -28,6 +28,7 @@ + From da4269eb9f4851c398444b554151a2eaf5c31782 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 8 Jul 2013 14:49:03 +0100 Subject: [PATCH 056/831] StoredOAuth2Request -> OAuth2Request --- .../TestClientCredentialsProvider.java | 2 +- .../common/DefaultOAuth2AccessToken.java | 4 +- .../oauth2/provider/AuthorizationRequest.java | 316 ++---------------- .../security/oauth2/provider/BaseRequest.java | 145 ++++++++ .../provider/DefaultOAuth2RequestFactory.java | 20 +- .../oauth2/provider/OAuth2Authentication.java | 6 +- .../oauth2/provider/OAuth2Request.java | 181 ++++++++++ .../oauth2/provider/OAuth2RequestFactory.java | 12 +- .../oauth2/provider/StoredOAuth2Request.java | 170 ---------- .../oauth2/provider/TokenRequest.java | 73 ++-- .../TokenServicesUserApprovalHandler.java | 4 +- .../code/AuthorizationCodeTokenGranter.java | 9 +- .../endpoint/AuthorizationEndpoint.java | 4 +- .../provider/endpoint/TokenEndpoint.java | 13 +- .../TokenEndpointAuthenticationFilter.java | 10 +- .../expression/OAuth2ExpressionUtils.java | 7 +- .../implicit/ImplicitTokenGranter.java | 4 +- .../ResourceOwnerPasswordTokenGranter.java | 10 +- .../provider/token/AbstractTokenGranter.java | 4 +- .../DefaultAuthenticationKeyGenerator.java | 4 +- .../provider/token/DefaultTokenServices.java | 13 +- .../oauth2/provider/vote/ScopeVoter.java | 4 +- ...2ClientAuthenticationProcessingFilter.java | 5 +- .../oauth2/provider/RequestTokenFactory.java | 38 +++ .../provider/TestOAuth2Authentication.java | 4 +- .../TestTokenServicesUserApprovalHandler.java | 4 +- .../TestOAuth2AuthenticationManager.java | 4 +- ...tOAuth2AuthenticationProcessingFilter.java | 4 +- .../TestAuthorizationCodeServicesBase.java | 7 +- .../TestAuthorizationCodeTokenGranter.java | 18 +- ...OAuth2MethodSecurityExpressionHandler.java | 11 +- .../TestOAuth2SecurityExpressionMethods.java | 23 +- ...estOAuth2WebSecurityExpressionHandler.java | 9 +- .../AbstractTestDefaultTokenServices.java | 9 +- .../TestDefaultTokenServicesWithInMemory.java | 17 +- .../token/TestInMemoryTokenStore.java | 11 +- .../provider/token/TestTokenStoreBase.java | 24 +- .../oauth2/provider/vote/TestScopeVoter.java | 13 +- 38 files changed, 562 insertions(+), 654 deletions(-) create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java delete mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/StoredOAuth2Request.java create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/RequestTokenFactory.java diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestClientCredentialsProvider.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestClientCredentialsProvider.java index 4789169c4..7ca5b04be 100644 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestClientCredentialsProvider.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestClientCredentialsProvider.java @@ -68,7 +68,7 @@ public void testPostForTokenWithForm() throws Exception { @OAuth2ContextConfiguration(NoScopeClientCredentials.class) public void testPostForTokenWithNoScopes() throws Exception { OAuth2AccessToken token = context.getAccessToken(); - assertFalse(token.getScope().isEmpty()); + assertFalse("Wrong scope: " + token.getScope(), token.getScope().isEmpty()); } @Test diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/DefaultOAuth2AccessToken.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/DefaultOAuth2AccessToken.java index a20dc84ab..9dbc83c15 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/DefaultOAuth2AccessToken.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/DefaultOAuth2AccessToken.java @@ -44,7 +44,7 @@ public DefaultOAuth2AccessToken(String value) { */ @SuppressWarnings("unused") private DefaultOAuth2AccessToken() { - this((String)null); + this((String) null); } /** @@ -60,7 +60,7 @@ public DefaultOAuth2AccessToken(OAuth2AccessToken accessToken) { setScope(accessToken.getScope()); setTokenType(accessToken.getTokenType()); } - + public DefaultOAuth2AccessToken setValue(String value) { DefaultOAuth2AccessToken result = new DefaultOAuth2AccessToken(this); result.value = value; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java index 6ab430797..fe0f5dc58 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java @@ -5,12 +5,10 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.oauth2.common.util.OAuth2Utils; /** * Base class representing an OAuth2 Authorization Request. HTTP request parameters are stored in @@ -23,63 +21,16 @@ * @author Dave Syer * @author Amanda Anganes */ -public class AuthorizationRequest implements Serializable { +public class AuthorizationRequest extends OAuth2Request implements Serializable { private static final long serialVersionUID = 1L; - /** - * Map of parameters passed in to the Authorization Endpoint or Token - * Endpoint, preserved unchanged from the original request. This map should - * not be modified after initialization. In general, classes should not - * retrieve values from this map directly, and should instead use the - * individual members on this class. - * - * The OAuth2RequestFactory is responsible for initializing all members of - * this class, usually by parsing the values inside the requestParmaeters - * map. - * - */ - private Map requestParameters = Collections.unmodifiableMap(new HashMap()); - /** * Map to hold the original, unchanged parameter set returned from the * Approval Endpoint. Once set this should not be modified. */ private Map approvalParameters = Collections.unmodifiableMap(new HashMap()); - /** - * Resolved client ID. This may be present in the original request - * parameters, or in some cases may be inferred by a processing class and - * inserted here. - */ - private String clientId; - - /** - * Resolved scope set, initialized (by the OAuth2RequestFactory) with the - * scopes originally requested. Further processing and user interaction may - * alter the set of scopes that is finally granted and stored when the - * request processing is complete. - */ - private Set scope = new HashSet(); - - /** - * Resolved resource IDs. This set may change during request processing. - */ - private Set resourceIds = new HashSet(); - - /** - * Resolved granted authorities for this request. May change during request - * processing. - */ - private Collection authorities = new HashSet(); - - /** - * Whether the request has been approved by the end user (or other process). - * This will be altered by the User Approval Endpoint and/or the - * UserApprovalHandler as appropriate. - */ - private boolean approved = false; - /** * The value of the "state" parameter sent by the client in the request, if * sent by the client. As this must be echoed back to the client unchanged, @@ -87,76 +38,36 @@ public class AuthorizationRequest implements Serializable { */ private String state; - /** - * The resolved redirect URI of this request. A URI may be present in the - * original request, in the authorizationParameters, or it may not be - * provided, in which case it will be defaulted (by processing classes) to - * the Client's default registered value. - */ - private String resolvedRedirectUri; - /** * Resolved requested response types initialized (by the * OAuth2RequestFactory) with the response types originally requested. */ private Set responseTypes = new HashSet(); - /** - * Extension point for custom processing classes which may wish to store - * additional information about the OAuth2 request. Since this class is - * serializable, all members of this map must also be serializable. - */ - private Map extensionProperties = new HashMap(); - /** * Default constructor. */ public AuthorizationRequest() { - } /** * Full constructor. - * - * @param authorizationParameters - * @param approvalParameters - * @param clientId - * @param scope - * @param resourceIds - * @param authorities - * @param approved - * @param state - * @param redirectUri - * @param responseTypes */ public AuthorizationRequest(Map authorizationParameters, Map approvalParameters, String clientId, Set scope, Set resourceIds, Collection authorities, boolean approved, String state, String redirectUri, Set responseTypes){ - if (authorizationParameters != null) { - this.requestParameters = Collections.unmodifiableMap(authorizationParameters); - } - if (approvalParameters != null) { - this.approvalParameters = Collections.unmodifiableMap(approvalParameters); - } - if (resourceIds != null) { - this.resourceIds = new HashSet(resourceIds); - } - if (scope != null) { - this.scope = new LinkedHashSet(scope); - } - if (authorities != null) { - this.authorities = new HashSet(authorities); - } + super(authorizationParameters, clientId, authorities, approved, scope, resourceIds, redirectUri, null); if (responseTypes != null) { this.responseTypes = responseTypes; } - this.resolvedRedirectUri = redirectUri; this.state = state; - this.clientId = clientId; - this.approved = approved; } + public OAuth2Request createOAuth2Request() { + return new OAuth2Request((OAuth2Request)this); + } + /** * Convenience constructor for unit tests, where client ID and scope are often * the only needed fields. @@ -165,10 +76,8 @@ public AuthorizationRequest(Map authorizationParameters, Map scopes) { - this.clientId = clientId; - if (scopes!= null) { - this.scope.addAll(scopes); - } + super(clientId); + setScope(new HashSet(scopes)); } /** @@ -178,30 +87,10 @@ public AuthorizationRequest(String clientId, Collection scopes) { * @param clientDetails */ public void setResourceIdsAndAuthoritiesFromClientDetails(ClientDetails clientDetails) { - resourceIds.addAll(clientDetails.getResourceIds()); - authorities.addAll(clientDetails.getAuthorities()); + setResourceIds(clientDetails.getResourceIds()); + setAuthorities(clientDetails.getAuthorities()); } - /** - * Warning: most classes should use the individual properties of this class, such - * as {{@link #getScope()} or {{@link #getClientId()}, rather than retrieving values from this map. - * - * @return the original, unchanged set of request parameters - */ - public Map getRequestParameters() { - return requestParameters; - } - - /** - * Warning: most classes should not alter this map after it has been initialized. - * - * @param requestParameters the original, unchanged set of request parameters to set - */ - public void setRequestParameters( - Map requestParameters) { - this.requestParameters = Collections.unmodifiableMap(requestParameters); - } - public Map getApprovalParameters() { return approvalParameters; } @@ -210,59 +99,6 @@ public void setApprovalParameters(Map approvalParameters) { this.approvalParameters = approvalParameters; } - public String getClientId() { - return clientId; - } - - public void setClientId(String clientId) { - this.clientId = clientId; - } - - public Set getScope() { - return scope; - } - - //TODO: remove parser and do intensive wiretesting to see if this is really needed - public void setScope(Set scope) { - if (scope != null && scope.size() == 1) { - String value = scope.iterator().next(); - /* - * This is really an error, but it can catch out unsuspecting users and it's easy to fix. It happens when an - * AuthorizationRequest gets bound accidentally from request parameters using @ModelAttribute. - */ - if (value.contains(" ") || scope.contains(",")) { - scope = OAuth2Utils.parseParameterList(value); - } - } - this.scope = scope == null ? new LinkedHashSet() : new LinkedHashSet(scope); - } - - public Set getResourceIds() { - return resourceIds; - } - - public void setResourceIds(Set resourceIds) { - this.resourceIds = resourceIds; - } - - public Collection getAuthorities() { - return authorities; - } - - public void setAuthorities(Collection authorities) { - if (authorities!= null) { - this.authorities = new HashSet(authorities); - } - } - - public boolean isApproved() { - return approved; - } - - public void setApproved(boolean approved) { - this.approved = approved; - } - public String getState() { return state; } @@ -271,14 +107,6 @@ public void setState(String state) { this.state = state; } - public String getRedirectUri() { - return resolvedRedirectUri; - } - - public void setRedirectUri(String redirectUri) { - this.resolvedRedirectUri = redirectUri; - } - public Set getResponseTypes() { return responseTypes; } @@ -287,140 +115,46 @@ public void setResponseTypes(Set responseTypes) { this.responseTypes = responseTypes; } - /** - * @return the extensionProperties - */ - public Map getExtensionProperties() { - return extensionProperties; - } - - /** - * @param extensionProperties the extensionProperties to set - */ - public void setExtensionProperties(Map extensionProperties) { - this.extensionProperties = extensionProperties; - } - @Override public int hashCode() { final int prime = 31; - int result = 1; - result = prime - * result - + ((approvalParameters == null) ? 0 : approvalParameters - .hashCode()); - result = prime * result + (approved ? 1231 : 1237); - result = prime * result - + ((authorities == null) ? 0 : authorities.hashCode()); - result = prime * result - + ((clientId == null) ? 0 : clientId.hashCode()); - result = prime - * result - + ((extensionProperties == null) ? 0 : extensionProperties - .hashCode()); - result = prime - * result - + ((requestParameters == null) ? 0 : requestParameters - .hashCode()); - result = prime - * result - + ((resolvedRedirectUri == null) ? 0 : resolvedRedirectUri - .hashCode()); - result = prime * result - + ((resourceIds == null) ? 0 : resourceIds.hashCode()); - result = prime * result - + ((responseTypes == null) ? 0 : responseTypes.hashCode()); - result = prime * result + ((scope == null) ? 0 : scope.hashCode()); + int result = super.hashCode(); + result = prime * result + ((approvalParameters == null) ? 0 : approvalParameters.hashCode()); + result = prime * result + ((responseTypes == null) ? 0 : responseTypes.hashCode()); result = prime * result + ((state == null) ? 0 : state.hashCode()); return result; } @Override public boolean equals(Object obj) { - if (this == obj) { + if (this == obj) return true; - } - if (obj == null) { + if (!super.equals(obj)) return false; - } - if (!(obj instanceof AuthorizationRequest)) { + if (getClass() != obj.getClass()) return false; - } AuthorizationRequest other = (AuthorizationRequest) obj; if (approvalParameters == null) { - if (other.approvalParameters != null) { + if (other.approvalParameters != null) return false; - } - } else if (!approvalParameters.equals(other.approvalParameters)) { - return false; - } - if (approved != other.approved) { - return false; - } - if (authorities == null) { - if (other.authorities != null) { - return false; - } - } else if (!authorities.equals(other.authorities)) { - return false; - } - if (clientId == null) { - if (other.clientId != null) { - return false; - } - } else if (!clientId.equals(other.clientId)) { - return false; } - if (extensionProperties == null) { - if (other.extensionProperties != null) { - return false; - } - } else if (!extensionProperties.equals(other.extensionProperties)) { + else if (!approvalParameters.equals(other.approvalParameters)) return false; - } - if (requestParameters == null) { - if (other.requestParameters != null) { - return false; - } - } else if (!requestParameters.equals(other.requestParameters)) { - return false; - } - if (resolvedRedirectUri == null) { - if (other.resolvedRedirectUri != null) { - return false; - } - } else if (!resolvedRedirectUri.equals(other.resolvedRedirectUri)) { - return false; - } - if (resourceIds == null) { - if (other.resourceIds != null) { - return false; - } - } else if (!resourceIds.equals(other.resourceIds)) { - return false; - } if (responseTypes == null) { - if (other.responseTypes != null) { + if (other.responseTypes != null) return false; - } - } else if (!responseTypes.equals(other.responseTypes)) { - return false; } - if (scope == null) { - if (other.scope != null) { - return false; - } - } else if (!scope.equals(other.scope)) { + else if (!responseTypes.equals(other.responseTypes)) return false; - } if (state == null) { - if (other.state != null) { + if (other.state != null) return false; - } - } else if (!state.equals(other.state)) { - return false; } + else if (!state.equals(other.state)) + return false; return true; } + + } \ No newline at end of file diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java new file mode 100644 index 000000000..d538a42f7 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java @@ -0,0 +1,145 @@ +/* + * Cloud Foundry 2012.02.03 Beta + * Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved. + * + * This product is licensed to you under the Apache License, Version 2.0 (the "License"). + * You may not use this product except in compliance with the License. + * + * This product includes a number of subcomponents with + * separate copyright notices and license terms. Your use of these + * subcomponents is subject to the terms and conditions of the + * subcomponent's license, as noted in the LICENSE file. + */ + +package org.springframework.security.oauth2.provider; + +import java.io.Serializable; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +import org.springframework.security.oauth2.common.util.OAuth2Utils; + +/** + * @author Dave Syer + * + */ +public class BaseRequest implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * Resolved client ID. This may be present in the original request parameters, or in some cases may be inferred by a + * processing class and inserted here. + */ + private String clientId; + + /** + * Resolved scope set, initialized (by the OAuth2RequestFactory) with the scopes originally requested. Further + * processing and user interaction may alter the set of scopes that is finally granted and stored when the request + * processing is complete. + */ + private Set scope = new HashSet(); + + /** + * Map of parameters passed in to the Authorization Endpoint or Token Endpoint, preserved unchanged from the + * original request. This map should not be modified after initialization. In general, classes should not retrieve + * values from this map directly, and should instead use the individual members on this class. + * + * The OAuth2RequestFactory is responsible for initializing all members of this class, usually by parsing the values + * inside the requestParmaeters map. + * + */ + private Map requestParameters = Collections.unmodifiableMap(new HashMap()); + + public BaseRequest(String clientId) { + this.clientId = clientId; + } + + public String getClientId() { + return clientId; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + public Set getScope() { + return scope; + } + + public void setScope(Set scope) { + if (scope != null && scope.size() == 1) { + String value = scope.iterator().next(); + /* + * This is really an error, but it can catch out unsuspecting users and it's easy to fix. It happens when an + * AuthorizationRequest gets bound accidentally from request parameters using @ModelAttribute. + */ + if (value.contains(" ") || scope.contains(",")) { + scope = OAuth2Utils.parseParameterList(value); + } + } + this.scope = Collections.unmodifiableSet(scope == null ? new LinkedHashSet() + : new LinkedHashSet(scope)); + } + + /** + * Warning: most clients should use the individual properties of this class, such as {{@link #getScope()} or { + * {@link #getClientId()}, rather than retrieving values from this map. + * + * @return the original, unchanged set of request parameters + */ + public Map getRequestParameters() { + return requestParameters; + } + + public void setRequestParameters(Map requestParameters) { + if (requestParameters != null) { + this.requestParameters = Collections.unmodifiableMap(requestParameters); + } + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((clientId == null) ? 0 : clientId.hashCode()); + result = prime * result + ((requestParameters == null) ? 0 : requestParameters.hashCode()); + result = prime * result + ((scope == null) ? 0 : scope.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + BaseRequest other = (BaseRequest) obj; + if (clientId == null) { + if (other.clientId != null) + return false; + } + else if (!clientId.equals(other.clientId)) + return false; + if (requestParameters == null) { + if (other.requestParameters != null) + return false; + } + else if (!requestParameters.equals(other.requestParameters)) + return false; + if (scope == null) { + if (other.scope != null) + return false; + } + else if (!scope.equals(other.scope)) + return false; + return true; + } + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestFactory.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestFactory.java index 962a8ff2b..17977fee7 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestFactory.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestFactory.java @@ -60,10 +60,8 @@ public AuthorizationRequest createAuthorizationRequest(Map autho } - public StoredOAuth2Request createStoredAuthorizationRequest(AuthorizationRequest request) { - StoredOAuth2Request storedOAuth2Request = new StoredOAuth2Request(request.getRequestParameters(), request.getClientId(), request.getAuthorities(), - request.isApproved(), request.getScope(), request.getResourceIds(), request.getRedirectUri(), request.getExtensionProperties()); - return storedOAuth2Request; + public OAuth2Request createStoredAuthorizationRequest(AuthorizationRequest request) { + return request.createOAuth2Request(); } public TokenRequest createTokenRequest(Map requestParameters) { @@ -72,6 +70,15 @@ public TokenRequest createTokenRequest(Map requestParameters) { Set scopes = OAuth2Utils.parseParameterList(requestParameters.get(OAuth2Utils.SCOPE)); String grantType = requestParameters.get(OAuth2Utils.GRANT_TYPE); + ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId); + + if ((scopes == null || scopes.isEmpty())) { + // If no scopes are specified in the incoming data, use the default values registered with the client + // (the spec allows us to choose between this option and rejecting the request completely, so we'll take the + // least obnoxious choice as a default). + scopes = clientDetails.getScope(); + } + TokenRequest tokenRequest = new TokenRequest(requestParameters, clientId, scopes, grantType); return tokenRequest; @@ -82,9 +89,8 @@ public TokenRequest createTokenRequestFromAuthorizationRequest(AuthorizationRequ return tokenRequest; } - public StoredOAuth2Request createStoredTokenRequest(TokenRequest tokenRequest) { - StoredOAuth2Request storedOAuth2Request = new StoredOAuth2Request(tokenRequest.getRequestParameters(), tokenRequest.getClientId(), null, true, tokenRequest.getScope(), null, null, null); - return storedOAuth2Request; + public OAuth2Request createStoredTokenRequest(TokenRequest tokenRequest) { + return tokenRequest.createOAuth2Request(); } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Authentication.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Authentication.java index 162b49f06..ed273d43d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Authentication.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Authentication.java @@ -13,7 +13,7 @@ public class OAuth2Authentication extends AbstractAuthenticationToken { private static final long serialVersionUID = -4809832298438307309L; - private final StoredOAuth2Request storedRequest; + private final OAuth2Request storedRequest; private final Authentication userAuthentication; @@ -24,7 +24,7 @@ public class OAuth2Authentication extends AbstractAuthenticationToken { * @param authorizationRequest The authorization request (must not be null). * @param userAuthentication The user authentication (possibly null). */ - public OAuth2Authentication(StoredOAuth2Request clientAuthentication, Authentication userAuthentication) { + public OAuth2Authentication(OAuth2Request clientAuthentication, Authentication userAuthentication) { super(userAuthentication == null ? clientAuthentication.getAuthorities() : userAuthentication.getAuthorities()); this.storedRequest = clientAuthentication; this.userAuthentication = userAuthentication; @@ -53,7 +53,7 @@ public boolean isClientOnly() { * * @return The client authentication. */ - public StoredOAuth2Request getStoredRequest() { + public OAuth2Request getStoredRequest() { return storedRequest; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java new file mode 100644 index 000000000..4f5c657eb --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java @@ -0,0 +1,181 @@ +package org.springframework.security.oauth2.provider; + +import java.io.Serializable; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.springframework.security.core.GrantedAuthority; + +/** + * Represents a stored authorization or token request. Used as part of the OAuth2Authentication object to store a + * request's authentication information. + * + * @author Amanda Anganes + * + */ +public class OAuth2Request extends BaseRequest implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * Resolved resource IDs. This set may change during request processing. + */ + private Set resourceIds = new HashSet(); + + /** + * Resolved granted authorities for this request. May change during request processing. + */ + private Collection authorities = new HashSet(); + + /** + * Whether the request has been approved by the end user (or other process). This will be altered by the User + * Approval Endpoint and/or the UserApprovalHandler as appropriate. + */ + private boolean approved = false; + + /** + * The resolved redirect URI of this request. A URI may be present in the original request, in the + * authorizationParameters, or it may not be provided, in which case it will be defaulted (by processing classes) to + * the Client's default registered value. + */ + private String redirectUri; + + /** + * Extension point for custom processing classes which may wish to store additional information about the OAuth2 + * request. Since this class is serializable, all members of this map must also be serializable. + */ + private Map extensionProperties = new HashMap(); + + protected OAuth2Request(Map requestParameters, String clientId, + Collection authorities, boolean approved, Set scope, + Set resourceIds, String redirectUri, Map extensionProperties) { + super(clientId); + setRequestParameters(requestParameters); + setScope(scope); + if (resourceIds != null) { + this.resourceIds = new HashSet(resourceIds); + } + if (authorities != null) { + this.authorities = new HashSet(authorities); + } + this.approved = approved; + this.resourceIds = resourceIds; + this.redirectUri = redirectUri; + if (extensionProperties != null) { + this.extensionProperties = extensionProperties; + } + } + + protected OAuth2Request(OAuth2Request other) { + this(other.getRequestParameters(), other.getClientId(), other.getAuthorities(), other.isApproved(), other + .getScope(), other.getResourceIds(), other.getRedirectUri(), other.getExtensionProperties()); + } + + protected OAuth2Request(String clientId) { + super(clientId); + } + + protected OAuth2Request() { + super(""); + } + + public String getRedirectUri() { + return redirectUri; + } + + public void setRedirectUri(String redirectUri) { + this.redirectUri = redirectUri; + } + + public Collection getAuthorities() { + return authorities; + } + + public void setAuthorities(Collection authorities) { + this.authorities = authorities; + } + + public boolean isApproved() { + return approved; + } + + public void setApproved(boolean approved) { + this.approved = approved; + } + + public Set getResourceIds() { + return resourceIds; + } + + public void setResourceIds(Set resourceIds) { + this.resourceIds = resourceIds; + } + + public Map getExtensionProperties() { + return extensionProperties; + } + + public void setExtensionProperties(Map extensionProperties) { + this.extensionProperties = extensionProperties; + } + + // FIXME: is this needed? + public OAuth2Request createOAuth2Request(Map parameters) { + return new OAuth2Request(parameters, getClientId(), authorities, approved, getScope(), resourceIds, + redirectUri, extensionProperties); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (approved ? 1231 : 1237); + result = prime * result + ((authorities == null) ? 0 : authorities.hashCode()); + result = prime * result + ((extensionProperties == null) ? 0 : extensionProperties.hashCode()); + result = prime * result + ((redirectUri == null) ? 0 : redirectUri.hashCode()); + result = prime * result + ((resourceIds == null) ? 0 : resourceIds.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + OAuth2Request other = (OAuth2Request) obj; + if (approved != other.approved) + return false; + if (authorities == null) { + if (other.authorities != null) + return false; + } + else if (!authorities.equals(other.authorities)) + return false; + if (extensionProperties == null) { + if (other.extensionProperties != null) + return false; + } + else if (!extensionProperties.equals(other.extensionProperties)) + return false; + if (redirectUri == null) { + if (other.redirectUri != null) + return false; + } + else if (!redirectUri.equals(other.redirectUri)) + return false; + if (resourceIds == null) { + if (other.resourceIds != null) + return false; + } + else if (!resourceIds.equals(other.resourceIds)) + return false; + return true; + } + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestFactory.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestFactory.java index 22767fa32..c409b6e05 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestFactory.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestFactory.java @@ -16,7 +16,7 @@ import java.util.Map; /** - * Strategy for managing OAuth2 requests: {@link AuthorizationRequest}, {@link TokenRequest}, {@link StoredRequest}. + * Strategy for managing OAuth2 requests: {@link AuthorizationRequest}, {@link TokenRequest}, {@link OAuth2Request}. * * @author Dave Syer * @author Amanda Anganes @@ -39,23 +39,23 @@ public interface OAuth2RequestFactory { AuthorizationRequest createAuthorizationRequest(Map authorizationParameters); /** - * Create a new {@link StoredOAuth2Request} by extracting the needed information from the current {@link AuthorizationRequest} object. + * Create a new {@link OAuth2Request} by extracting the needed information from the current {@link AuthorizationRequest} object. * * @param request the request to be converted * @return an immutable object for storage */ - StoredOAuth2Request createStoredAuthorizationRequest(AuthorizationRequest request); + OAuth2Request createStoredAuthorizationRequest(AuthorizationRequest request); /** - * Create a new {@link StoredOAuth2Request} by extracting the needed information from the current {@link TokenRequest} object. + * Create a new {@link OAuth2Request} by extracting the needed information from the current {@link TokenRequest} object. * * @param tokenRequest the request to be converted * @return am immutable object for storage */ - StoredOAuth2Request createStoredTokenRequest(TokenRequest tokenRequest); + OAuth2Request createStoredTokenRequest(TokenRequest tokenRequest); /** - * Create a new {@link TokenRequest} by extracted the needed information from the incoming request parameter map. + * Create a new {@link TokenRequest} by extracting the needed information from the incoming request parameter map. * * @param requestParameters the parameters in the request * @return a new TokenRequest diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/StoredOAuth2Request.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/StoredOAuth2Request.java deleted file mode 100644 index cc2c7ec3f..000000000 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/StoredOAuth2Request.java +++ /dev/null @@ -1,170 +0,0 @@ -package org.springframework.security.oauth2.provider; - -import java.io.Serializable; -import java.util.Collection; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import org.springframework.security.core.GrantedAuthority; - -/** - * Represents a stored authorization or token request. Used as part of the OAuth2Authentication object to store - * a request's authentication information. - * - * @author Amanda Anganes - * - */ -public class StoredOAuth2Request implements Serializable { - - private static final long serialVersionUID = 1L; - - private String clientId; - private Set authorities; - private boolean approved; - private Set scope; - private Set resourceIds; - private Map requestParameters; - private String redirectUri; - private Map extensionProperties; - - public StoredOAuth2Request(Map requestParameters, String clientId, Collection authorities, boolean approved, Set scope, Set resourceIds, String redirectUri, Map extensionProperties) { - this.requestParameters = requestParameters; - this.clientId = clientId; - this.authorities = (authorities!=null ? new HashSet(authorities) : null); - this.approved = approved; - this.scope = scope; - this.resourceIds = resourceIds; - this.redirectUri = redirectUri; - this.extensionProperties = extensionProperties; - } - - public String getClientId() { - return clientId; - } - - public String getRedirectUri() { - return redirectUri; - } - - public Set getAuthorities() { - return authorities; - } - - public boolean isApproved() { - return approved; - } - - public Set getScope() { - return scope; - } - - public Set getResourceIds() { - return resourceIds; - } - - public Map getRequestParameters() { - return requestParameters; - } - - public Map getExtensionProperties() { - return extensionProperties; - } - - public void setExtensionProperties(Map extensionProperties) { - this.extensionProperties = extensionProperties; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + (approved ? 1231 : 1237); - result = prime * result - + ((authorities == null) ? 0 : authorities.hashCode()); - result = prime * result - + ((clientId == null) ? 0 : clientId.hashCode()); - result = prime - * result - + ((extensionProperties == null) ? 0 : extensionProperties - .hashCode()); - result = prime * result - + ((redirectUri == null) ? 0 : redirectUri.hashCode()); - result = prime - * result - + ((requestParameters == null) ? 0 : requestParameters - .hashCode()); - result = prime * result - + ((resourceIds == null) ? 0 : resourceIds.hashCode()); - result = prime * result + ((scope == null) ? 0 : scope.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof StoredOAuth2Request)) { - return false; - } - StoredOAuth2Request other = (StoredOAuth2Request) obj; - if (approved != other.approved) { - return false; - } - if (authorities == null) { - if (other.authorities != null) { - return false; - } - } else if (!authorities.equals(other.authorities)) { - return false; - } - if (clientId == null) { - if (other.clientId != null) { - return false; - } - } else if (!clientId.equals(other.clientId)) { - return false; - } - if (extensionProperties == null) { - if (other.extensionProperties != null) { - return false; - } - } else if (!extensionProperties.equals(other.extensionProperties)) { - return false; - } - if (redirectUri == null) { - if (other.redirectUri != null) { - return false; - } - } else if (!redirectUri.equals(other.redirectUri)) { - return false; - } - if (requestParameters == null) { - if (other.requestParameters != null) { - return false; - } - } else if (!requestParameters.equals(other.requestParameters)) { - return false; - } - if (resourceIds == null) { - if (other.resourceIds != null) { - return false; - } - } else if (!resourceIds.equals(other.resourceIds)) { - return false; - } - if (scope == null) { - if (other.scope != null) { - return false; - } - } else if (!scope.equals(other.scope)) { - return false; - } - return true; - } - -} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java index 1f8697974..f0fc07be8 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java @@ -1,9 +1,13 @@ package org.springframework.security.oauth2.provider; -import java.util.Collections; +import java.io.Serializable; +import java.util.HashMap; import java.util.Map; import java.util.Set; +import org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint; +import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint; + /** * Represents an OAuth2 token request, made at the {@link TokenEndpoint}. The requestParameters map should * contain the original, unmodified parameters from the original OAuth2 request. @@ -15,13 +19,19 @@ * @author Amanda Anganes * */ -public class TokenRequest { +public class TokenRequest extends BaseRequest implements Serializable { + + private static final long serialVersionUID = 1L; - private Map requestParameters; - private String clientId; - private Set scope; private String grantType; + /** + * Default constructor + */ + protected TokenRequest() { + super(""); + } + /** * Full constructor. Sets this TokenRequest's requestParameters map to an unmodifiable version of the one provided. * @@ -31,51 +41,12 @@ public class TokenRequest { * @param grantType */ public TokenRequest(Map requestParameters, String clientId, Set scope, String grantType) { - - if (requestParameters != null) { - this.requestParameters = Collections.unmodifiableMap(requestParameters); - } - - this.clientId = clientId; - this.scope = scope; + super(clientId); + setRequestParameters(requestParameters); + setScope(scope); this.grantType = grantType; } - /** - * Warning: most classes should not need to interact with the parameters map directly. - * - * @return the original token request's parameters map - */ - public Map getRequestParameters() { - return requestParameters; - } - - /** - * Warning: This method should not be called during normal usage. Instead, properties that need to be - * altered during processing should be stored on individual property fields on this object. - * - * @param requestParameters the parameter map to set - */ - public void setRequestParameters(Map requestParameters) { - this.requestParameters = requestParameters; - } - - public String getClientId() { - return clientId; - } - - public void setClientId(String clientId) { - this.clientId = clientId; - } - - public Set getScope() { - return scope; - } - - public void setScope(Set scope) { - this.scope = scope; - } - public String getGrantType() { return grantType; } @@ -83,5 +54,13 @@ public String getGrantType() { public void setGrantType(String grantType) { this.grantType = grantType; } + + public OAuth2Request createOAuth2Request() { + // Remove password if present to prevent leaks + Map requestParameters = getRequestParameters(); + HashMap modifiable = new HashMap(requestParameters); + modifiable.remove("password"); + return new OAuth2Request(modifiable, this.getClientId(), null, true, this.getScope(), null, null, null); + } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenServicesUserApprovalHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenServicesUserApprovalHandler.java index f3b7a6e36..72df47ce8 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenServicesUserApprovalHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenServicesUserApprovalHandler.java @@ -25,7 +25,7 @@ import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; -import org.springframework.security.oauth2.provider.StoredOAuth2Request; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; import org.springframework.util.Assert; @@ -82,7 +82,7 @@ public boolean isApproved(AuthorizationRequest authorizationRequest, Authenticat String flag = authorizationRequest.getApprovalParameters().get(approvalParameter); boolean approved = flag != null && flag.toLowerCase().equals("true"); - StoredOAuth2Request storedOAuth2Request = requestFactory.createStoredAuthorizationRequest(authorizationRequest); + OAuth2Request storedOAuth2Request = requestFactory.createStoredAuthorizationRequest(authorizationRequest); OAuth2Authentication authentication = new OAuth2Authentication(storedOAuth2Request, userAuthentication); if (logger.isDebugEnabled()) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranter.java index 3699052a2..2ceba16ca 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranter.java @@ -28,7 +28,7 @@ import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; -import org.springframework.security.oauth2.provider.StoredOAuth2Request; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.token.AbstractTokenGranter; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; @@ -67,7 +67,7 @@ protected OAuth2Authentication getOAuth2Authentication(TokenRequest tokenRequest throw new InvalidGrantException("Invalid authorization code: " + authorizationCode); } - StoredOAuth2Request pendingOAuth2Request = storedAuth.getStoredRequest(); + OAuth2Request pendingOAuth2Request = storedAuth.getStoredRequest(); // https://jira.springsource.org/browse/SECOAUTH-333 // This might be null, if the authorization was done without the redirect_uri parameter String redirectUriApprovalParameter = pendingOAuth2Request.getRequestParameters().get( @@ -95,10 +95,7 @@ protected OAuth2Authentication getOAuth2Authentication(TokenRequest tokenRequest combinedParameters.putAll(parameters); //Make a new stored request with the combined parameters - StoredOAuth2Request finalStoredOAuth2Request = new StoredOAuth2Request(combinedParameters, clientId, - pendingOAuth2Request.getAuthorities(), pendingOAuth2Request.isApproved(), - pendingOAuth2Request.getScope(), pendingOAuth2Request.getResourceIds(), pendingOAuth2Request.getRedirectUri(), - pendingOAuth2Request.getExtensionProperties()); + OAuth2Request finalStoredOAuth2Request = pendingOAuth2Request.createOAuth2Request(combinedParameters); Authentication userAuth = storedAuth.getUserAuthentication(); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java index 357d36877..41a6488d1 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java @@ -46,7 +46,7 @@ import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.OAuth2RequestValidator; -import org.springframework.security.oauth2.provider.StoredOAuth2Request; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.approval.DefaultUserApprovalHandler; import org.springframework.security.oauth2.provider.approval.UserApprovalHandler; @@ -326,7 +326,7 @@ private String generateCode(AuthorizationRequest authorizationRequest, Authentic try { - StoredOAuth2Request storedOAuth2Request = getOAuth2RequestFactory().createStoredAuthorizationRequest(authorizationRequest); + OAuth2Request storedOAuth2Request = getOAuth2RequestFactory().createStoredAuthorizationRequest(authorizationRequest); OAuth2Authentication combinedAuth = new OAuth2Authentication(storedOAuth2Request, authentication); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java index 6ce085d0a..a65e3547d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java @@ -18,6 +18,7 @@ import java.security.Principal; import java.util.Collections; +import java.util.HashMap; import java.util.Map; import org.springframework.http.HttpHeaders; @@ -74,18 +75,18 @@ public ResponseEntity getAccessToken(Principal principal, "There is no client authentication. Try adding an appropriate authentication filter."); } - TokenRequest tokenRequest = getOAuth2RequestFactory().createTokenRequest(parameters); - String clientId = getClientId(principal); + HashMap map = new HashMap(parameters); if (clientId != null) { - tokenRequest.setClientId(clientId); - //Only validate the client details if a client authenticated during this - //request. + map.put(OAuth2Utils.CLIENT_ID, clientId); + // Only validate the client details if a client authenticated during this + // request. ClientDetails client = getClientDetailsService().loadClientByClientId(clientId); if (client != null) { - oAuth2RequestValidator.validateScope(parameters, client.getScope()); + oAuth2RequestValidator.validateScope(map, client.getScope()); } } + TokenRequest tokenRequest = getOAuth2RequestFactory().createTokenRequest(map); if (!StringUtils.hasText(tokenRequest.getGrantType())) { throw new InvalidRequestException("Missing grant type"); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java index 558e034da..4ca52d461 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java @@ -44,7 +44,7 @@ import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; -import org.springframework.security.oauth2.provider.StoredOAuth2Request; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; @@ -139,16 +139,18 @@ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) "No client authentication found. Remember to put a filter upstream of the TokenEndpointAuthenticationFilter."); } - AuthorizationRequest authorizationRequest = oAuth2RequestFactory.createAuthorizationRequest(getSingleValueMap(request)); + // FIXME: use client id in factory method + Map map = getSingleValueMap(request); + map.put(OAuth2Utils.CLIENT_ID, clientAuth.getName()); + AuthorizationRequest authorizationRequest = oAuth2RequestFactory.createAuthorizationRequest(map); - authorizationRequest.setClientId(clientAuth.getName()); authorizationRequest.setScope(getScope(request)); if (clientAuth.isAuthenticated()) { // Ensure the OAuth2Authentication is authenticated authorizationRequest.setApproved(true); } - StoredOAuth2Request storedOAuth2Request = oAuth2RequestFactory.createStoredAuthorizationRequest(authorizationRequest); + OAuth2Request storedOAuth2Request = oAuth2RequestFactory.createStoredAuthorizationRequest(authorizationRequest); SecurityContextHolder.getContext().setAuthentication( new OAuth2Authentication(storedOAuth2Request, authResult)); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionUtils.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionUtils.java index 3aa678ebf..add97dcb3 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionUtils.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionUtils.java @@ -18,8 +18,9 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.oauth2.provider.BaseRequest; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.StoredOAuth2Request; +import org.springframework.security.oauth2.provider.OAuth2Request; /** * @author Dave Syer @@ -29,7 +30,7 @@ public abstract class OAuth2ExpressionUtils { public static boolean clientHasAnyRole(Authentication authentication, String... roles) { if (authentication instanceof OAuth2Authentication) { - StoredOAuth2Request clientAuthentication = ((OAuth2Authentication) authentication).getStoredRequest(); + OAuth2Request clientAuthentication = ((OAuth2Authentication) authentication).getStoredRequest(); Collection clientAuthorities = clientAuthentication.getAuthorities(); if (clientAuthorities != null) { Set roleSet = AuthorityUtils.authorityListToSet(clientAuthorities); @@ -74,7 +75,7 @@ public static boolean isOAuthUserAuth(Authentication authentication) { public static boolean hasAnyScope(Authentication authentication, String[] scopes) { if (authentication instanceof OAuth2Authentication) { - StoredOAuth2Request clientAuthentication = ((OAuth2Authentication) authentication).getStoredRequest(); + BaseRequest clientAuthentication = ((OAuth2Authentication) authentication).getStoredRequest(); Collection assigned = clientAuthentication.getScope(); if (assigned != null) { for (String scope : scopes) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java index fe920a04f..925bf067b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java @@ -23,7 +23,7 @@ import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; -import org.springframework.security.oauth2.provider.StoredOAuth2Request; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.token.AbstractTokenGranter; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; @@ -48,7 +48,7 @@ protected OAuth2Authentication getOAuth2Authentication(TokenRequest clientToken) throw new InsufficientAuthenticationException("There is no currently logged in user"); } - StoredOAuth2Request storedOAuth2Request = getRequestFactory().createStoredTokenRequest(clientToken); + OAuth2Request storedOAuth2Request = getRequestFactory().createStoredTokenRequest(clientToken); return new OAuth2Authentication(storedOAuth2Request, userAuth); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java index ccb4f760b..f64416756 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java @@ -16,7 +16,6 @@ package org.springframework.security.oauth2.provider.password; -import java.util.HashMap; import java.util.Map; import org.springframework.security.authentication.AccountStatusException; @@ -27,8 +26,8 @@ import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; -import org.springframework.security.oauth2.provider.StoredOAuth2Request; import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.token.AbstractTokenGranter; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; @@ -72,14 +71,9 @@ protected OAuth2Authentication getOAuth2Authentication(TokenRequest clientToken) throw new InvalidGrantException("Could not authenticate user: " + username); } - //TODO: Why are we removing something from the original parameters map? - Map requestParameters = clientToken.getRequestParameters(); - HashMap modifiable = new HashMap(requestParameters); - modifiable.remove("password"); - //Bypass the factory and instead create our own object here, since we want all the properties of the original TokenRequest, //but with the new requestParameters map that has had the "password" parameter removed. - StoredOAuth2Request storedOAuth2Request = new StoredOAuth2Request(modifiable, clientToken.getClientId(), null, true, clientToken.getScope(), null, null, null); + OAuth2Request storedOAuth2Request = clientToken.createOAuth2Request(); return new OAuth2Authentication(storedOAuth2Request, userAuth); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AbstractTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AbstractTokenGranter.java index 6984b1471..632b7ae78 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AbstractTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AbstractTokenGranter.java @@ -22,7 +22,7 @@ import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; -import org.springframework.security.oauth2.provider.StoredOAuth2Request; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.TokenGranter; import org.springframework.security.oauth2.provider.TokenRequest; @@ -74,7 +74,7 @@ protected OAuth2AccessToken getAccessToken(TokenRequest tokenRequest) { } protected OAuth2Authentication getOAuth2Authentication(TokenRequest tokenRequest) { - StoredOAuth2Request storedOAuth2Request = requestFactory.createStoredTokenRequest(tokenRequest); + OAuth2Request storedOAuth2Request = requestFactory.createStoredTokenRequest(tokenRequest); return new OAuth2Authentication(storedOAuth2Request, null); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAuthenticationKeyGenerator.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAuthenticationKeyGenerator.java index 6854b9226..6b35b09ba 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAuthenticationKeyGenerator.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAuthenticationKeyGenerator.java @@ -20,8 +20,8 @@ import java.util.Map; import org.springframework.security.oauth2.common.util.OAuth2Utils; +import org.springframework.security.oauth2.provider.BaseRequest; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.StoredOAuth2Request; /** * Basic key generator taking into account the client id, scope, reource ids and username (principal name) if they @@ -40,7 +40,7 @@ public class DefaultAuthenticationKeyGenerator implements AuthenticationKeyGener public String extractKey(OAuth2Authentication authentication) { Map values = new LinkedHashMap(); - StoredOAuth2Request authorizationRequest = authentication.getStoredRequest(); + BaseRequest authorizationRequest = authentication.getStoredRequest(); if (!authentication.isClientOnly()) { values.put(USERNAME, authentication.getName()); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java index 00cd6e99d..2e226453d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java @@ -28,10 +28,11 @@ import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; import org.springframework.security.oauth2.common.exceptions.InvalidScopeException; import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; +import org.springframework.security.oauth2.provider.BaseRequest; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.StoredOAuth2Request; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.util.Assert; @@ -169,7 +170,7 @@ public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) { private OAuth2Authentication createRefreshedAuthentication(OAuth2Authentication authentication, Set scope) { OAuth2Authentication narrowed = authentication; if (scope != null && !scope.isEmpty()) { - StoredOAuth2Request clientAuth = authentication.getStoredRequest(); + OAuth2Request clientAuth = authentication.getStoredRequest(); Set originalScope = clientAuth.getScope(); if (originalScope == null || !originalScope.containsAll(scope)) { throw new InvalidScopeException("Unable to narrow the scope of the client authentication to " + scope @@ -214,7 +215,7 @@ public String getClientId(String tokenValue) { if (authentication == null) { throw new InvalidTokenException("Invalid access token: " + tokenValue); } - StoredOAuth2Request clientAuth = authentication.getStoredRequest(); + BaseRequest clientAuth = authentication.getStoredRequest(); if (clientAuth == null) { throw new InvalidTokenException("Invalid access token (no client id): " + tokenValue); } @@ -268,7 +269,7 @@ private OAuth2AccessToken createAccessToken(OAuth2Authentication authentication, * @param authorizationRequest the current authorization request * @return the access token validity period in seconds */ - protected int getAccessTokenValiditySeconds(StoredOAuth2Request clientAuth) { + protected int getAccessTokenValiditySeconds(BaseRequest clientAuth) { if (clientDetailsService != null) { ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId()); Integer validity = client.getAccessTokenValiditySeconds(); @@ -284,7 +285,7 @@ protected int getAccessTokenValiditySeconds(StoredOAuth2Request clientAuth) { * @param authorizationRequest the current authorization request * @return the refresh token validity period in seconds */ - protected int getRefreshTokenValiditySeconds(StoredOAuth2Request clientAuth) { + protected int getRefreshTokenValiditySeconds(BaseRequest clientAuth) { if (clientDetailsService != null) { ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId()); Integer validity = client.getRefreshTokenValiditySeconds(); @@ -301,7 +302,7 @@ protected int getRefreshTokenValiditySeconds(StoredOAuth2Request clientAuth) { * @param authorizationRequest the current authorization request * @return boolean to indicate if refresh token is supported */ - protected boolean isSupportRefreshToken(StoredOAuth2Request clientAuth) { + protected boolean isSupportRefreshToken(BaseRequest clientAuth) { if (clientDetailsService != null) { ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId()); return client.getAuthorizedGrantTypes().contains("refresh_token"); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/vote/ScopeVoter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/vote/ScopeVoter.java index eba497400..2975e776e 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/vote/ScopeVoter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/vote/ScopeVoter.java @@ -25,9 +25,9 @@ import org.springframework.security.access.ConfigAttribute; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.common.exceptions.InsufficientScopeException; +import org.springframework.security.oauth2.provider.BaseRequest; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.AuthorizationRequest; -import org.springframework.security.oauth2.provider.StoredOAuth2Request; /** *

@@ -132,7 +132,7 @@ public int vote(Authentication authentication, Object object, Collection scopes = new HashSet(); scopes.addAll(Arrays.asList("read", "write")); - StoredOAuth2Request storedOAuth2Request = new StoredOAuth2Request(null, "client", null, false, scopes, null, null, null); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "client", null, false, scopes, null, null, null); this.authentication = new OAuth2Authentication(storedOAuth2Request, null); Mockito.when(tokenServices.loadAuthentication("FOO")).thenReturn(authentication); Authentication authentication = filter.attemptAuthentication(null, null); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/RequestTokenFactory.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/RequestTokenFactory.java new file mode 100644 index 000000000..7c3c93f0a --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/RequestTokenFactory.java @@ -0,0 +1,38 @@ +/* + * Cloud Foundry 2012.02.03 Beta + * Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved. + * + * This product is licensed to you under the Apache License, Version 2.0 (the "License"). + * You may not use this product except in compliance with the License. + * + * This product includes a number of subcomponents with + * separate copyright notices and license terms. Your use of these + * subcomponents is subject to the terms and conditions of the + * subcomponent's license, as noted in the LICENSE file. + */ + +package org.springframework.security.oauth2.provider; + +import java.io.Serializable; +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +import org.springframework.security.core.GrantedAuthority; + +/** + * Factory for tests to create OAuth2Request objects. + * + * @author Dave Syer + * + */ +public class RequestTokenFactory { + + public static OAuth2Request createOAuth2Request(Map requestParameters, String clientId, + Collection authorities, boolean approved, Set scope, + Set resourceIds, String redirectUri, Map extensionProperties) { + return new OAuth2Request(requestParameters, clientId, authorities, approved, scope, resourceIds, redirectUri, + extensionProperties); + } + +} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestOAuth2Authentication.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestOAuth2Authentication.java index 4895eb952..f79d18ddc 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestOAuth2Authentication.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestOAuth2Authentication.java @@ -13,7 +13,7 @@ public class TestOAuth2Authentication { - private StoredOAuth2Request request = new StoredOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null); + private OAuth2Request request = RequestTokenFactory.createOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null); private UsernamePasswordAuthenticationToken userAuthentication = new UsernamePasswordAuthenticationToken("foo", "bar", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"))); @@ -21,7 +21,7 @@ public class TestOAuth2Authentication { @Test @Rollback public void testIsAuthenticated() { - request = new StoredOAuth2Request(null, "id", null, true, Collections.singleton("read"), null, null, null); + request = RequestTokenFactory.createOAuth2Request(null, "id", null, true, Collections.singleton("read"), null, null, null); OAuth2Authentication authentication = new OAuth2Authentication(request, userAuthentication); assertTrue(authentication.isAuthenticated()); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenServicesUserApprovalHandler.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenServicesUserApprovalHandler.java index 578b57eb0..2cbca1c8c 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenServicesUserApprovalHandler.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenServicesUserApprovalHandler.java @@ -23,7 +23,7 @@ import org.springframework.security.oauth2.provider.DefaultOAuth2RequestFactory; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.AuthorizationRequest; -import org.springframework.security.oauth2.provider.StoredOAuth2Request; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.token.DefaultTokenServices; import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; @@ -68,7 +68,7 @@ public void testMemorizedApproval() { AuthorizationRequest authorizationRequest = new AuthorizationRequest(parameters, null, "foo", null, null, null, false, null, null, null); authorizationRequest.setApproved(false); TestAuthentication userAuthentication = new TestAuthentication("marissa", true); - StoredOAuth2Request storedOAuth2Request = requestFactory.createStoredAuthorizationRequest(authorizationRequest); + OAuth2Request storedOAuth2Request = requestFactory.createStoredAuthorizationRequest(authorizationRequest); tokenServices.createAccessToken(new OAuth2Authentication(storedOAuth2Request, userAuthentication)); assertTrue(handler.isApproved(authorizationRequest, userAuthentication)); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationManager.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationManager.java index 3cbeaf794..7355c1d7c 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationManager.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationManager.java @@ -21,7 +21,7 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.StoredOAuth2Request; +import org.springframework.security.oauth2.provider.RequestTokenFactory; import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices; import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken; @@ -37,7 +37,7 @@ public class TestOAuth2AuthenticationManager { private Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala"); - private OAuth2Authentication authentication = new OAuth2Authentication(new StoredOAuth2Request(null, "foo", null, false, null, null, null, null), userAuthentication); + private OAuth2Authentication authentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "foo", null, false, null, null, null, null), userAuthentication); { manager.setTokenServices(tokenServices); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationProcessingFilter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationProcessingFilter.java index 9a280dc07..ef4e23fb2 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationProcessingFilter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationProcessingFilter.java @@ -29,7 +29,7 @@ import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.StoredOAuth2Request; +import org.springframework.security.oauth2.provider.RequestTokenFactory; /** * @author Dave Syer @@ -43,7 +43,7 @@ public class TestOAuth2AuthenticationProcessingFilter { private Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala"); - private OAuth2Authentication authentication = new OAuth2Authentication(new StoredOAuth2Request(null, "foo", null, false, null, null, null, null), userAuthentication); + private OAuth2Authentication authentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "foo", null, false, null, null, null, null), userAuthentication); private FilterChain chain = Mockito.mock(FilterChain.class); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeServicesBase.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeServicesBase.java index 0f28ddf9d..4bdc48eea 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeServicesBase.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeServicesBase.java @@ -8,7 +8,8 @@ import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.StoredOAuth2Request; +import org.springframework.security.oauth2.provider.RequestTokenFactory; +import org.springframework.security.oauth2.provider.OAuth2Request; public abstract class TestAuthorizationCodeServicesBase { @@ -16,7 +17,7 @@ public abstract class TestAuthorizationCodeServicesBase { @Test public void testCreateAuthorizationCode() { - StoredOAuth2Request storedOAuth2Request = new StoredOAuth2Request(null, "id", null, false, null, null, null, null); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null); OAuth2Authentication expectedAuthentication = new OAuth2Authentication( storedOAuth2Request, new TestAuthentication( "test2", false)); @@ -30,7 +31,7 @@ storedOAuth2Request, new TestAuthentication( @Test public void testConsumeRemovesCode() { - StoredOAuth2Request storedOAuth2Request = new StoredOAuth2Request(null, "id", null, false, null, null, null, null); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null); OAuth2Authentication expectedAuthentication = new OAuth2Authentication( storedOAuth2Request, new TestAuthentication( "test2", false)); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeTokenGranter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeTokenGranter.java index ffeb0c612..98180aaba 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeTokenGranter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeTokenGranter.java @@ -31,12 +31,14 @@ import org.springframework.security.oauth2.common.exceptions.RedirectMismatchException; import org.springframework.security.oauth2.common.util.OAuth2Utils; import org.springframework.security.oauth2.provider.BaseClientDetails; +import org.springframework.security.oauth2.provider.BaseRequest; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.DefaultOAuth2RequestFactory; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; -import org.springframework.security.oauth2.provider.StoredOAuth2Request; +import org.springframework.security.oauth2.provider.RequestTokenFactory; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.token.DefaultTokenServices; import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; @@ -77,7 +79,7 @@ public void testAuthorizationCodeGrant() { parameters.clear(); parameters.put(OAuth2Utils.CLIENT_ID, "foo"); parameters.put(OAuth2Utils.SCOPE, "scope"); - StoredOAuth2Request storedOAuth2Request = new StoredOAuth2Request(parameters, "foo", null, true, Collections.singleton("scope"), null, null, null); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(parameters, "foo", null, true, Collections.singleton("scope"), null, null, null); String code = authorizationCodeServices.createAuthorizationCode(new OAuth2Authentication( storedOAuth2Request, userAuthentication)); @@ -99,7 +101,7 @@ public void testAuthorizationParametersPreserved() { parameters.put("foo", "bar"); parameters.put(OAuth2Utils.CLIENT_ID, "foo"); parameters.put(OAuth2Utils.SCOPE, "scope"); - StoredOAuth2Request storedOAuth2Request = new StoredOAuth2Request(parameters, "foo", null, true, Collections.singleton("scope"), null, null, null); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(parameters, "foo", null, true, Collections.singleton("scope"), null, null, null); Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); @@ -112,7 +114,7 @@ public void testAuthorizationParametersPreserved() { AuthorizationCodeTokenGranter granter = new AuthorizationCodeTokenGranter(providerTokenServices, authorizationCodeServices, clientDetailsService, requestFactory); OAuth2AccessToken token = granter.grant("authorization_code", tokenRequest); - StoredOAuth2Request finalRequest = providerTokenServices.loadAuthentication(token.getValue()) + BaseRequest finalRequest = providerTokenServices.loadAuthentication(token.getValue()) .getStoredRequest(); assertEquals(code, finalRequest.getRequestParameters().get("code")); assertEquals("bar", finalRequest.getRequestParameters().get("foo")); @@ -124,7 +126,7 @@ public void testAuthorizationRequestPreserved() { parameters.clear(); parameters.put(OAuth2Utils.CLIENT_ID, "foo"); parameters.put(OAuth2Utils.SCOPE, "read"); - StoredOAuth2Request storedOAuth2Request = new StoredOAuth2Request(parameters, "foo", null, true, Collections.singleton("read"), Collections.singleton("resource"), null, null); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(parameters, "foo", null, true, Collections.singleton("read"), Collections.singleton("resource"), null, null); Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); @@ -137,7 +139,7 @@ public void testAuthorizationRequestPreserved() { AuthorizationCodeTokenGranter granter = new AuthorizationCodeTokenGranter(providerTokenServices, authorizationCodeServices, clientDetailsService, requestFactory); OAuth2AccessToken token = granter.grant("authorization_code", tokenRequest); - StoredOAuth2Request finalRequest = providerTokenServices.loadAuthentication(token.getValue()) + OAuth2Request finalRequest = providerTokenServices.loadAuthentication(token.getValue()) .getStoredRequest(); assertEquals("[read]", finalRequest.getScope().toString()); assertEquals("[resource]", finalRequest.getResourceIds().toString()); @@ -150,7 +152,7 @@ public void testAuthorizationCodeGrantWithNoClientAuthorities() { parameters.clear(); parameters.put(OAuth2Utils.CLIENT_ID, "foo"); parameters.put(OAuth2Utils.SCOPE, "scope"); - StoredOAuth2Request storedOAuth2Request = new StoredOAuth2Request(parameters, "foo", Collections. emptySet(), true, Collections.singleton("scope"), null, null, null); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(parameters, "foo", Collections. emptySet(), true, Collections.singleton("scope"), null, null, null); Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); @@ -175,7 +177,7 @@ public void testAuthorizationRedirectMismatch() { parameters.clear(); parameters.put(OAuth2Utils.REDIRECT_URI, "https://redirectme/"); parameters.put(OAuth2Utils.CLIENT_ID, "foo"); - StoredOAuth2Request storedOAuth2Request = new StoredOAuth2Request(parameters, "foo", null, true, null, null, "https://redirectme/", null); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(parameters, "foo", null, true, null, null, "https://redirectme/", null); Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2MethodSecurityExpressionHandler.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2MethodSecurityExpressionHandler.java index 2cae80e65..0f3e2d8a6 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2MethodSecurityExpressionHandler.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2MethodSecurityExpressionHandler.java @@ -30,7 +30,8 @@ import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.AuthorizationRequest; -import org.springframework.security.oauth2.provider.StoredOAuth2Request; +import org.springframework.security.oauth2.provider.RequestTokenFactory; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.util.SimpleMethodInvocation; import org.springframework.util.ReflectionUtils; @@ -50,8 +51,8 @@ public void testOauthClient() throws Exception { .setResourceIdsAndAuthoritiesFromClientDetails(new BaseClientDetails("foo", "", "", "client_credentials", "ROLE_CLIENT")); Authentication userAuthentication = null; - StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(request.getRequestParameters(), request.getClientId(), request.getAuthorities(), - request.isApproved(), request.getScope(), request.getResourceIds(), request.getRedirectUri(), request.getExtensionProperties()); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(request.getRequestParameters(), request.getClientId(), request.getAuthorities(), request.isApproved(), request.getScope(), request.getResourceIds(), + request.getRedirectUri(), request.getExtensionProperties()); OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); MethodInvocation invocation = new SimpleMethodInvocation(this, ReflectionUtils.findMethod(getClass(), @@ -65,7 +66,7 @@ public void testOauthClient() throws Exception { @Test public void testScopes() throws Exception { - StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); @@ -106,7 +107,7 @@ public void testReEvaluationWithDifferentRoot() throws Exception { EvaluationContext context = handler.createEvaluationContext(clientAuthentication, invocation); assertFalse((Boolean) expression.getValue(context)); - StoredOAuth2Request storedOAuth2Request = new StoredOAuth2Request(null, "foo", null, true, Collections.singleton("read"), null, null, null); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "foo", null, true, Collections.singleton("read"), null, null, null); OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(storedOAuth2Request, null); EvaluationContext anotherContext = handler.createEvaluationContext(oAuth2Authentication, invocation); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2SecurityExpressionMethods.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2SecurityExpressionMethods.java index b89481440..574dd6fa4 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2SecurityExpressionMethods.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2SecurityExpressionMethods.java @@ -29,7 +29,8 @@ import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.AuthorizationRequest; -import org.springframework.security.oauth2.provider.StoredOAuth2Request; +import org.springframework.security.oauth2.provider.RequestTokenFactory; +import org.springframework.security.oauth2.provider.OAuth2Request; /** * @author Dave Syer @@ -45,8 +46,8 @@ public void testOauthClient() throws Exception { .setResourceIdsAndAuthoritiesFromClientDetails(new BaseClientDetails("foo", "", "", "client_credentials", "ROLE_CLIENT")); Authentication userAuthentication = null; - StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(request.getRequestParameters(), request.getClientId(), request.getAuthorities(), - request.isApproved(), request.getScope(), request.getResourceIds(), request.getRedirectUri(), request.getExtensionProperties()); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(request.getRequestParameters(), request.getClientId(), request.getAuthorities(), request.isApproved(), request.getScope(), request.getResourceIds(), + request.getRedirectUri(), request.getExtensionProperties()); OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); assertTrue(new OAuth2SecurityExpressionMethods(oAuth2Authentication, true).clientHasAnyRole("ROLE_CLIENT")); @@ -54,7 +55,7 @@ public void testOauthClient() throws Exception { @Test public void testScopes() throws Exception { - StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); @@ -64,7 +65,7 @@ public void testScopes() throws Exception { @Test public void testScopesFalse() throws Exception { - StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); @@ -74,7 +75,7 @@ public void testScopesFalse() throws Exception { @Test(expected = AccessDeniedException.class) public void testScopesWithException() throws Exception { - StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); @@ -83,7 +84,7 @@ public void testScopesWithException() throws Exception { @Test(expected = AccessDeniedException.class) public void testInsufficientScope() throws Exception { - StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); @@ -93,7 +94,7 @@ public void testInsufficientScope() throws Exception { @Test public void testSufficientScope() throws Exception { - StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); @@ -103,7 +104,7 @@ public void testSufficientScope() throws Exception { @Test public void testSufficientScopeWithNoPreviousScopeDecision() throws Exception { - StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(null, "foo", null, true, Collections.singleton("read"), null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, true, Collections.singleton("read"), null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); @@ -119,7 +120,7 @@ public void testNonOauthClient() throws Exception { @Test public void testClientOnly() throws Exception { - StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(null, "foo", null, true, Collections.singleton("read"), null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, true, Collections.singleton("read"), null, null, null); Authentication userAuthentication = new UsernamePasswordAuthenticationToken("foo", "bar", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"))); @@ -130,7 +131,7 @@ public void testClientOnly() throws Exception { @Test public void testOAuthUser() throws Exception { - StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(null, "foo", null, true, Collections.singleton("read"), null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, true, Collections.singleton("read"), null, null, null); Authentication userAuthentication = new UsernamePasswordAuthenticationToken("foo", "bar", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"))); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2WebSecurityExpressionHandler.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2WebSecurityExpressionHandler.java index 248b1253b..b3d527794 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2WebSecurityExpressionHandler.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2WebSecurityExpressionHandler.java @@ -28,7 +28,8 @@ import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.AuthorizationRequest; -import org.springframework.security.oauth2.provider.StoredOAuth2Request; +import org.springframework.security.oauth2.provider.RequestTokenFactory; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.web.FilterInvocation; /** @@ -44,8 +45,8 @@ public void testOauthClient() throws Exception { AuthorizationRequest request = new AuthorizationRequest("foo", Collections.singleton("read")); request.setResourceIdsAndAuthoritiesFromClientDetails(new BaseClientDetails("foo", "", "", "client_credentials", "ROLE_CLIENT")); - StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(request.getRequestParameters(), request.getClientId(), request.getAuthorities(), - request.isApproved(), request.getScope(), request.getResourceIds(), request.getRedirectUri(), request.getExtensionProperties()); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(request.getRequestParameters(), request.getClientId(), request.getAuthorities(), request.isApproved(), request.getScope(), request.getResourceIds(), + request.getRedirectUri(), request.getExtensionProperties()); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); @@ -56,7 +57,7 @@ public void testOauthClient() throws Exception { @Test public void testScopes() throws Exception { - StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); FilterInvocation invocation = new FilterInvocation("/foo", "GET"); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractTestDefaultTokenServices.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractTestDefaultTokenServices.java index 6620110e8..acb469710 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractTestDefaultTokenServices.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractTestDefaultTokenServices.java @@ -22,7 +22,7 @@ import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.StoredOAuth2Request; +import org.springframework.security.oauth2.provider.RequestTokenFactory; import org.springframework.security.oauth2.provider.TokenRequest; /** @@ -171,11 +171,11 @@ public void testOneAccessTokenPerAuthentication() throws Exception { @Test public void testOneAccessTokenPerUniqueAuthentication() throws Exception { getTokenServices().createAccessToken( - new OAuth2Authentication(new StoredOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null), + new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null), new TestAuthentication("test2", false))); assertEquals(1, getAccessTokenCount()); getTokenServices().createAccessToken( - new OAuth2Authentication(new StoredOAuth2Request(null, "id", null, false, Collections.singleton("write"), null, null, null), + new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, Collections.singleton("write"), null, null, null), new TestAuthentication("test2", false))); assertEquals(2, getAccessTokenCount()); } @@ -207,8 +207,7 @@ public void testNotReuseRefreshTokenMaintainsState() throws Exception { private OAuth2Authentication createAuthentication() { - return new OAuth2Authentication(new StoredOAuth2Request(null, "id", null, false, - Collections.singleton("read"), null, null, null), new TestAuthentication("test2", false)); + return new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null), new TestAuthentication("test2", false)); } protected abstract int getAccessTokenCount(); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestDefaultTokenServicesWithInMemory.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestDefaultTokenServicesWithInMemory.java index e33b82458..efc085306 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestDefaultTokenServicesWithInMemory.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestDefaultTokenServicesWithInMemory.java @@ -23,7 +23,7 @@ import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.StoredOAuth2Request; +import org.springframework.security.oauth2.provider.RequestTokenFactory; import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.test.util.ReflectionTestUtils; @@ -41,8 +41,7 @@ public class TestDefaultTokenServicesWithInMemory extends AbstractTestDefaultTok @Test public void testExpiredToken() throws Exception { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new StoredOAuth2Request(null, "id", null, false, - Collections.singleton("read"), null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null), new TestAuthentication("test2", false)); DefaultOAuth2AccessToken firstAccessToken = (DefaultOAuth2AccessToken) getTokenServices().createAccessToken( expectedAuthentication); // Make it expire (and rely on mutable state in volatile token store) @@ -54,8 +53,7 @@ public void testExpiredToken() throws Exception { @Test public void testExpiredRefreshToken() throws Exception { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new StoredOAuth2Request(null, "id", null, false, - Collections.singleton("read"), null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null), new TestAuthentication("test2", false)); DefaultOAuth2AccessToken firstAccessToken = (DefaultOAuth2AccessToken) getTokenServices().createAccessToken( expectedAuthentication); assertNotNull(firstAccessToken.getRefreshToken()); @@ -71,8 +69,7 @@ public void testExpiredRefreshToken() throws Exception { @Test public void testExpiredRefreshTokenIsRenewedWithNewAccessToken() throws Exception { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new StoredOAuth2Request(null, "id", null, false, - Collections.singleton("read"), null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null), new TestAuthentication("test2", false)); DefaultOAuth2AccessToken firstAccessToken = (DefaultOAuth2AccessToken) getTokenServices().createAccessToken( expectedAuthentication); assertNotNull(firstAccessToken.getRefreshToken()); @@ -99,8 +96,7 @@ public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exceptio return client; } }); - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new StoredOAuth2Request(null, "id", null, false, - Collections.singleton("read"), null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null), new TestAuthentication("test2", false)); DefaultOAuth2AccessToken firstAccessToken = (DefaultOAuth2AccessToken) getTokenServices().createAccessToken( expectedAuthentication); OAuth2RefreshToken expectedExpiringRefreshToken = firstAccessToken.getRefreshToken(); @@ -131,8 +127,7 @@ public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exceptio return client; } }); - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new StoredOAuth2Request(null, "id", null, false, - Collections.singleton("read"), null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null), new TestAuthentication("test2", false)); DefaultOAuth2AccessToken token = (DefaultOAuth2AccessToken) getTokenServices().createAccessToken( expectedAuthentication); assertNull(token.getRefreshToken()); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestInMemoryTokenStore.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestInMemoryTokenStore.java index 6f04ff67f..dc5664395 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestInMemoryTokenStore.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestInMemoryTokenStore.java @@ -8,7 +8,7 @@ import org.junit.Test; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.StoredOAuth2Request; +import org.springframework.security.oauth2.provider.RequestTokenFactory; /** * @author Dave Syer @@ -31,8 +31,7 @@ public void createStore() { @Test public void testTokenCountConsistency() throws Exception { for (int i = 0; i <= 10; i++) { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new StoredOAuth2Request(null, "id" + i, - null, false, null, null, null, null), new TestAuthentication("test", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id" + i, null, false, null, null, null, null), new TestAuthentication("test", false)); DefaultOAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken" + i); expectedOAuth2AccessToken.setExpiration(new Date(System.currentTimeMillis() - 1000)); if (i > 1) { @@ -44,8 +43,7 @@ public void testTokenCountConsistency() throws Exception { @Test public void testTokenCountConsistentWithExpiryQueue() throws Exception { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new StoredOAuth2Request(null, "id", - null, false, null, null, null, null), new TestAuthentication("test", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null), new TestAuthentication("test", false)); DefaultOAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); expectedOAuth2AccessToken.setExpiration(new Date(System.currentTimeMillis()+10000)); for (int i = 0; i <= 10; i++) { @@ -58,8 +56,7 @@ public void testTokenCountConsistentWithExpiryQueue() throws Exception { public void testAutoFlush() throws Exception { getTokenStore().setFlushInterval(3); for (int i = 0; i <= 10; i++) { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new StoredOAuth2Request(null, "id" + i, - null, false, null, null, null, null), new TestAuthentication("test", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id" + i, null, false, null, null, null, null), new TestAuthentication("test", false)); DefaultOAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken" + i); expectedOAuth2AccessToken.setExpiration(new Date(System.currentTimeMillis() - 1000)); if (i > 2) { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestTokenStoreBase.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestTokenStoreBase.java index 8291faf5a..ef17f9c2e 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestTokenStoreBase.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestTokenStoreBase.java @@ -28,7 +28,8 @@ 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.StoredOAuth2Request; +import org.springframework.security.oauth2.provider.RequestTokenFactory; +import org.springframework.security.oauth2.provider.OAuth2Request; /** * @author Dave Syer @@ -45,8 +46,7 @@ public void testReadingAuthenticationForTokenThatDoesNotExist() { @Test public void testStoreAccessToken() { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new StoredOAuth2Request(null, "id", - null, false, null, null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null), new TestAuthentication("test2", false)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); @@ -61,13 +61,13 @@ public void testStoreAccessToken() { @Test public void testRetrieveAccessToken() { //Test approved request - StoredOAuth2Request storedOAuth2Request = new StoredOAuth2Request(null, "id", null, true, null, null, null, null); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "id", null, true, null, null, null, null); OAuth2Authentication authentication = new OAuth2Authentication(storedOAuth2Request, new TestAuthentication("test2", true)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, authentication); //Test unapproved request - storedOAuth2Request = new StoredOAuth2Request(null, "id", null, false, null, null, null, null); + storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null); authentication = new OAuth2Authentication(storedOAuth2Request, new TestAuthentication("test2", true)); OAuth2AccessToken actualOAuth2AccessToken = getTokenStore().getAccessToken(authentication); assertEquals(expectedOAuth2AccessToken, actualOAuth2AccessToken); @@ -84,7 +84,7 @@ public void testRetrieveAccessToken() { @Test public void testFindAccessTokensByUserName() { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new StoredOAuth2Request(null, "id", null, false, null, null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null), new TestAuthentication("test2", false)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); @@ -94,7 +94,7 @@ public void testFindAccessTokensByUserName() { @Test public void testFindAccessTokensByClientId() { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new StoredOAuth2Request(null, "id", null, false, null, null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null), new TestAuthentication("test2", false)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); @@ -109,7 +109,7 @@ public void testReadingAccessTokenForTokenThatDoesNotExist() { @Test public void testRefreshTokenIsNotStoredDuringAccessToken() { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new StoredOAuth2Request(null, "id", null, false, null, null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null), new TestAuthentication("test2", false)); DefaultOAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); expectedOAuth2AccessToken.setRefreshToken(new DefaultOAuth2RefreshToken("refreshToken")); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); @@ -124,7 +124,7 @@ public void testRefreshTokenIsNotStoredDuringAccessToken() { public void testStoreRefreshToken() { DefaultOAuth2RefreshToken expectedExpiringRefreshToken = new DefaultExpiringOAuth2RefreshToken("testToken", new Date()); - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new StoredOAuth2Request(null, "id", null, false, null, null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null), new TestAuthentication("test2", false)); getTokenStore().storeRefreshToken(expectedExpiringRefreshToken, expectedAuthentication); OAuth2RefreshToken actualExpiringRefreshToken = getTokenStore().readRefreshToken("testToken"); @@ -143,7 +143,7 @@ public void testReadingRefreshTokenForTokenThatDoesNotExist() { @Test public void testGetAccessTokenForDeletedUser() throws Exception { //Test approved request - StoredOAuth2Request storedOAuth2Request = new StoredOAuth2Request(null, "id", null, true, null, null, null, null); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "id", null, true, null, null, null, null); OAuth2Authentication expectedAuthentication = new OAuth2Authentication(storedOAuth2Request, new TestAuthentication("test", true)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); @@ -151,7 +151,7 @@ public void testGetAccessTokenForDeletedUser() throws Exception { assertEquals(expectedAuthentication, getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue())); //Test unapproved request - storedOAuth2Request = new StoredOAuth2Request(null, "id", null, false, null, null, null, null); + storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null); OAuth2Authentication anotherAuthentication = new OAuth2Authentication(storedOAuth2Request, new TestAuthentication("test", true)); assertEquals(expectedOAuth2AccessToken, getTokenStore().getAccessToken(anotherAuthentication)); // The generated key for the authentication is the same as before, but the two auths are not equal. This could @@ -166,7 +166,7 @@ public void testGetAccessTokenForDeletedUser() throws Exception { public void testRemoveRefreshToken() { OAuth2RefreshToken expectedExpiringRefreshToken = new DefaultExpiringOAuth2RefreshToken("testToken", new Date()); - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new StoredOAuth2Request(null, "id", null, false, null, null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null), new TestAuthentication("test2", false)); getTokenStore().storeRefreshToken(expectedExpiringRefreshToken, expectedAuthentication); getTokenStore().removeRefreshToken(expectedExpiringRefreshToken); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/TestScopeVoter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/TestScopeVoter.java index 460f49d9b..f31400591 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/TestScopeVoter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/TestScopeVoter.java @@ -28,7 +28,8 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.StoredOAuth2Request; +import org.springframework.security.oauth2.provider.RequestTokenFactory; +import org.springframework.security.oauth2.provider.OAuth2Request; /** * @author Dave Syer @@ -50,7 +51,7 @@ public void testAbstainIfNotOAuth2() throws Exception { @Test public void testDenyIfOAuth2AndExplictlyDenied() throws Exception { - StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); assertEquals( @@ -61,7 +62,7 @@ public void testDenyIfOAuth2AndExplictlyDenied() throws Exception { @Test public void testAccessGrantedIfScopesPresent() throws Exception { - StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null ,null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); assertEquals( @@ -73,7 +74,7 @@ public void testAccessGrantedIfScopesPresent() throws Exception { @Test public void testAccessGrantedIfScopesPresentWithPrefix() throws Exception { voter.setScopePrefix("scope="); - StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); assertEquals( @@ -84,7 +85,7 @@ public void testAccessGrantedIfScopesPresentWithPrefix() throws Exception { @Test public void testAccessDeniedIfWrongScopesPresent() throws Exception { - StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); voter.setThrowException(false); @@ -96,7 +97,7 @@ public void testAccessDeniedIfWrongScopesPresent() throws Exception { @Test(expected = AccessDeniedException.class) public void testExceptionThrownIfWrongScopesPresent() throws Exception { - StoredOAuth2Request clientAuthentication = new StoredOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); assertEquals( From d6c87049b14163b58907171422ddaca90316e460 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 9 Jul 2013 06:52:02 +0100 Subject: [PATCH 057/831] Tidy names and interfaces --- .../security/oauth2/common/util/OAuth2Utils.java | 1 + .../security/oauth2/provider/BaseRequest.java | 3 ++- .../provider/DefaultOAuth2RequestFactory.java | 1 + .../oauth2/provider/OAuth2Authentication.java | 2 +- .../security/oauth2/provider/OAuth2Request.java | 6 +++--- .../security/oauth2/provider/TokenRequest.java | 4 ++-- .../OAuth2AuthenticationManager.java | 2 +- .../code/AuthorizationCodeTokenGranter.java | 2 +- .../oauth2/provider/endpoint/TokenEndpoint.java | 2 +- .../provider/expression/OAuth2ExpressionUtils.java | 4 ++-- .../token/DefaultAuthenticationKeyGenerator.java | 2 +- .../provider/token/DefaultTokenServices.java | 14 +++++++------- .../oauth2/provider/token/InMemoryTokenStore.java | 4 ++-- .../oauth2/provider/token/JdbcTokenStore.java | 2 +- .../security/oauth2/provider/vote/ScopeVoter.java | 2 +- .../code/TestAuthorizationCodeTokenGranter.java | 4 ++-- .../token/AbstractTestDefaultTokenServices.java | 2 +- .../oauth2/provider/token/TestTokenStoreBase.java | 4 ++-- 18 files changed, 32 insertions(+), 29 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/OAuth2Utils.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/OAuth2Utils.java index 57d53d41b..22be9d7b6 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/OAuth2Utils.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/OAuth2Utils.java @@ -31,6 +31,7 @@ */ public abstract class OAuth2Utils { + // FIXME: is this the right place for constants? /** * Constants to use while parsing parameter maps for OAuth2 requests */ diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java index d538a42f7..105327e5f 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java @@ -14,6 +14,7 @@ package org.springframework.security.oauth2.provider; import java.io.Serializable; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -71,7 +72,7 @@ public Set getScope() { return scope; } - public void setScope(Set scope) { + public void setScope(Collection scope) { if (scope != null && scope.size() == 1) { String value = scope.iterator().next(); /* diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestFactory.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestFactory.java index 17977fee7..ad8d7e05f 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestFactory.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestFactory.java @@ -84,6 +84,7 @@ public TokenRequest createTokenRequest(Map requestParameters) { return tokenRequest; } + // FIXME: "implicit" is hard coded? public TokenRequest createTokenRequestFromAuthorizationRequest(AuthorizationRequest authorizationRequest) { TokenRequest tokenRequest = new TokenRequest(authorizationRequest.getRequestParameters(), authorizationRequest.getClientId(), authorizationRequest.getScope(), "implicit"); return tokenRequest; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Authentication.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Authentication.java index ed273d43d..28afb593c 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Authentication.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Authentication.java @@ -53,7 +53,7 @@ public boolean isClientOnly() { * * @return The client authentication. */ - public OAuth2Request getStoredRequest() { + public OAuth2Request getOAuth2Request() { return storedRequest; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java index 4f5c657eb..20b3b2424 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java @@ -28,7 +28,7 @@ public class OAuth2Request extends BaseRequest implements Serializable { /** * Resolved granted authorities for this request. May change during request processing. */ - private Collection authorities = new HashSet(); + private Collection authorities = new HashSet(); /** * Whether the request has been approved by the end user (or other process). This will be altered by the User @@ -90,11 +90,11 @@ public void setRedirectUri(String redirectUri) { this.redirectUri = redirectUri; } - public Collection getAuthorities() { + public Collection getAuthorities() { return authorities; } - public void setAuthorities(Collection authorities) { + public void setAuthorities(Collection authorities) { this.authorities = authorities; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java index f0fc07be8..049b6df89 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java @@ -1,9 +1,9 @@ package org.springframework.security.oauth2.provider; import java.io.Serializable; +import java.util.Collection; import java.util.HashMap; import java.util.Map; -import java.util.Set; import org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint; import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint; @@ -40,7 +40,7 @@ protected TokenRequest() { * @param scope * @param grantType */ - public TokenRequest(Map requestParameters, String clientId, Set scope, String grantType) { + public TokenRequest(Map requestParameters, String clientId, Collection scope, String grantType) { super(clientId); setRequestParameters(requestParameters); setScope(scope); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java index 78b4d18cc..39b628e35 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java @@ -72,7 +72,7 @@ public Authentication authenticate(Authentication authentication) throws Authent throw new InvalidTokenException("Invalid token: " + token); } - Collection resourceIds = auth.getStoredRequest().getResourceIds(); + Collection resourceIds = auth.getOAuth2Request().getResourceIds(); if (resourceId != null && resourceIds != null && !resourceIds.isEmpty() && !resourceIds.contains(resourceId)) { throw new OAuth2AccessDeniedException("Invalid token does not contain resource id (" + resourceId + ")"); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranter.java index 2ceba16ca..6d07bd64f 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranter.java @@ -67,7 +67,7 @@ protected OAuth2Authentication getOAuth2Authentication(TokenRequest tokenRequest throw new InvalidGrantException("Invalid authorization code: " + authorizationCode); } - OAuth2Request pendingOAuth2Request = storedAuth.getStoredRequest(); + OAuth2Request pendingOAuth2Request = storedAuth.getOAuth2Request(); // https://jira.springsource.org/browse/SECOAUTH-333 // This might be null, if the authorization was done without the redirect_uri parameter String redirectUriApprovalParameter = pendingOAuth2Request.getRequestParameters().get( diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java index a65e3547d..ff899af93 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java @@ -126,7 +126,7 @@ protected String getClientId(Principal principal) { String clientId = client.getName(); if (client instanceof OAuth2Authentication) { // Might be a client and user combined authentication - clientId = ((OAuth2Authentication) client).getStoredRequest().getClientId(); + clientId = ((OAuth2Authentication) client).getOAuth2Request().getClientId(); } return clientId; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionUtils.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionUtils.java index add97dcb3..7e2d3b5c5 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionUtils.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionUtils.java @@ -30,7 +30,7 @@ public abstract class OAuth2ExpressionUtils { public static boolean clientHasAnyRole(Authentication authentication, String... roles) { if (authentication instanceof OAuth2Authentication) { - OAuth2Request clientAuthentication = ((OAuth2Authentication) authentication).getStoredRequest(); + OAuth2Request clientAuthentication = ((OAuth2Authentication) authentication).getOAuth2Request(); Collection clientAuthorities = clientAuthentication.getAuthorities(); if (clientAuthorities != null) { Set roleSet = AuthorityUtils.authorityListToSet(clientAuthorities); @@ -75,7 +75,7 @@ public static boolean isOAuthUserAuth(Authentication authentication) { public static boolean hasAnyScope(Authentication authentication, String[] scopes) { if (authentication instanceof OAuth2Authentication) { - BaseRequest clientAuthentication = ((OAuth2Authentication) authentication).getStoredRequest(); + BaseRequest clientAuthentication = ((OAuth2Authentication) authentication).getOAuth2Request(); Collection assigned = clientAuthentication.getScope(); if (assigned != null) { for (String scope : scopes) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAuthenticationKeyGenerator.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAuthenticationKeyGenerator.java index 6b35b09ba..639dd0dea 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAuthenticationKeyGenerator.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAuthenticationKeyGenerator.java @@ -40,7 +40,7 @@ public class DefaultAuthenticationKeyGenerator implements AuthenticationKeyGener public String extractKey(OAuth2Authentication authentication) { Map values = new LinkedHashMap(); - BaseRequest authorizationRequest = authentication.getStoredRequest(); + BaseRequest authorizationRequest = authentication.getOAuth2Request(); if (!authentication.isClientOnly()) { values.put(USERNAME, authentication.getName()); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java index 2e226453d..e1355adc0 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java @@ -127,7 +127,7 @@ public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, TokenReque } OAuth2Authentication authentication = tokenStore.readAuthenticationForRefreshToken(refreshToken); - String clientId = authentication.getStoredRequest().getClientId(); + String clientId = authentication.getOAuth2Request().getClientId(); if (clientId == null || !clientId.equals(tokenRequest.getClientId())) { throw new InvalidGrantException("Wrong client for this refresh token: " + refreshTokenValue); } @@ -170,7 +170,7 @@ public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) { private OAuth2Authentication createRefreshedAuthentication(OAuth2Authentication authentication, Set scope) { OAuth2Authentication narrowed = authentication; if (scope != null && !scope.isEmpty()) { - OAuth2Request clientAuth = authentication.getStoredRequest(); + OAuth2Request clientAuth = authentication.getOAuth2Request(); Set originalScope = clientAuth.getScope(); if (originalScope == null || !originalScope.containsAll(scope)) { throw new InvalidScopeException("Unable to narrow the scope of the client authentication to " + scope @@ -215,7 +215,7 @@ public String getClientId(String tokenValue) { if (authentication == null) { throw new InvalidTokenException("Invalid access token: " + tokenValue); } - BaseRequest clientAuth = authentication.getStoredRequest(); + BaseRequest clientAuth = authentication.getOAuth2Request(); if (clientAuth == null) { throw new InvalidTokenException("Invalid access token (no client id): " + tokenValue); } @@ -243,10 +243,10 @@ public boolean revokeToken(String tokenValue) { } private ExpiringOAuth2RefreshToken createRefreshToken(OAuth2Authentication authentication) { - if (!isSupportRefreshToken(authentication.getStoredRequest())) { + if (!isSupportRefreshToken(authentication.getOAuth2Request())) { return null; } - int validitySeconds = getRefreshTokenValiditySeconds(authentication.getStoredRequest()); + int validitySeconds = getRefreshTokenValiditySeconds(authentication.getOAuth2Request()); ExpiringOAuth2RefreshToken refreshToken = new DefaultExpiringOAuth2RefreshToken(UUID.randomUUID().toString(), new Date(System.currentTimeMillis() + (validitySeconds * 1000L))); return refreshToken; @@ -254,12 +254,12 @@ private ExpiringOAuth2RefreshToken createRefreshToken(OAuth2Authentication authe private OAuth2AccessToken createAccessToken(OAuth2Authentication authentication, OAuth2RefreshToken refreshToken) { DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(UUID.randomUUID().toString()); - int validitySeconds = getAccessTokenValiditySeconds(authentication.getStoredRequest()); + int validitySeconds = getAccessTokenValiditySeconds(authentication.getOAuth2Request()); if (validitySeconds > 0) { token.setExpiration(new Date(System.currentTimeMillis() + (validitySeconds * 1000L))); } token.setRefreshToken(refreshToken); - token.setScope(authentication.getStoredRequest().getScope()); + token.setScope(authentication.getOAuth2Request().getScope()); return accessTokenEnhancer != null ? accessTokenEnhancer.enhance(token, authentication) : token; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStore.java index 8dec551c7..c278ee9f9 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStore.java @@ -150,7 +150,7 @@ public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authe if (!authentication.isClientOnly()) { addToCollection(this.userNameToAccessTokenStore, authentication.getName(), token); } - addToCollection(this.clientIdToAccessTokenStore, authentication.getStoredRequest().getClientId(), token); + addToCollection(this.clientIdToAccessTokenStore, authentication.getOAuth2Request().getClientId(), token); if (token.getExpiration() != null) { TokenExpiry expiry = new TokenExpiry(token.getValue(), token.getExpiration()); // Remove existing expiry for this token if present @@ -198,7 +198,7 @@ public void removeAccessToken(String tokenValue) { if (tokens != null) { tokens.remove(removed); } - String clientId = authentication.getStoredRequest().getClientId(); + String clientId = authentication.getOAuth2Request().getClientId(); tokens = this.clientIdToAccessTokenStore.get(clientId); if (tokens != null) { tokens.remove(removed); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JdbcTokenStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JdbcTokenStore.java index bc2695ae0..b1dc43c26 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JdbcTokenStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JdbcTokenStore.java @@ -137,7 +137,7 @@ public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authe jdbcTemplate.update(insertAccessTokenSql, new Object[] { extractTokenKey(token.getValue()), new SqlLobValue(serializeAccessToken(token)), authenticationKeyGenerator.extractKey(authentication), authentication.isClientOnly() ? null : authentication.getName(), - authentication.getStoredRequest().getClientId(), + authentication.getOAuth2Request().getClientId(), new SqlLobValue(serializeAuthentication(authentication)), extractTokenKey(refreshToken) }, new int[] { Types.VARCHAR, Types.BLOB, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.BLOB, Types.VARCHAR }); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/vote/ScopeVoter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/vote/ScopeVoter.java index 2975e776e..f6881b3b9 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/vote/ScopeVoter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/vote/ScopeVoter.java @@ -132,7 +132,7 @@ public int vote(Authentication authentication, Object object, Collection Date: Wed, 10 Jul 2013 09:55:44 +0100 Subject: [PATCH 058/831] Tidy up a few things related to *Request - OAuth2Request is now immutable from the point of view of clients (it still has setters but they are protected) - OAuth2RequestFactory has overloaded methods (instead of method names that refect the parameters) - OAuth2RequestFactory.createTokenRequest for the implicit grant explicitly requires the grant type to be provided - Cleaned up some copyright notices - Removed or fixed some TODO/FIXME comments --- .../TestAuthorizationCodeProvider.java | 1 - .../oauth2/client/OAuth2RestOperations.java | 19 +++-- .../UserRedirectRequiredException.java | 1 - .../oauth2/common/util/OAuth2Utils.java | 21 ++++- .../oauth2/provider/AuthorizationRequest.java | 78 ++++++++++++------- .../security/oauth2/provider/BaseRequest.java | 19 +++-- .../provider/DefaultOAuth2RequestFactory.java | 9 +-- .../oauth2/provider/OAuth2Request.java | 42 +++++----- .../oauth2/provider/OAuth2RequestFactory.java | 41 +++++----- .../TokenServicesUserApprovalHandler.java | 2 +- .../endpoint/AuthorizationEndpoint.java | 4 +- .../TokenEndpointAuthenticationFilter.java | 3 +- .../implicit/ImplicitTokenGranter.java | 2 +- .../provider/token/AbstractTokenGranter.java | 5 +- .../token/TestOAuth2AccessTokenSupport.java | 19 +++-- .../provider/TestOAuth2Authentication.java | 23 +++++- .../TestTokenServicesUserApprovalHandler.java | 2 +- .../code/TestAuthorizationRequestHolder.java | 41 ---------- ...OAuth2MethodSecurityExpressionHandler.java | 2 +- .../TestOAuth2SecurityExpressionMethods.java | 2 +- ...estOAuth2WebSecurityExpressionHandler.java | 2 +- 21 files changed, 180 insertions(+), 158 deletions(-) delete mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationRequestHolder.java diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationCodeProvider.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationCodeProvider.java index a24cb953a..b48408993 100755 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationCodeProvider.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationCodeProvider.java @@ -223,7 +223,6 @@ public void testNoClientIdProvided() throws Exception { ResponseEntity response = attemptToGetConfirmationPage(null, "http://anywhere/"); // With no client id you get an InvalidClientException on the server which is forwarded to /oauth/error assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); - // TODO: assert the HTML content String body = response.getBody(); assertTrue("Wrong body: " + body, body.contains(" getRequestParams() { * * @return The key to the state to preserve. */ - // TODO: is this obsolete or in the wrong place? public String getStateKey() { return stateKey; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/OAuth2Utils.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/OAuth2Utils.java index 22be9d7b6..c28a64037 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/OAuth2Utils.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/OAuth2Utils.java @@ -31,22 +31,39 @@ */ public abstract class OAuth2Utils { - // FIXME: is this the right place for constants? /** - * Constants to use while parsing parameter maps for OAuth2 requests + * Constant to use while parsing and formatting parameter maps for OAuth2 requests */ public static final String CLIENT_ID = "client_id"; + /** + * Constant to use while parsing and formatting parameter maps for OAuth2 requests + */ public static final String STATE = "state"; + /** + * Constant to use while parsing and formatting parameter maps for OAuth2 requests + */ public static final String SCOPE = "scope"; + /** + * Constant to use while parsing and formatting parameter maps for OAuth2 requests + */ public static final String REDIRECT_URI = "redirect_uri"; + /** + * Constant to use while parsing and formatting parameter maps for OAuth2 requests + */ public static final String RESPONSE_TYPE = "response_type"; + /** + * Constant to use while parsing and formatting parameter maps for OAuth2 requests + */ public static final String USER_OAUTH_APPROVAL = "user_oauth_approval"; + /** + * Constant to use while parsing and formatting parameter maps for OAuth2 requests + */ public static final String GRANT_TYPE = "grant_type"; /** diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java index fe0f5dc58..b2cec5858 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java @@ -11,11 +11,11 @@ import org.springframework.security.core.GrantedAuthority; /** - * Base class representing an OAuth2 Authorization Request. HTTP request parameters are stored in - * the parameters map, and any processing the server makes throughout the lifecycle of a request are stored - * on individual properties. The original request parameters will remain available through the parameters - * map. For convenience, constants are defined in order to get at those original values. However, the - * parameters map is unmodifiable so that processing cannot drop the original values. + * Base class representing an OAuth2 Authorization Request. HTTP request parameters are stored in the parameters map, + * and any processing the server makes throughout the lifecycle of a request are stored on individual properties. The + * original request parameters will remain available through the parameters map. For convenience, constants are defined + * in order to get at those original values. However, the parameters map is unmodifiable so that processing cannot drop + * the original values. * * @author Ryan Heaton * @author Dave Syer @@ -24,53 +24,51 @@ public class AuthorizationRequest extends OAuth2Request implements Serializable { private static final long serialVersionUID = 1L; - + /** - * Map to hold the original, unchanged parameter set returned from the - * Approval Endpoint. Once set this should not be modified. + * Map to hold the original, unchanged parameter set submitted by a user to signal approval of the token grant + * approval. Once set this should not be modified. */ private Map approvalParameters = Collections.unmodifiableMap(new HashMap()); /** - * The value of the "state" parameter sent by the client in the request, if - * sent by the client. As this must be echoed back to the client unchanged, - * it should not be modified by any processing classes. + * The value of the "state" parameter sent by the client in the request, if sent by the client. As this must be + * echoed back to the client unchanged, it should not be modified by any processing classes. */ private String state; /** - * Resolved requested response types initialized (by the - * OAuth2RequestFactory) with the response types originally requested. + * Resolved requested response types initialized (by the OAuth2RequestFactory) with the response types originally + * requested. */ private Set responseTypes = new HashSet(); /** - * Default constructor. + * Default constructor. */ public AuthorizationRequest() { } - + /** * Full constructor. */ - public AuthorizationRequest(Map authorizationParameters, Map approvalParameters, - String clientId, Set scope, Set resourceIds, - Collection authorities, boolean approved, String state, - String redirectUri, Set responseTypes){ + public AuthorizationRequest(Map authorizationParameters, Map approvalParameters, + String clientId, Set scope, Set resourceIds, + Collection authorities, boolean approved, String state, String redirectUri, + Set responseTypes) { super(authorizationParameters, clientId, authorities, approved, scope, resourceIds, redirectUri, null); if (responseTypes != null) { this.responseTypes = responseTypes; } this.state = state; } - + public OAuth2Request createOAuth2Request() { - return new OAuth2Request((OAuth2Request)this); + return new OAuth2Request((OAuth2Request) this); } /** - * Convenience constructor for unit tests, where client ID and scope are often - * the only needed fields. + * Convenience constructor for unit tests, where client ID and scope are often the only needed fields. * * @param clientId * @param scopes @@ -79,10 +77,9 @@ public AuthorizationRequest(String clientId, Collection scopes) { super(clientId); setScope(new HashSet(scopes)); } - + /** - * Convenience method to set resourceIds and authorities on this request by - * inheriting from a ClientDetails object. + * Convenience method to set resourceIds and authorities on this request by inheriting from a ClientDetails object. * * @param clientDetails */ @@ -90,7 +87,7 @@ public void setResourceIdsAndAuthoritiesFromClientDetails(ClientDetails clientDe setResourceIds(clientDetails.getResourceIds()); setAuthorities(clientDetails.getAuthorities()); } - + public Map getApprovalParameters() { return approvalParameters; } @@ -115,6 +112,31 @@ public void setResponseTypes(Set responseTypes) { this.responseTypes = responseTypes; } + @Override + public void setRedirectUri(String redirectUri) { + super.setRedirectUri(redirectUri); + } + + @Override + public void setApproved(boolean approved) { + super.setApproved(approved); + } + + @Override + public void setAuthorities(Collection authorities) { + super.setAuthorities(authorities); + } + + @Override + public void setExtensions(Map extensionProperties) { + super.setExtensions(extensionProperties); + } + + @Override + public void setResourceIds(Set resourceIds) { + super.setResourceIds(resourceIds); + } + @Override public int hashCode() { final int prime = 31; @@ -155,6 +177,4 @@ else if (!state.equals(other.state)) return true; } - - } \ No newline at end of file diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java index 105327e5f..ea83ec6a8 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java @@ -1,14 +1,17 @@ /* - * Cloud Foundry 2012.02.03 Beta - * Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved. + * Copyright 2012-2013 the original author or authors. * - * This product is licensed to you under the Apache License, Version 2.0 (the "License"). - * You may not use this product except in compliance with the License. + * 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 * - * This product includes a number of subcomponents with - * separate copyright notices and license terms. Your use of these - * subcomponents is subject to the terms and conditions of the - * subcomponent's license, as noted in the LICENSE file. + * 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; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestFactory.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestFactory.java index ad8d7e05f..11144889d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestFactory.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestFactory.java @@ -60,7 +60,7 @@ public AuthorizationRequest createAuthorizationRequest(Map autho } - public OAuth2Request createStoredAuthorizationRequest(AuthorizationRequest request) { + public OAuth2Request createOAuth2Request(AuthorizationRequest request) { return request.createOAuth2Request(); } @@ -84,13 +84,12 @@ public TokenRequest createTokenRequest(Map requestParameters) { return tokenRequest; } - // FIXME: "implicit" is hard coded? - public TokenRequest createTokenRequestFromAuthorizationRequest(AuthorizationRequest authorizationRequest) { - TokenRequest tokenRequest = new TokenRequest(authorizationRequest.getRequestParameters(), authorizationRequest.getClientId(), authorizationRequest.getScope(), "implicit"); + public TokenRequest createTokenRequest(AuthorizationRequest authorizationRequest, String grantType) { + TokenRequest tokenRequest = new TokenRequest(authorizationRequest.getRequestParameters(), authorizationRequest.getClientId(), authorizationRequest.getScope(), grantType); return tokenRequest; } - public OAuth2Request createStoredTokenRequest(TokenRequest tokenRequest) { + public OAuth2Request createOAuth2Request(TokenRequest tokenRequest) { return tokenRequest.createOAuth2Request(); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java index 20b3b2424..2108313c7 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java @@ -11,9 +11,11 @@ /** * Represents a stored authorization or token request. Used as part of the OAuth2Authentication object to store a - * request's authentication information. + * request's authentication information. Does not expose public setters so that clients can not mutate state if they + * respect the declared type of the request. * * @author Amanda Anganes + * @author Dave Syer * */ public class OAuth2Request extends BaseRequest implements Serializable { @@ -47,7 +49,7 @@ public class OAuth2Request extends BaseRequest implements Serializable { * Extension point for custom processing classes which may wish to store additional information about the OAuth2 * request. Since this class is serializable, all members of this map must also be serializable. */ - private Map extensionProperties = new HashMap(); + private Map extensions = new HashMap(); protected OAuth2Request(Map requestParameters, String clientId, Collection authorities, boolean approved, Set scope, @@ -65,13 +67,13 @@ protected OAuth2Request(Map requestParameters, String clientId, this.resourceIds = resourceIds; this.redirectUri = redirectUri; if (extensionProperties != null) { - this.extensionProperties = extensionProperties; + this.extensions = extensionProperties; } } protected OAuth2Request(OAuth2Request other) { this(other.getRequestParameters(), other.getClientId(), other.getAuthorities(), other.isApproved(), other - .getScope(), other.getResourceIds(), other.getRedirectUri(), other.getExtensionProperties()); + .getScope(), other.getResourceIds(), other.getRedirectUri(), other.getExtensions()); } protected OAuth2Request(String clientId) { @@ -86,7 +88,7 @@ public String getRedirectUri() { return redirectUri; } - public void setRedirectUri(String redirectUri) { + protected void setRedirectUri(String redirectUri) { this.redirectUri = redirectUri; } @@ -94,7 +96,7 @@ public Collection getAuthorities() { return authorities; } - public void setAuthorities(Collection authorities) { + protected void setAuthorities(Collection authorities) { this.authorities = authorities; } @@ -102,7 +104,7 @@ public boolean isApproved() { return approved; } - public void setApproved(boolean approved) { + protected void setApproved(boolean approved) { this.approved = approved; } @@ -110,22 +112,26 @@ public Set getResourceIds() { return resourceIds; } - public void setResourceIds(Set resourceIds) { + protected void setResourceIds(Set resourceIds) { this.resourceIds = resourceIds; } - public Map getExtensionProperties() { - return extensionProperties; + public Map getExtensions() { + return extensions; } - public void setExtensionProperties(Map extensionProperties) { - this.extensionProperties = extensionProperties; + protected void setExtensions(Map extensionProperties) { + this.extensions = extensionProperties; } - // FIXME: is this needed? + /** + * Update the request parameters and return a new object with the same properties except the parameters. + * @param parameters new parameters replacing the existing ones + * @return a new OAuth2Request + */ public OAuth2Request createOAuth2Request(Map parameters) { return new OAuth2Request(parameters, getClientId(), authorities, approved, getScope(), resourceIds, - redirectUri, extensionProperties); + redirectUri, extensions); } @Override @@ -134,7 +140,7 @@ public int hashCode() { int result = 1; result = prime * result + (approved ? 1231 : 1237); result = prime * result + ((authorities == null) ? 0 : authorities.hashCode()); - result = prime * result + ((extensionProperties == null) ? 0 : extensionProperties.hashCode()); + result = prime * result + ((extensions == null) ? 0 : extensions.hashCode()); result = prime * result + ((redirectUri == null) ? 0 : redirectUri.hashCode()); result = prime * result + ((resourceIds == null) ? 0 : resourceIds.hashCode()); return result; @@ -157,11 +163,11 @@ public boolean equals(Object obj) { } else if (!authorities.equals(other.authorities)) return false; - if (extensionProperties == null) { - if (other.extensionProperties != null) + if (extensions == null) { + if (other.extensions != null) return false; } - else if (!extensionProperties.equals(other.extensionProperties)) + else if (!extensions.equals(other.extensions)) return false; if (redirectUri == null) { if (other.redirectUri != null) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestFactory.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestFactory.java index c409b6e05..d091707e8 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestFactory.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestFactory.java @@ -25,35 +25,39 @@ public interface OAuth2RequestFactory { /** - * Create a new {@link AuthorizationRequest} extracting all the needed information from the incoming parameter map, and - * initializing all individual fields on the {@link AuthorizationRequest} to reasonable values. When a class uses - * the factory to create an {@link AuthorizationRequest}, it should not need to access the parameter map directly afterwards. + * Create a new {@link AuthorizationRequest} extracting all the needed information from the incoming parameter map, + * and initializing all individual fields on the {@link AuthorizationRequest} to reasonable values. When a class + * uses the factory to create an {@link AuthorizationRequest}, it should not need to access the parameter map + * directly afterwards. * - * Typical implementations would initialize the individual fields on the {@link AuthorizationRequest} with the values - * requested in the original parameter map. It may also load the client details from the client id provided and - * validate the grant type and scopes, populating any fields in the request that are known only to the authorization server. + * Typical implementations would initialize the individual fields on the {@link AuthorizationRequest} with the + * values requested in the original parameter map. It may also load the client details from the client id provided + * and validate the grant type and scopes, populating any fields in the request that are known only to the + * authorization server. * * @param authorizationParameters the parameters in the request * @return a new AuthorizationRequest */ AuthorizationRequest createAuthorizationRequest(Map authorizationParameters); - + /** - * Create a new {@link OAuth2Request} by extracting the needed information from the current {@link AuthorizationRequest} object. + * Create a new {@link OAuth2Request} by extracting the needed information from the current + * {@link AuthorizationRequest} object. * * @param request the request to be converted * @return an immutable object for storage */ - OAuth2Request createStoredAuthorizationRequest(AuthorizationRequest request); - + OAuth2Request createOAuth2Request(AuthorizationRequest request); + /** - * Create a new {@link OAuth2Request} by extracting the needed information from the current {@link TokenRequest} object. + * Create a new {@link OAuth2Request} by extracting the needed information from the current {@link TokenRequest} + * object. * * @param tokenRequest the request to be converted * @return am immutable object for storage */ - OAuth2Request createStoredTokenRequest(TokenRequest tokenRequest); - + OAuth2Request createOAuth2Request(TokenRequest tokenRequest); + /** * Create a new {@link TokenRequest} by extracting the needed information from the incoming request parameter map. * @@ -63,14 +67,13 @@ public interface OAuth2RequestFactory { TokenRequest createTokenRequest(Map requestParameters); /** - * Create a new {@link TokenRequest} from an {@link AuthorizationRequest}. Used by the AuthorizationEndpoint during the - * implicit flow. + * Create a new {@link TokenRequest} from an {@link AuthorizationRequest}. Principally used by the + * AuthorizationEndpoint during the implicit flow. * * @param authorizationRequest the incoming request - * @return a new TokenRequest + * @param grantType the grant type for the token request + * @return a new token request */ - TokenRequest createTokenRequestFromAuthorizationRequest(AuthorizationRequest authorizationRequest); + TokenRequest createTokenRequest(AuthorizationRequest authorizationRequest, String grantType); - - } \ No newline at end of file diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenServicesUserApprovalHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenServicesUserApprovalHandler.java index 72df47ce8..e9e9d5270 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenServicesUserApprovalHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenServicesUserApprovalHandler.java @@ -82,7 +82,7 @@ public boolean isApproved(AuthorizationRequest authorizationRequest, Authenticat String flag = authorizationRequest.getApprovalParameters().get(approvalParameter); boolean approved = flag != null && flag.toLowerCase().equals("true"); - OAuth2Request storedOAuth2Request = requestFactory.createStoredAuthorizationRequest(authorizationRequest); + OAuth2Request storedOAuth2Request = requestFactory.createOAuth2Request(authorizationRequest); OAuth2Authentication authentication = new OAuth2Authentication(storedOAuth2Request, userAuthentication); if (logger.isDebugEnabled()) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java index 41a6488d1..9aefbd351 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java @@ -249,7 +249,7 @@ private ModelAndView getUserApprovalPageResponse(Map model, // We can grant a token and return it with implicit approval. private ModelAndView getImplicitGrantResponse(AuthorizationRequest authorizationRequest) { try { - TokenRequest tokenRequest = getOAuth2RequestFactory().createTokenRequestFromAuthorizationRequest(authorizationRequest); + TokenRequest tokenRequest = getOAuth2RequestFactory().createTokenRequest(authorizationRequest, "implicit"); OAuth2AccessToken accessToken = getTokenGranter().grant("implicit", tokenRequest); if (accessToken == null) { throw new UnsupportedResponseTypeException("Unsupported response type: token"); @@ -326,7 +326,7 @@ private String generateCode(AuthorizationRequest authorizationRequest, Authentic try { - OAuth2Request storedOAuth2Request = getOAuth2RequestFactory().createStoredAuthorizationRequest(authorizationRequest); + OAuth2Request storedOAuth2Request = getOAuth2RequestFactory().createOAuth2Request(authorizationRequest); OAuth2Authentication combinedAuth = new OAuth2Authentication(storedOAuth2Request, authentication); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java index 4ca52d461..72d394134 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java @@ -139,7 +139,6 @@ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) "No client authentication found. Remember to put a filter upstream of the TokenEndpointAuthenticationFilter."); } - // FIXME: use client id in factory method Map map = getSingleValueMap(request); map.put(OAuth2Utils.CLIENT_ID, clientAuth.getName()); AuthorizationRequest authorizationRequest = oAuth2RequestFactory.createAuthorizationRequest(map); @@ -150,7 +149,7 @@ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) authorizationRequest.setApproved(true); } - OAuth2Request storedOAuth2Request = oAuth2RequestFactory.createStoredAuthorizationRequest(authorizationRequest); + OAuth2Request storedOAuth2Request = oAuth2RequestFactory.createOAuth2Request(authorizationRequest); SecurityContextHolder.getContext().setAuthentication( new OAuth2Authentication(storedOAuth2Request, authResult)); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java index 925bf067b..3e988ebc6 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java @@ -48,7 +48,7 @@ protected OAuth2Authentication getOAuth2Authentication(TokenRequest clientToken) throw new InsufficientAuthenticationException("There is no currently logged in user"); } - OAuth2Request storedOAuth2Request = getRequestFactory().createStoredTokenRequest(clientToken); + OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(clientToken); return new OAuth2Authentication(storedOAuth2Request, userAuth); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AbstractTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AbstractTokenGranter.java index 632b7ae78..2221842e2 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AbstractTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AbstractTokenGranter.java @@ -62,9 +62,6 @@ public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) { logger.debug("Getting access token for: " + clientId); - // FIXME: do we need to explicitly set approved flag here? - //tokenRequest.setApproved(true); - return getAccessToken(tokenRequest); } @@ -74,7 +71,7 @@ protected OAuth2AccessToken getAccessToken(TokenRequest tokenRequest) { } protected OAuth2Authentication getOAuth2Authentication(TokenRequest tokenRequest) { - OAuth2Request storedOAuth2Request = requestFactory.createStoredTokenRequest(tokenRequest); + OAuth2Request storedOAuth2Request = requestFactory.createOAuth2Request(tokenRequest); return new OAuth2Authentication(storedOAuth2Request, null); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/TestOAuth2AccessTokenSupport.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/TestOAuth2AccessTokenSupport.java index 6a085d009..8a9fb6124 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/TestOAuth2AccessTokenSupport.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/TestOAuth2AccessTokenSupport.java @@ -1,14 +1,17 @@ /* - * Cloud Foundry 2012.02.03 Beta - * Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved. + * Copyright 2012-2013 the original author or authors. * - * This product is licensed to you under the Apache License, Version 2.0 (the "License"). - * You may not use this product except in compliance with the License. + * 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 * - * This product includes a number of subcomponents with - * separate copyright notices and license terms. Your use of these - * subcomponents is subject to the terms and conditions of the - * subcomponent's license, as noted in the LICENSE file. + * 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.client.token; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestOAuth2Authentication.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestOAuth2Authentication.java index f79d18ddc..a3c45b969 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestOAuth2Authentication.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestOAuth2Authentication.java @@ -3,6 +3,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import java.util.Arrays; import java.util.Collections; import org.codehaus.jackson.map.ObjectMapper; @@ -10,10 +11,12 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.test.annotation.Rollback; +import org.springframework.util.SerializationUtils; public class TestOAuth2Authentication { - private OAuth2Request request = RequestTokenFactory.createOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null); + private OAuth2Request request = RequestTokenFactory.createOAuth2Request(null, "id", null, false, + Collections.singleton("read"), null, null, null); private UsernamePasswordAuthenticationToken userAuthentication = new UsernamePasswordAuthenticationToken("foo", "bar", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"))); @@ -21,7 +24,8 @@ public class TestOAuth2Authentication { @Test @Rollback public void testIsAuthenticated() { - request = RequestTokenFactory.createOAuth2Request(null, "id", null, true, Collections.singleton("read"), null, null, null); + request = RequestTokenFactory.createOAuth2Request(null, "id", null, true, Collections.singleton("read"), null, + null, null); OAuth2Authentication authentication = new OAuth2Authentication(request, userAuthentication); assertTrue(authentication.isAuthenticated()); } @@ -43,10 +47,21 @@ public void testIsClientOnly() { OAuth2Authentication authentication = new OAuth2Authentication(request, null); assertTrue(authentication.isClientOnly()); } - + @Test public void testJsonSerialization() throws Exception { - System.err.println(new ObjectMapper().writeValueAsString(new OAuth2Authentication(request, userAuthentication))); + System.err + .println(new ObjectMapper().writeValueAsString(new OAuth2Authentication(request, userAuthentication))); + } + + @Test + public void testSerialization() { + OAuth2Authentication holder = new OAuth2Authentication( + new AuthorizationRequest("client", Arrays.asList("read")), new UsernamePasswordAuthenticationToken( + "user", "pwd")); + OAuth2Authentication other = (OAuth2Authentication) SerializationUtils.deserialize(SerializationUtils + .serialize(holder)); + assertEquals(holder, other); } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenServicesUserApprovalHandler.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenServicesUserApprovalHandler.java index 2cbca1c8c..2ee20b7c3 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenServicesUserApprovalHandler.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenServicesUserApprovalHandler.java @@ -68,7 +68,7 @@ public void testMemorizedApproval() { AuthorizationRequest authorizationRequest = new AuthorizationRequest(parameters, null, "foo", null, null, null, false, null, null, null); authorizationRequest.setApproved(false); TestAuthentication userAuthentication = new TestAuthentication("marissa", true); - OAuth2Request storedOAuth2Request = requestFactory.createStoredAuthorizationRequest(authorizationRequest); + OAuth2Request storedOAuth2Request = requestFactory.createOAuth2Request(authorizationRequest); tokenServices.createAccessToken(new OAuth2Authentication(storedOAuth2Request, userAuthentication)); assertTrue(handler.isApproved(authorizationRequest, userAuthentication)); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationRequestHolder.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationRequestHolder.java deleted file mode 100644 index b3560ddb9..000000000 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationRequestHolder.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Cloud Foundry 2012.02.03 Beta - * Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved. - * - * This product is licensed to you under the Apache License, Version 2.0 (the "License"). - * You may not use this product except in compliance with the License. - * - * This product includes a number of subcomponents with - * separate copyright notices and license terms. Your use of these - * subcomponents is subject to the terms and conditions of the - * subcomponent's license, as noted in the LICENSE file. - */ - -package org.springframework.security.oauth2.provider.code; - -import static org.junit.Assert.assertEquals; - -import java.util.Arrays; - -import org.junit.Test; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.oauth2.common.util.SerializationUtils; -import org.springframework.security.oauth2.provider.AuthorizationRequest; - -/** - * @author Dave Syer - * - */ -//TOOD: Test serialization of OAuth2Authentication -public class TestAuthorizationRequestHolder { - - //private OAuth2Authentication holder = new AuthorizationRequestHolder(new AuthorizationRequest( - // "client", Arrays.asList("read")), new UsernamePasswordAuthenticationToken("user", "pwd")); - - //@Test - public void test() { - //AuthorizationRequestHolder other = SerializationUtils.deserialize(SerializationUtils.serialize(holder)); - //assertEquals(holder, other); - } - -} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2MethodSecurityExpressionHandler.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2MethodSecurityExpressionHandler.java index 0f3e2d8a6..d06773fee 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2MethodSecurityExpressionHandler.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2MethodSecurityExpressionHandler.java @@ -52,7 +52,7 @@ public void testOauthClient() throws Exception { Authentication userAuthentication = null; OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(request.getRequestParameters(), request.getClientId(), request.getAuthorities(), request.isApproved(), request.getScope(), request.getResourceIds(), - request.getRedirectUri(), request.getExtensionProperties()); + request.getRedirectUri(), request.getExtensions()); OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); MethodInvocation invocation = new SimpleMethodInvocation(this, ReflectionUtils.findMethod(getClass(), diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2SecurityExpressionMethods.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2SecurityExpressionMethods.java index 574dd6fa4..c3c122baf 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2SecurityExpressionMethods.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2SecurityExpressionMethods.java @@ -47,7 +47,7 @@ public void testOauthClient() throws Exception { Authentication userAuthentication = null; OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(request.getRequestParameters(), request.getClientId(), request.getAuthorities(), request.isApproved(), request.getScope(), request.getResourceIds(), - request.getRedirectUri(), request.getExtensionProperties()); + request.getRedirectUri(), request.getExtensions()); OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); assertTrue(new OAuth2SecurityExpressionMethods(oAuth2Authentication, true).clientHasAnyRole("ROLE_CLIENT")); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2WebSecurityExpressionHandler.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2WebSecurityExpressionHandler.java index b3d527794..978de79fa 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2WebSecurityExpressionHandler.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2WebSecurityExpressionHandler.java @@ -46,7 +46,7 @@ public void testOauthClient() throws Exception { request.setResourceIdsAndAuthoritiesFromClientDetails(new BaseClientDetails("foo", "", "", "client_credentials", "ROLE_CLIENT")); OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(request.getRequestParameters(), request.getClientId(), request.getAuthorities(), request.isApproved(), request.getScope(), request.getResourceIds(), - request.getRedirectUri(), request.getExtensionProperties()); + request.getRedirectUri(), request.getExtensions()); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); From d89d1d25a2e658483b02edf47bf89e5fb430f87e Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 10 Jul 2013 10:27:52 +0100 Subject: [PATCH 059/831] Add ClientDetails to some method signatures where it is clearly always available --- .../oauth2/provider/DefaultOAuth2RequestFactory.java | 4 ++-- .../security/oauth2/provider/OAuth2RequestFactory.java | 5 +++-- .../security/oauth2/provider/TokenRequest.java | 4 ++-- .../provider/code/AuthorizationCodeTokenGranter.java | 3 ++- .../oauth2/provider/implicit/ImplicitTokenGranter.java | 5 +++-- .../password/ResourceOwnerPasswordTokenGranter.java | 10 ++++------ .../oauth2/provider/refresh/RefreshTokenGranter.java | 3 ++- .../oauth2/provider/token/AbstractTokenGranter.java | 10 +++++----- .../token/AuthorizationServerTokenServices.java | 1 - .../converter/jaxb/BaseJaxbMessageConverterTest.java | 1 + .../TestJaxbOAuth2AccessTokenMessageConverter.java | 1 + .../jaxb/TestJaxbOAuth2ExceptionMessageConverter.java | 1 + .../approval/TestTokenServicesUserApprovalHandler.java | 2 +- .../code/TestAuthorizationCodeTokenGranter.java | 2 +- 14 files changed, 28 insertions(+), 24 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestFactory.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestFactory.java index 11144889d..93cf01f95 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestFactory.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestFactory.java @@ -89,8 +89,8 @@ public TokenRequest createTokenRequest(AuthorizationRequest authorizationRequest return tokenRequest; } - public OAuth2Request createOAuth2Request(TokenRequest tokenRequest) { - return tokenRequest.createOAuth2Request(); + public OAuth2Request createOAuth2Request(ClientDetails client, TokenRequest tokenRequest) { + return tokenRequest.createOAuth2Request(client); } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestFactory.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestFactory.java index d091707e8..84315ddae 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestFactory.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestFactory.java @@ -52,11 +52,12 @@ public interface OAuth2RequestFactory { /** * Create a new {@link OAuth2Request} by extracting the needed information from the current {@link TokenRequest} * object. - * + * @param client TODO * @param tokenRequest the request to be converted + * * @return am immutable object for storage */ - OAuth2Request createOAuth2Request(TokenRequest tokenRequest); + OAuth2Request createOAuth2Request(ClientDetails client, TokenRequest tokenRequest); /** * Create a new {@link TokenRequest} by extracting the needed information from the incoming request parameter map. diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java index 049b6df89..293f17e8e 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java @@ -55,12 +55,12 @@ public void setGrantType(String grantType) { this.grantType = grantType; } - public OAuth2Request createOAuth2Request() { + public OAuth2Request createOAuth2Request(ClientDetails client) { // Remove password if present to prevent leaks Map requestParameters = getRequestParameters(); HashMap modifiable = new HashMap(requestParameters); modifiable.remove("password"); - return new OAuth2Request(modifiable, this.getClientId(), null, true, this.getScope(), null, null, null); + return new OAuth2Request(modifiable, client.getClientId(), client.getAuthorities(), true, this.getScope(), null, null, null); } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranter.java index 6d07bd64f..1d76768aa 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranter.java @@ -25,6 +25,7 @@ import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.common.exceptions.RedirectMismatchException; import org.springframework.security.oauth2.common.util.OAuth2Utils; +import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; @@ -52,7 +53,7 @@ public AuthorizationCodeTokenGranter(AuthorizationServerTokenServices tokenServi } @Override - protected OAuth2Authentication getOAuth2Authentication(TokenRequest tokenRequest) { + protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) { Map parameters = tokenRequest.getRequestParameters(); String authorizationCode = parameters.get("code"); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java index 3e988ebc6..956c895ba 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java @@ -20,6 +20,7 @@ import org.springframework.security.authentication.InsufficientAuthenticationException; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; @@ -41,14 +42,14 @@ public ImplicitTokenGranter(AuthorizationServerTokenServices tokenServices, Clie } @Override - protected OAuth2Authentication getOAuth2Authentication(TokenRequest clientToken) { + protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest clientToken) { Authentication userAuth = SecurityContextHolder.getContext().getAuthentication(); if (userAuth==null || !userAuth.isAuthenticated()) { throw new InsufficientAuthenticationException("There is no currently logged in user"); } - OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(clientToken); + OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, clientToken); return new OAuth2Authentication(storedOAuth2Request, userAuth); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java index f64416756..bdaa86f67 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java @@ -24,6 +24,7 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; +import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; @@ -49,9 +50,9 @@ public ResourceOwnerPasswordTokenGranter(AuthenticationManager authenticationMan } @Override - protected OAuth2Authentication getOAuth2Authentication(TokenRequest clientToken) { + protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) { - Map parameters = clientToken.getRequestParameters(); + Map parameters = tokenRequest.getRequestParameters(); String username = parameters.get("username"); String password = parameters.get("password"); @@ -71,10 +72,7 @@ protected OAuth2Authentication getOAuth2Authentication(TokenRequest clientToken) throw new InvalidGrantException("Could not authenticate user: " + username); } - //Bypass the factory and instead create our own object here, since we want all the properties of the original TokenRequest, - //but with the new requestParameters map that has had the "password" parameter removed. - OAuth2Request storedOAuth2Request = clientToken.createOAuth2Request(); - + 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/refresh/RefreshTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/refresh/RefreshTokenGranter.java index e02e7163e..4ea82a4e5 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/refresh/RefreshTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/refresh/RefreshTokenGranter.java @@ -17,6 +17,7 @@ package org.springframework.security.oauth2.provider.refresh; import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; import org.springframework.security.oauth2.provider.TokenRequest; @@ -36,7 +37,7 @@ public RefreshTokenGranter(AuthorizationServerTokenServices tokenServices, Clien } @Override - protected OAuth2AccessToken getAccessToken(TokenRequest tokenRequest) { + protected OAuth2AccessToken getAccessToken(ClientDetails client, TokenRequest tokenRequest) { String refreshToken = tokenRequest.getRequestParameters().get("refresh_token"); return getTokenServices().refreshAccessToken(refreshToken, tokenRequest); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AbstractTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AbstractTokenGranter.java index 2221842e2..dd15635ff 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AbstractTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AbstractTokenGranter.java @@ -62,16 +62,16 @@ public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) { logger.debug("Getting access token for: " + clientId); - return getAccessToken(tokenRequest); + return getAccessToken(client, tokenRequest); } - protected OAuth2AccessToken getAccessToken(TokenRequest tokenRequest) { - return tokenServices.createAccessToken(getOAuth2Authentication(tokenRequest)); + protected OAuth2AccessToken getAccessToken(ClientDetails client, TokenRequest tokenRequest) { + return tokenServices.createAccessToken(getOAuth2Authentication(client, tokenRequest)); } - protected OAuth2Authentication getOAuth2Authentication(TokenRequest tokenRequest) { - OAuth2Request storedOAuth2Request = requestFactory.createOAuth2Request(tokenRequest); + protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) { + OAuth2Request storedOAuth2Request = requestFactory.createOAuth2Request(client, tokenRequest); return new OAuth2Authentication(storedOAuth2Request, null); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AuthorizationServerTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AuthorizationServerTokenServices.java index 5df146db5..13549ea70 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AuthorizationServerTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AuthorizationServerTokenServices.java @@ -29,7 +29,6 @@ public interface AuthorizationServerTokenServices { /** * Create an access token associated with the specified credentials. - * * @param authentication The credentials associated with the access token. * @return The access token. * @throws AuthenticationException If the credentials are inadequate. diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/BaseJaxbMessageConverterTest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/BaseJaxbMessageConverterTest.java index cf52a5bae..bd07b869b 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/BaseJaxbMessageConverterTest.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/BaseJaxbMessageConverterTest.java @@ -40,6 +40,7 @@ * @author Rob Winch * */ +@SuppressWarnings("restriction") @RunWith(PowerMockRunner.class) @PrepareForTest(System.class) abstract class BaseJaxbMessageConverterTest { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/TestJaxbOAuth2AccessTokenMessageConverter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/TestJaxbOAuth2AccessTokenMessageConverter.java index 99da1a4ba..d6caa896e 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/TestJaxbOAuth2AccessTokenMessageConverter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/TestJaxbOAuth2AccessTokenMessageConverter.java @@ -34,6 +34,7 @@ * @author Rob Winch * */ +@SuppressWarnings("restriction") @PrepareForTest(JaxbOAuth2AccessToken.class) public class TestJaxbOAuth2AccessTokenMessageConverter extends BaseJaxbMessageConverterTest { private JaxbOAuth2AccessTokenMessageConverter converter; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/TestJaxbOAuth2ExceptionMessageConverter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/TestJaxbOAuth2ExceptionMessageConverter.java index cb8930de7..fce14a58a 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/TestJaxbOAuth2ExceptionMessageConverter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/TestJaxbOAuth2ExceptionMessageConverter.java @@ -40,6 +40,7 @@ * @author Rob Winch * */ +@SuppressWarnings("restriction") @RunWith(PowerMockRunner.class) @PrepareForTest({ System.class, JaxbOAuth2AccessToken.class }) public class TestJaxbOAuth2ExceptionMessageConverter extends BaseJaxbMessageConverterTest { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenServicesUserApprovalHandler.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenServicesUserApprovalHandler.java index 2ee20b7c3..49d662076 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenServicesUserApprovalHandler.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenServicesUserApprovalHandler.java @@ -20,9 +20,9 @@ import org.junit.Test; import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.oauth2.common.util.OAuth2Utils; +import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.DefaultOAuth2RequestFactory; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.token.DefaultTokenServices; import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeTokenGranter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeTokenGranter.java index c82702c43..5b79ea1cf 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeTokenGranter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeTokenGranter.java @@ -196,7 +196,7 @@ public void testAuthorizationRedirectMismatch() { AuthorizationCodeTokenGranter granter = new AuthorizationCodeTokenGranter(providerTokenServices, authorizationCodeServices, clientDetailsService, requestFactory); try { - granter.getOAuth2Authentication(tokenRequest); + granter.getOAuth2Authentication(client, tokenRequest); fail("RedirectMismatchException because of null redirect_uri in authorizationRequest"); } catch (RedirectMismatchException e) { From 9704cf66181cb1179bd02dad8cf63c0e77cf8ebc Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Wed, 10 Jul 2013 11:59:05 -0400 Subject: [PATCH 060/831] Refactored OAuth2Request, AuthorizationRequest, and TokenRequest ...into a flatter heirarchy --- .../oauth2/provider/AuthorizationRequest.java | 125 +++++++++++++++--- .../security/oauth2/provider/BaseRequest.java | 21 +-- .../oauth2/provider/OAuth2Request.java | 81 ++++++++---- .../oauth2/provider/TokenRequest.java | 29 +++- .../expression/OAuth2ExpressionUtils.java | 3 +- .../DefaultAuthenticationKeyGenerator.java | 4 +- .../provider/token/DefaultTokenServices.java | 9 +- .../oauth2/provider/vote/ScopeVoter.java | 6 +- .../provider/TestOAuth2Authentication.java | 4 +- .../TestAuthorizationCodeTokenGranter.java | 13 +- 10 files changed, 212 insertions(+), 83 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java index b2cec5858..d5b93fd8a 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java @@ -21,9 +21,7 @@ * @author Dave Syer * @author Amanda Anganes */ -public class AuthorizationRequest extends OAuth2Request implements Serializable { - - private static final long serialVersionUID = 1L; +public class AuthorizationRequest extends BaseRequest { /** * Map to hold the original, unchanged parameter set submitted by a user to signal approval of the token grant @@ -43,6 +41,36 @@ public class AuthorizationRequest extends OAuth2Request implements Serializable */ private Set responseTypes = new HashSet(); + /** + * Resolved resource IDs. This set may change during request processing. + */ + private Set resourceIds = new HashSet(); + + /** + * Resolved granted authorities for this request. May change during request processing. + */ + private Collection authorities = new HashSet(); + + /** + * Whether the request has been approved by the end user (or other process). This will be altered by the User + * Approval Endpoint and/or the UserApprovalHandler as appropriate. + */ + private boolean approved = false; + + /** + * The resolved redirect URI of this request. A URI may be present in the original request, in the + * authorizationParameters, or it may not be provided, in which case it will be defaulted (by processing classes) to + * the Client's default registered value. + */ + private String redirectUri; + + /** + * Extension point for custom processing classes which may wish to store additional information about the OAuth2 + * request. Since this class will create a serializable OAuth2Request, all members of this extension map + * must be serializable. + */ + private Map extensions = new HashMap(); + /** * Default constructor. */ @@ -56,7 +84,18 @@ public AuthorizationRequest(Map authorizationParameters, Map scope, Set resourceIds, Collection authorities, boolean approved, String state, String redirectUri, Set responseTypes) { - super(authorizationParameters, clientId, authorities, approved, scope, resourceIds, redirectUri, null); + super.setClientId(clientId); + super.setRequestParameters(authorizationParameters); + super.setScope(scope); + if (resourceIds != null) { + this.resourceIds = new HashSet(resourceIds); + } + if (authorities != null) { + this.authorities = new HashSet(authorities); + } + this.approved = approved; + this.resourceIds = resourceIds; + this.redirectUri = redirectUri; if (responseTypes != null) { this.responseTypes = responseTypes; } @@ -64,7 +103,7 @@ public AuthorizationRequest(Map authorizationParameters, Map scopes) { - super(clientId); - setScope(new HashSet(scopes)); + super.setClientId(clientId); + super.setScope(new HashSet(scopes)); } /** @@ -112,29 +151,81 @@ public void setResponseTypes(Set responseTypes) { this.responseTypes = responseTypes; } - @Override public void setRedirectUri(String redirectUri) { - super.setRedirectUri(redirectUri); + this.redirectUri = redirectUri; } - @Override public void setApproved(boolean approved) { - super.setApproved(approved); + this.approved = approved; } - @Override public void setAuthorities(Collection authorities) { - super.setAuthorities(authorities); + if (authorities!= null) { + this.authorities = new HashSet(authorities); + } + } + + /** + * @return the extensions + */ + public Map getExtensions() { + return extensions; } + public void setExtensions(Map extensions) { + this.extensions = extensions; + } + + public void setResourceIds(Set resourceIds) { + this.resourceIds = resourceIds; + } + + // expose the superclass's utility method @Override - public void setExtensions(Map extensionProperties) { - super.setExtensions(extensionProperties); + public void setClientId(String clientId) { + super.setClientId(clientId); } + // expose the superclass's utility method @Override - public void setResourceIds(Set resourceIds) { - super.setResourceIds(resourceIds); + public void setScope(Collection scope) { + super.setScope(scope); + } + + // expose the superclass's utiltiy method + @Override + public void setRequestParameters(Map requestParameters) { + if (requestParameters != null) { + this.requestParameters = Collections.unmodifiableMap(requestParameters); + } + } + + /** + * @return the resourceIds + */ + public Set getResourceIds() { + return resourceIds; + } + + /** + * @return the authorities + */ + public Collection getAuthorities() { + return authorities; + } + + /** + * @return the approved + */ + public boolean isApproved() { + return approved; + } + + /** + * @return the redirectUri + */ + public String getRedirectUri() { + return redirectUri; } @Override diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java index ea83ec6a8..cd2cf3c63 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java @@ -16,7 +16,6 @@ package org.springframework.security.oauth2.provider; -import java.io.Serializable; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -31,22 +30,20 @@ * @author Dave Syer * */ -public class BaseRequest implements Serializable { - - private static final long serialVersionUID = 1L; +abstract class BaseRequest { /** * Resolved client ID. This may be present in the original request parameters, or in some cases may be inferred by a * processing class and inserted here. */ - private String clientId; + protected String clientId; /** * Resolved scope set, initialized (by the OAuth2RequestFactory) with the scopes originally requested. Further * processing and user interaction may alter the set of scopes that is finally granted and stored when the request * processing is complete. */ - private Set scope = new HashSet(); + protected Set scope = new HashSet(); /** * Map of parameters passed in to the Authorization Endpoint or Token Endpoint, preserved unchanged from the @@ -57,17 +54,13 @@ public class BaseRequest implements Serializable { * inside the requestParmaeters map. * */ - private Map requestParameters = Collections.unmodifiableMap(new HashMap()); + protected Map requestParameters = Collections.unmodifiableMap(new HashMap()); - public BaseRequest(String clientId) { - this.clientId = clientId; - } - public String getClientId() { return clientId; } - public void setClientId(String clientId) { + protected void setClientId(String clientId) { this.clientId = clientId; } @@ -75,7 +68,7 @@ public Set getScope() { return scope; } - public void setScope(Collection scope) { + protected void setScope(Collection scope) { if (scope != null && scope.size() == 1) { String value = scope.iterator().next(); /* @@ -100,7 +93,7 @@ public Map getRequestParameters() { return requestParameters; } - public void setRequestParameters(Map requestParameters) { + protected void setRequestParameters(Map requestParameters) { if (requestParameters != null) { this.requestParameters = Collections.unmodifiableMap(requestParameters); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java index 2108313c7..b606669f8 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java @@ -1,5 +1,8 @@ package org.springframework.security.oauth2.provider; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.Collection; import java.util.HashMap; @@ -51,12 +54,12 @@ public class OAuth2Request extends BaseRequest implements Serializable { */ private Map extensions = new HashMap(); - protected OAuth2Request(Map requestParameters, String clientId, + public OAuth2Request(Map requestParameters, String clientId, Collection authorities, boolean approved, Set scope, Set resourceIds, String redirectUri, Map extensionProperties) { - super(clientId); - setRequestParameters(requestParameters); - setScope(scope); + super.setClientId(clientId); + super.setRequestParameters(requestParameters); + super.setScope(scope); if (resourceIds != null) { this.resourceIds = new HashSet(resourceIds); } @@ -77,52 +80,62 @@ protected OAuth2Request(OAuth2Request other) { } protected OAuth2Request(String clientId) { - super(clientId); + super.setClientId(clientId); } protected OAuth2Request() { - super(""); + super(); } public String getRedirectUri() { return redirectUri; } - protected void setRedirectUri(String redirectUri) { - this.redirectUri = redirectUri; - } - public Collection getAuthorities() { return authorities; } - protected void setAuthorities(Collection authorities) { - this.authorities = authorities; - } - public boolean isApproved() { return approved; } - protected void setApproved(boolean approved) { - this.approved = approved; - } - public Set getResourceIds() { return resourceIds; } - protected void setResourceIds(Set resourceIds) { - this.resourceIds = resourceIds; - } - public Map getExtensions() { return extensions; } + + - protected void setExtensions(Map extensionProperties) { - this.extensions = extensionProperties; - } + // + // These three methods override the protected utility methods in the parent class to ensure that the setters never get called. + // + + /* (non-Javadoc) + * @see org.springframework.security.oauth2.provider.BaseRequest#setClientId(java.lang.String) + */ + @Override + protected void setClientId(String clientId) { + throw new IllegalStateException("Can't set clientId on OAuth2Request"); + } + + /* (non-Javadoc) + * @see org.springframework.security.oauth2.provider.BaseRequest#setScope(java.util.Collection) + */ + @Override + protected void setScope(Collection scope) { + throw new IllegalStateException("Can't set scope on OAuth2Request"); + } + + /* (non-Javadoc) + * @see org.springframework.security.oauth2.provider.BaseRequest#setRequestParameters(java.util.Map) + */ + @Override + protected void setRequestParameters(Map requestParameters) { + throw new IllegalStateException("Can't set request parameters on OAuth2Request"); + } /** * Update the request parameters and return a new object with the same properties except the parameters. @@ -133,6 +146,24 @@ public OAuth2Request createOAuth2Request(Map parameters) { return new OAuth2Request(parameters, getClientId(), authorities, approved, getScope(), resourceIds, redirectUri, extensions); } + + // + // Handle serialization and deserialization to capture fields from parent class + // + + private void writeObject(ObjectOutputStream out) throws IOException { + out.defaultWriteObject(); + out.writeObject(clientId); + out.writeObject(new HashMap(requestParameters)); + out.writeObject(new HashSet(scope)); + } + + private void readObject(ObjectInputStream in) throws ClassNotFoundException, IOException { + in.defaultReadObject(); + clientId = (String) in.readObject(); + requestParameters = (HashMap) in.readObject(); + scope = (HashSet) in.readObject(); + } @Override public int hashCode() { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java index 293f17e8e..e19fdf8e9 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java @@ -1,7 +1,7 @@ package org.springframework.security.oauth2.provider; -import java.io.Serializable; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -19,17 +19,14 @@ * @author Amanda Anganes * */ -public class TokenRequest extends BaseRequest implements Serializable { +public class TokenRequest extends BaseRequest { - private static final long serialVersionUID = 1L; - private String grantType; /** * Default constructor */ protected TokenRequest() { - super(""); } /** @@ -41,7 +38,7 @@ protected TokenRequest() { * @param grantType */ public TokenRequest(Map requestParameters, String clientId, Collection scope, String grantType) { - super(clientId); + super.setClientId(clientId); setRequestParameters(requestParameters); setScope(scope); this.grantType = grantType; @@ -55,6 +52,26 @@ public void setGrantType(String grantType) { this.grantType = grantType; } + // expose the superclass's utility method + @Override + public void setClientId(String clientId) { + super.setClientId(clientId); + } + + // expose the superclass's utility method + @Override + public void setScope(Collection scope) { + super.setScope(scope); + } + + // expose the superclass's utility method + @Override + public void setRequestParameters(Map requestParameters) { + if (requestParameters != null) { + this.requestParameters = Collections.unmodifiableMap(requestParameters); + } + } + public OAuth2Request createOAuth2Request(ClientDetails client) { // Remove password if present to prevent leaks Map requestParameters = getRequestParameters(); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionUtils.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionUtils.java index 7e2d3b5c5..86e114ee5 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionUtils.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionUtils.java @@ -18,7 +18,6 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.AuthorityUtils; -import org.springframework.security.oauth2.provider.BaseRequest; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; @@ -75,7 +74,7 @@ public static boolean isOAuthUserAuth(Authentication authentication) { public static boolean hasAnyScope(Authentication authentication, String[] scopes) { if (authentication instanceof OAuth2Authentication) { - BaseRequest clientAuthentication = ((OAuth2Authentication) authentication).getOAuth2Request(); + OAuth2Request clientAuthentication = ((OAuth2Authentication) authentication).getOAuth2Request(); Collection assigned = clientAuthentication.getScope(); if (assigned != null) { for (String scope : scopes) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAuthenticationKeyGenerator.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAuthenticationKeyGenerator.java index 639dd0dea..74a7278b9 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAuthenticationKeyGenerator.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAuthenticationKeyGenerator.java @@ -20,8 +20,8 @@ import java.util.Map; import org.springframework.security.oauth2.common.util.OAuth2Utils; -import org.springframework.security.oauth2.provider.BaseRequest; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.OAuth2Request; /** * Basic key generator taking into account the client id, scope, reource ids and username (principal name) if they @@ -40,7 +40,7 @@ public class DefaultAuthenticationKeyGenerator implements AuthenticationKeyGener public String extractKey(OAuth2Authentication authentication) { Map values = new LinkedHashMap(); - BaseRequest authorizationRequest = authentication.getOAuth2Request(); + OAuth2Request authorizationRequest = authentication.getOAuth2Request(); if (!authentication.isClientOnly()) { values.put(USERNAME, authentication.getName()); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java index e1355adc0..95b271889 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java @@ -28,7 +28,6 @@ import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; import org.springframework.security.oauth2.common.exceptions.InvalidScopeException; import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; -import org.springframework.security.oauth2.provider.BaseRequest; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; @@ -215,7 +214,7 @@ public String getClientId(String tokenValue) { if (authentication == null) { throw new InvalidTokenException("Invalid access token: " + tokenValue); } - BaseRequest clientAuth = authentication.getOAuth2Request(); + OAuth2Request clientAuth = authentication.getOAuth2Request(); if (clientAuth == null) { throw new InvalidTokenException("Invalid access token (no client id): " + tokenValue); } @@ -269,7 +268,7 @@ private OAuth2AccessToken createAccessToken(OAuth2Authentication authentication, * @param authorizationRequest the current authorization request * @return the access token validity period in seconds */ - protected int getAccessTokenValiditySeconds(BaseRequest clientAuth) { + protected int getAccessTokenValiditySeconds(OAuth2Request clientAuth) { if (clientDetailsService != null) { ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId()); Integer validity = client.getAccessTokenValiditySeconds(); @@ -285,7 +284,7 @@ protected int getAccessTokenValiditySeconds(BaseRequest clientAuth) { * @param authorizationRequest the current authorization request * @return the refresh token validity period in seconds */ - protected int getRefreshTokenValiditySeconds(BaseRequest clientAuth) { + protected int getRefreshTokenValiditySeconds(OAuth2Request clientAuth) { if (clientDetailsService != null) { ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId()); Integer validity = client.getRefreshTokenValiditySeconds(); @@ -302,7 +301,7 @@ protected int getRefreshTokenValiditySeconds(BaseRequest clientAuth) { * @param authorizationRequest the current authorization request * @return boolean to indicate if refresh token is supported */ - protected boolean isSupportRefreshToken(BaseRequest clientAuth) { + protected boolean isSupportRefreshToken(OAuth2Request clientAuth) { if (clientDetailsService != null) { ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId()); return client.getAuthorizedGrantTypes().contains("refresh_token"); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/vote/ScopeVoter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/vote/ScopeVoter.java index f6881b3b9..6198ecce3 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/vote/ScopeVoter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/vote/ScopeVoter.java @@ -25,9 +25,9 @@ import org.springframework.security.access.ConfigAttribute; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.common.exceptions.InsufficientScopeException; -import org.springframework.security.oauth2.provider.BaseRequest; -import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.OAuth2Request; /** *

@@ -132,7 +132,7 @@ public int vote(Authentication authentication, Object object, Collection Date: Fri, 12 Jul 2013 08:56:08 +0100 Subject: [PATCH 061/831] Remove broken links from docs and pull in some changes from wiki --- .gitignore | 4 ++++ README.md | 21 +++++++++++---------- docs/.gitignore | 4 ---- docs/Home.md | 14 +++++++------- docs/_Sidebar.md | 12 ++++++------ docs/devguide.md | 16 ++++++++++------ docs/downloads.md | 24 +++++++++++++++++++++--- docs/oauth1.md | 34 ++++++++++++++++++++++++++++++---- docs/oauth2.md | 3 +-- docs/tutorial.md | 23 ++++++++++++++--------- 10 files changed, 104 insertions(+), 51 deletions(-) delete mode 100644 docs/.gitignore diff --git a/.gitignore b/.gitignore index eaf2dd9f7..9bee68634 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ +#*# +.#* +*~ +_site/ */src/META-INF/ */src/main/java/META-INF/ samples/*/*/src/main/webapp/META-INF/ diff --git a/README.md b/README.md index 16b62e347..72943b0dc 100644 --- a/README.md +++ b/README.md @@ -5,16 +5,17 @@ Security programming models and configuration idioms. # Getting Started -[Dowload](https://github.com/SpringSource/spring-security-oauth/tags) +[Download](https://github.com/SpringSource/spring-security-oauth/tags) or clone from [GIT](https://github.com/SpringSource/spring-security-oauth) and then -use Maven (2.2.*): +use Maven (2.2.\*): $ git clone ... $ mvn install -P bootstrap Use the `bootstrap` profile only the first time - it enables some -repositories that can't be exposed in the poms by default. +repositories that can't be exposed in the poms by default. You may +find it useful to add this profile to your local `settings.xml`. SpringSource ToolSuite users (or Eclipse users with the latest m2eclipse plugin) can import the projects as existing Maven projects. @@ -24,15 +25,15 @@ Software License Version 2.0 (see license.txt). ## Samples -Samples and integration tests are in [a subdirectory](./samples). -There is a separate README there for orientation and information. -Once you have installed the artifacts locally (as per the getting -started instructions above) you should be able to +Samples and integration tests are in [a subdirectory](samples). There +is a separate README there for orientation and information. Once you +have installed the artifacts locally (as per the getting started +instructions above) you should be able to $ cd samples/oauth2/tonr $ mvn tomcat:run -and visit the app in your browser at [http://localhost:8080/tonr/][] +and visit the app in your browser at [http://localhost:8080/tonr2/](http://localhost:8080/tonr2/) to check that it works. (This is for the OAuth 2.0 sample, for the OAuth 1.0a sample just remove the "2" from the directory path.) @@ -43,7 +44,7 @@ Lists of issues addressed per release can be found in ## Additional Resources -* [Spring Security OAuth Homepage](http://static.springsource.org/spring-security/oauth) +* [Spring Security OAuth User Guide](docs/Home.md) * [Spring Security OAuth Source](http://github.com/SpringSource/spring-security-oauth) * [Spring Security OAuth Forum](http://forum.springsource.org/forumdisplay.php?f=79) @@ -72,7 +73,7 @@ None of these is essential for a pull request, but they will all help. They can request but before a merge. * Use the Spring Framework code format conventions. Import `eclipse-code-formatter.xml` from the root of the project - if you are using Eclipse. If using IntelliJ, copy `spring-intellij-code-style.xml` to ~/.IntelliJIdea*/config/codestyles + if you are using Eclipse. If using IntelliJ, copy `spring-intellij-code-style.xml` to `~/.IntelliJIdea*/config/codestyles` and select spring-intellij-code-style from Settings -> Code Styles. * Make sure all new .java files to have a simple Javadoc class comment with at least an @author tag identifying you, and preferably at least a paragraph on what the class is for. diff --git a/docs/.gitignore b/docs/.gitignore deleted file mode 100644 index 4d94ec080..000000000 --- a/docs/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -target -*.ipr -*.iml -*.iws diff --git a/docs/Home.md b/docs/Home.md index e5acb0740..a7c0dbd76 100644 --- a/docs/Home.md +++ b/docs/Home.md @@ -4,9 +4,9 @@ OAuth for Spring Security provides an [OAuth](http://oauth.net) implementation for [Spring Security](http://static.springsource.org/spring-security/site/). Support is provided for the implementation of OAuth providers and -OAuth consumers. There is support for [[Oauth 1(a)|oauth1]] (including -[[two-legged OAuth|twolegged]], a.k.a. "Signed Fetch") and for -[[OAuth 2.0|oauth2]]. +OAuth consumers. There is support for [Oauth 1(a)](oauth1.md) (including +[two-legged OAuth](twolegged.md), a.k.a. "Signed Fetch") and for +[OAuth 2.0]oauth2.md). Applying security to an application is not for the faint of heart, and OAuth is no exception. Before you get started, you're going to want to make sure you understand OAuth and the problem it's designed to address. There is good @@ -20,15 +20,15 @@ and patterns that are used. With that, you're ready to get started. Here are some useful links: -* For access to the binaries, use Maven ([[instructions here|downloads]]) +* For access to the binaries, use Maven ([instructions here](downloads.md)) * Source code is in github [at SpringSource/spring-security-oauth](https://github.com/SpringSource/spring-security-oauth). * You'll want to see OAuth for Spring Security in action, so here is a -[[tutorial]] +[tutorial](tutorial.md) -* Read a more detailed explanation in the [[developer's guide|devguide]]. +* Read a more detailed explanation in the [developer's guide](devguide.md). -* For more help and support, checkout the [[support links|support]]. +* For more help and support, checkout the [support links](support.md). diff --git a/docs/_Sidebar.md b/docs/_Sidebar.md index 309045857..e3b01c8ae 100644 --- a/docs/_Sidebar.md +++ b/docs/_Sidebar.md @@ -1,6 +1,6 @@ -* [[Home]] -* [Tuturial](wiki/tutorial) -* [OAuth 1.0](wiki/oauth1) -* [OAuth 2.0](wiki/oauth2) -* [Downloads](wiki/downloads) -* [Support](wiki/support) +* [Home](Home.md) +* [Tuturial](tutorial.md) +* [OAuth 1.0](oauth1.md) +* [OAuth 2.0](oauth2.md) +* [Downloads](downloads.md) +* [Support](support.md) diff --git a/docs/devguide.md b/docs/devguide.md index 2e45399b6..c6e5656a9 100644 --- a/docs/devguide.md +++ b/docs/devguide.md @@ -2,10 +2,14 @@ ## Preparation -You're going to want to be quite familiar with both [OAuth](http://oauth.net) (and/or [OAuth2](http://tools.ietf.org/html/draft-ietf-oauth-v2)) -and [Spring Security](http://static.springsource.org/spring-security/site/), to maximize the effectiveness of this developers guide. OAuth for -Spring Security is tightly tied to both technologies, so the more familiar you are with them, the more likely you'll be to recognize the terminology -and patterns that are used. +You're going to want to be quite familiar with +[OAuth2](http://tools.ietf.org/html/draft-ietf-oauth-v2)(and/or +[OAuth](http://oauth.net) ) and +[Spring Security](http://static.springsource.org/spring-security/site/), +to maximize the effectiveness of this developers guide. OAuth for +Spring Security is tightly tied to both technologies, so the more +familiar you are with them, the more likely you'll be to recognize the +terminology and patterns that are used. ## Options @@ -13,5 +17,5 @@ Your first decision is whether you need to leverage support for OAuth 1.0, OAuth So pick your poison: -* [[OAuth 1.0|oauth1]] -* [[OAuth 2|oauth2]] \ No newline at end of file +* [OAuth 1.0](oauth1.md) +* [OAuth 2](oauth2.md) diff --git a/docs/downloads.md b/docs/downloads.md index 67ada27d1..f2a6ac4db 100644 --- a/docs/downloads.md +++ b/docs/downloads.md @@ -1,10 +1,28 @@ # Downloads -OAuth for Spring Security is a Maven-based project. +You can download source code bundles from [Github], or clone the repository using git. OAuth for Spring Security is a Maven-based project. * groupId: `org.springframework.security.oauth` -* artifactId: `spring-security-oauth` +* artifactId: `spring-security-oauth` for OAuth 1.0a and `spring-security-oauth2` for OAuth 2.0 To download the jars, just look in the [Maven repository][mavenrepo]. -[mavenrepo]: http://shrub.appspot.com/maven.springframework.org/milestone/org/springframework/security/oauth/spring-security-oauth/ +Full releases go in Maven [central], and in the SpringSource repository but milestones and snapshots go only in the SpringSource respository. For milestones: + + + spring-milestone + Spring Maven MILESTONE Repository + http://maven.springframework.org/milestone + + +and for snapshots: + + + spring-snnapshot + Spring Maven SNAPSHOT Repository + http://maven.springframework.org/snapshot + + +[mavenrepo]: http://shrub.appspot.com/maven.springframework.org/release/org/springframework/security/oauth/spring-security-oauth/ +[central]: http://repo1.maven.org/maven2/org/springframework/security/oauth/spring-security-oauth/ +[Github]: http://github.com/SpringSource/spring-security-oauth \ No newline at end of file diff --git a/docs/oauth1.md b/docs/oauth1.md index b4b5ffedf..c7f2f6788 100644 --- a/docs/oauth1.md +++ b/docs/oauth1.md @@ -2,7 +2,7 @@ ## Introduction -This is the developers guide for the support for OAuth 1.0. For OAuth 2.0, everything is different, so [[see it's developers guide|oauth2]]. +This is the developers guide for the support for OAuth 1.0. For OAuth 2.0, everything is different, so [see it's developers guide](oauth2.md). This user guide is divided into two parts, the first for the OAuth 1.0 provider, the second for the OAuth 1.0 consumer. Here's a TOC for quick navigation: @@ -89,7 +89,7 @@ Spring Security authentication manager. ### Provider Configuration For the OAuth 1.0 provider, configuration is simplified using the custom spring configuration elements. The schema for these elements rests at -[http://www.springframework.org/schema/security/spring-security-oauth.xsd]. The namespace is `http://www.springframework.org/schema/security/oauth`. +[http://www.springframework.org/schema/security/spring-security-oauth.xsd][oauth1.xsd]. The namespace is `http://www.springframework.org/schema/security/oauth`. The following configuration elements are used to supply provider configuration: @@ -189,7 +189,7 @@ RestTemplate (new in Spring 3), but is supplied with a specific `ProtectedResour ### Consumer Configuration For the OAuth 1.0 consumer, configuration is simplified using the custom spring configuration elements. The schema for these elements rests at -[http://www.springframework.org/schema/security/spring-security-oauth.xsd](http://www.springframework.org/schema/security/spring-security-oauth.xsd). +[http://www.springframework.org/schema/security/spring-security-oauth.xsd][oauth1.xsd]. The namespace is `http://www.springframework.org/schema/security/oauth`. Two custom configuration elements are used to supply provider configuration: @@ -235,6 +235,31 @@ and an arbitrary number of `resource` child elements which are used to define th * `authorization-header-realm`: The "realm" for the HTTP authorization header. * `use10a`: Whether the resource is protected using OAuth 1.0a. Default: "true" +## Customizations Not Explicitly Supported by Namespace + +The XML DSL has extension points for some of the most common use +cases, generally specified through strategies injected through +attributes (e.g. the `token-services-ref` in the ``), but +occasionally you may need to add customizations not supported in this +way. Other cases can be handled locally without losing the benefit of +the namespace because the bean definitions created are all designed to +be easy to override. The namespace parsers create bean definitions +with fixed bean definition names (hopefully easy to guess, but it is +not hard to verify them by reading the source code of the parsers), +and all you need to do to override one part of the namespace support +is create a bean definition with the same name. For instance, the +`` element creates an `OAuthProviderProcessingFilter` which +itself has a default `ProtectedResourceProcessingFilter`, but if you +wanted to replace it you could override the bean definition: + + + + + ... + + +In this example, the explicit bean definition overrides the one created by the `` because of the ordering in the application context declaration (this is a standard Spring bean factory feature). Bean definitions created by the namespace parsers follow the convention that they start with "oauth" and generally they are the class name of the default implementation provided by the framework. + [ConsumerDetailsService]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/ConsumerDetailsService.html [ConsumerDetails]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/ConsumerDetails.html [InMemoryConsumerDetailsService]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/InMemoryConsumerDetailsService.html @@ -263,4 +288,5 @@ and an arbitrary number of `resource` child elements which are used to define th [HttpSessionBasedTokenServices]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/consumer/token/HttpSessionBasedTokenServices.html [OAuthConsumerContextFilter]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/consumer/OAuthConsumerContextFilter.html [OAuthConsumerProcessingFilter]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/consumer/OAuthConsumerProcessingFilter.html -[OAuthRestTemplate]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/consumer/OAuthRestTemplate.html \ No newline at end of file +[OAuthRestTemplate]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/consumer/OAuthRestTemplate.html +[oauth1.xsd]: http://www.springframework.org/schema/security/spring-security-oauth.xsd "oauth1.xsd" diff --git a/docs/oauth2.md b/docs/oauth2.md index e48bc32f6..c9a611f6e 100644 --- a/docs/oauth2.md +++ b/docs/oauth2.md @@ -2,7 +2,7 @@ ## Introduction -This is the user guide for the support for [`OAuth 2.0`](http://tools.ietf.org/html/draft-ietf-oauth-v2). For OAuth 1.0, everything is different, so [see its user guide][oauth1]. +This is the user guide for the support for [`OAuth 2.0`](http://tools.ietf.org/html/draft-ietf-oauth-v2). For OAuth 1.0, everything is different, so [see its user guide](oauth1.md). This user guide is divided into two parts, the first for the OAuth 2.0 provider, the second for the OAuth 2.0 client. @@ -177,7 +177,6 @@ To use Facebook as an example, there is a Facebook feature in the `tonr2` applic Facebook token responses also contain a non-compliant JSON entry for the expiry time of the token (they use `expires` instead of `expires_in`), so if you want to use the expiry time in your application you will have to decode it manually using a custom `OAuth2SerializationService`. - [oauth1]: https://github.com/SpringSource/spring-security-oauth/wiki/oauth1.html "OAuth 1.0a support" [AuthorizationEndpoint]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.html "AuthorizationEndpoint" [TokenEndpoint]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.html "TokenEndpoint" [RandomValueTokenServices]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/token/RandomValueOAuth2ProviderTokenServices.html "RandomValueTokenServices" diff --git a/docs/tutorial.md b/docs/tutorial.md index 99ffcc1d6..5cb6ad6ec 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -12,26 +12,31 @@ photo-printing application on our local machine. We'll name the photo-sharing a photo-printing application "Tonr". A user named "Marissa" (who has an account at both Sparkr and Tonr) will use Tonr to access her photos on Sparklr without ever giving Tonr her credentials to Sparklr. -There is a Sparklr application for both OAuth 1.0 and for OAuth 2.0, likewise Tonr. Download the pair for the spec that you'd like to to see -in action: +There is a Sparklr application for both OAuth 1.0 and for OAuth 2.0, +likewise Tonr. The best way to run them is to clone or download the +[repo on github](https://github.com/SpringSource/spring-security-oauth/tree) +and run from source code See the +[samples/README.md](https://github.com/SpringSource/spring-security-oauth/tree/master/samples) +for detailed instructions. OAuth 1.0|OAuth 2.0 ---------|--------- -[Sparklr 1](http://static.springsource.org/spring-security/oauth/sparklr.zip) | [Sparklr 2](http://static.springsource.org/spring-security/oauth/sparklr2.zip) -[Tonr 1](http://static.springsource.org/spring-security/oauth/tonr.zip) | [Tonr 2](http://static.springsource.org/spring-security/oauth/tonr2.zip) +Sparklr 1 | Sparklr 2 +Tonr 1 | Tonr 2 -Each application is a standard [Maven](http://maven.apache.org/) project, so you will need Maven installed. Each application -is a standard Spring MVC application with Spring Security integrated. Presumably, you're familiar with Spring and Spring Security so -the configuration files will look familiar to you. +Each application is a standard [Maven](http://maven.apache.org/) project, so you will need Maven installed. Each +application is also a Spring MVC application with Spring Security integrated. If you are familiar with Spring and Spring +Security, the configuration files will look familiar to you (the OAuth2 samples use a single application context whereas +many MVC applications use a root context and a child for the DispatcherServlet). ## Setup -Unzip the Sparklr and Tonr applications, and take a look around. Note especially the Spring configuration files in `src/main/webapp/WEB-INF`. +Checkout the Sparklr and Tonr applications, and take a look around. Note especially the Spring configuration files in `src/main/webapp/WEB-INF`. For Sparklr, you'll notice the definition of the OAuth provider mechanism and the consumer/client details along with the [standard spring security configuration](http://static.springsource.org/spring-security/site/docs/3.0.x/reference/ns-config.html) elements. For Tonr, you'll notice the definition of the OAuth consumer/client mechanism and the resource details. For more information about the necessary -components of an OAuth provider and consumer, see the [[developers guide|devguide]]. +components of an OAuth provider and consumer, see the [developers guide](devguide.md). You'll also notice the Spring Security filter chain in `applicationContext.xml` and how it's configured for OAuth support. From 15b3d3b10d3ad0c2fd1959ccc75e9efd9f4916bd Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 24 Jul 2013 13:27:59 +0100 Subject: [PATCH 062/831] Fix milestone profile --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index df816be2d..0294301d8 100644 --- a/pom.xml +++ b/pom.xml @@ -113,9 +113,9 @@ milestone - spring-release - Spring Release Repository - s3://maven.springframework.org/release + spring-milestone + Spring Milestone Repository + s3://maven.springframework.org/milestone From 323c95f0a7612bdb2289f908d21f8277173f033a Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 24 Jul 2013 13:32:45 +0100 Subject: [PATCH 063/831] [maven-release-plugin] prepare release 1.1.0.M1 --- pom.xml | 4 ++-- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index 0294301d8..bf1674eb1 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ OAuth for Spring Security Parent Project for OAuth Support for Spring Security pom - 1.1.0.BUILD-SNAPSHOT + 1.1.0.M1 http://static.springframework.org/spring-security/oauth @@ -26,7 +26,7 @@ http://github.com/SpringSource/spring-security-oauth scm:git:git://github.com/SpringSource/spring-security-oauth.git scm:git:ssh://git@github.com/SpringSource/spring-security-oauth.git - HEAD + 1.1.0.M1 JIRA diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index d737c63c9..9ad2fbb62 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 - 1.1.0.BUILD-SNAPSHOT + 1.1.0.M1 ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index 485eaf1fe..a564cff05 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 - 1.1.0.BUILD-SNAPSHOT + 1.1.0.M1 ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index a08bb0f15..0143aae96 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 - 1.1.0.BUILD-SNAPSHOT + 1.1.0.M1 ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 466cdc8e1..6b46384ae 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 1.1.0.BUILD-SNAPSHOT + 1.1.0.M1 ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index 643c02272..7b344de8e 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 1.1.0.BUILD-SNAPSHOT + 1.1.0.M1 spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index 36cc0a83a..85a370b93 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 - 1.1.0.BUILD-SNAPSHOT + 1.1.0.M1 spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 24c90d12b..1c88b6ef3 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 - 1.1.0.BUILD-SNAPSHOT + 1.1.0.M1 spring-security-oauth2 From d3a1a312e76a983844614736179e3b7fc1998406 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 24 Jul 2013 13:32:46 +0100 Subject: [PATCH 064/831] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index bf1674eb1..0294301d8 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ OAuth for Spring Security Parent Project for OAuth Support for Spring Security pom - 1.1.0.M1 + 1.1.0.BUILD-SNAPSHOT http://static.springframework.org/spring-security/oauth @@ -26,7 +26,7 @@ http://github.com/SpringSource/spring-security-oauth scm:git:git://github.com/SpringSource/spring-security-oauth.git scm:git:ssh://git@github.com/SpringSource/spring-security-oauth.git - 1.1.0.M1 + HEAD JIRA diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index 9ad2fbb62..d737c63c9 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 - 1.1.0.M1 + 1.1.0.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index a564cff05..485eaf1fe 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 - 1.1.0.M1 + 1.1.0.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 0143aae96..a08bb0f15 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 - 1.1.0.M1 + 1.1.0.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 6b46384ae..466cdc8e1 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 1.1.0.M1 + 1.1.0.BUILD-SNAPSHOT ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index 7b344de8e..643c02272 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 1.1.0.M1 + 1.1.0.BUILD-SNAPSHOT spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index 85a370b93..36cc0a83a 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 - 1.1.0.M1 + 1.1.0.BUILD-SNAPSHOT spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 1c88b6ef3..24c90d12b 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 - 1.1.0.M1 + 1.1.0.BUILD-SNAPSHOT spring-security-oauth2 From 09dfebd0e535f588d491aaefb48aa0a88ee70ce8 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 24 Jul 2013 13:32:47 +0100 Subject: [PATCH 065/831] Sync docs from master branch to docs gh-pages directory --- README.md | 2 +- _includes/README.md | 84 ++++++++++++++++++++++++++++++++++++++++++++ _includes/header.txt | 7 ++++ docs/Home.md | 19 ++++++---- docs/_Sidebar.md | 19 ++++++---- docs/devguide.md | 11 ++++-- docs/downloads.md | 9 ++++- docs/oauth1.md | 9 ++++- docs/oauth2.md | 9 ++++- docs/support.md | 9 ++++- docs/tutorial.md | 29 +++++++++------ docs/twolegged.md | 7 ++++ index.md | 6 ++++ samples/README.md | 0 14 files changed, 190 insertions(+), 30 deletions(-) create mode 100644 _includes/README.md create mode 100644 _includes/header.txt create mode 100644 index.md mode change 100755 => 100644 samples/README.md diff --git a/README.md b/README.md index 72943b0dc..9f527180a 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ Lists of issues addressed per release can be found in ## Additional Resources -* [Spring Security OAuth User Guide](docs/Home.md) +* [Spring Security OAuth User Guide](docs/Home.html) * [Spring Security OAuth Source](http://github.com/SpringSource/spring-security-oauth) * [Spring Security OAuth Forum](http://forum.springsource.org/forumdisplay.php?f=79) diff --git a/_includes/README.md b/_includes/README.md new file mode 100644 index 000000000..9f527180a --- /dev/null +++ b/_includes/README.md @@ -0,0 +1,84 @@ +This project provides support for using Spring Security with OAuth +(1a) and OAuth2. It provides features for implementing both consumers +and providers of these protocols using standard Spring and Spring +Security programming models and configuration idioms. + +# Getting Started + +[Download](https://github.com/SpringSource/spring-security-oauth/tags) +or clone from +[GIT](https://github.com/SpringSource/spring-security-oauth) and then +use Maven (2.2.\*): + + $ git clone ... + $ mvn install -P bootstrap + +Use the `bootstrap` profile only the first time - it enables some +repositories that can't be exposed in the poms by default. You may +find it useful to add this profile to your local `settings.xml`. + +SpringSource ToolSuite users (or Eclipse users with the latest +m2eclipse plugin) can import the projects as existing Maven projects. + +Spring Security OAuth is released under the terms of the Apache +Software License Version 2.0 (see license.txt). + +## Samples + +Samples and integration tests are in [a subdirectory](samples). There +is a separate README there for orientation and information. Once you +have installed the artifacts locally (as per the getting started +instructions above) you should be able to + + $ cd samples/oauth2/tonr + $ mvn tomcat:run + +and visit the app in your browser at [http://localhost:8080/tonr2/](http://localhost:8080/tonr2/) +to check that it works. (This is for the OAuth 2.0 sample, for the +OAuth 1.0a sample just remove the "2" from the directory path.) + +## Changelog + +Lists of issues addressed per release can be found in +[JIRA](https://jira.springsource.org/browse/SECOAUTH#selectedTab=com.atlassian.jira.plugin.system.project%3Aversions-panel). + +## Additional Resources + +* [Spring Security OAuth User Guide](docs/Home.html) +* [Spring Security OAuth Source](http://github.com/SpringSource/spring-security-oauth) +* [Spring Security OAuth Forum](http://forum.springsource.org/forumdisplay.php?f=79) + +# Contributing to Spring Security OAuth + +Here are some ways for you to get involved in the community: + +* Get involved with the Spring community on the Spring Community Forums. Please help out on the + [forum](http://forum.springsource.org/forumdisplay.php?f=79) by responding to questions and joining the debate. +* Create [JIRA](https://jira.springsource.org/browse/SECOAUTH) tickets for bugs and new features and comment and + vote on the ones that you are interested in. +* Github is for social coding: if you want to write code, we encourage contributions through pull requests from + [forks of this repository](http://help.github.com/forking/). If you want to contribute code this way, please + reference a JIRA ticket as well covering the specific issue you are addressing. +* Watch for upcoming articles on Spring by [subscribing](http://www.springsource.org/node/feed) to springframework.org + +Before we accept a non-trivial patch or pull request we will need you to sign the +[contributor's agreement](https://support.springsource.com/spring_committer_signup). +Signing the contributor's agreement does not grant anyone commit rights to the main repository, but it does mean that we +can accept your contributions, and you will get an author credit if we do. Active contributors might be asked to join +the core team, and given the ability to merge pull requests. + +## Code Conventions and Housekeeping + +None of these is essential for a pull request, but they will all help. They can also be added after the original pull +request but before a merge. + +* Use the Spring Framework code format conventions. Import `eclipse-code-formatter.xml` from the root of the project + if you are using Eclipse. If using IntelliJ, copy `spring-intellij-code-style.xml` to `~/.IntelliJIdea*/config/codestyles` + and select spring-intellij-code-style from Settings -> Code Styles. +* Make sure all new .java files to have a simple Javadoc class comment with at least an @author tag identifying you, and + preferably at least a paragraph on what the class is for. +* Add the ASF license header comment to all new .java files (copy from existing files in the project) +* Add yourself as an @author to the .java files that you modify substantially (moew than cosmetic changes). +* Add some Javadocs and, if you change the namespace, some XSD doc elements. +* A few unit tests would help a lot as well - someone has to do it. +* If no-one else is using your branch, please rebase it against the current master (or other target branch in the main project). diff --git a/_includes/header.txt b/_includes/header.txt new file mode 100644 index 000000000..aaecc2497 --- /dev/null +++ b/_includes/header.txt @@ -0,0 +1,7 @@ +--- +title: Docs +layout: default +home: +--- + + diff --git a/docs/Home.md b/docs/Home.md index a7c0dbd76..f48f652b6 100644 --- a/docs/Home.md +++ b/docs/Home.md @@ -1,11 +1,18 @@ +--- +title: Docs +layout: default +home: ../ +--- + + # Welcome OAuth for Spring Security provides an [OAuth](http://oauth.net) implementation for [Spring Security](http://static.springsource.org/spring-security/site/). Support is provided for the implementation of OAuth providers and -OAuth consumers. There is support for [Oauth 1(a)](oauth1.md) (including -[two-legged OAuth](twolegged.md), a.k.a. "Signed Fetch") and for +OAuth consumers. There is support for [Oauth 1(a)](oauth1.html) (including +[two-legged OAuth](twolegged.html), a.k.a. "Signed Fetch") and for [OAuth 2.0]oauth2.md). Applying security to an application is not for the faint of heart, and OAuth is no exception. Before you get started, @@ -20,15 +27,15 @@ and patterns that are used. With that, you're ready to get started. Here are some useful links: -* For access to the binaries, use Maven ([instructions here](downloads.md)) +* For access to the binaries, use Maven ([instructions here](downloads.html)) * Source code is in github [at SpringSource/spring-security-oauth](https://github.com/SpringSource/spring-security-oauth). * You'll want to see OAuth for Spring Security in action, so here is a -[tutorial](tutorial.md) +[tutorial](tutorial.html) -* Read a more detailed explanation in the [developer's guide](devguide.md). +* Read a more detailed explanation in the [developer's guide](devguide.html). -* For more help and support, checkout the [support links](support.md). +* For more help and support, checkout the [support links](support.html). diff --git a/docs/_Sidebar.md b/docs/_Sidebar.md index e3b01c8ae..981184225 100644 --- a/docs/_Sidebar.md +++ b/docs/_Sidebar.md @@ -1,6 +1,13 @@ -* [Home](Home.md) -* [Tuturial](tutorial.md) -* [OAuth 1.0](oauth1.md) -* [OAuth 2.0](oauth2.md) -* [Downloads](downloads.md) -* [Support](support.md) +--- +title: Docs +layout: default +home: ../ +--- + + +* [Home](Home.html) +* [Tuturial](tutorial.html) +* [OAuth 1.0](oauth1.html) +* [OAuth 2.0](oauth2.html) +* [Downloads](downloads.html) +* [Support](support.html) diff --git a/docs/devguide.md b/docs/devguide.md index c6e5656a9..1a2626542 100644 --- a/docs/devguide.md +++ b/docs/devguide.md @@ -1,3 +1,10 @@ +--- +title: Docs +layout: default +home: ../ +--- + + # Developers Guide ## Preparation @@ -17,5 +24,5 @@ Your first decision is whether you need to leverage support for OAuth 1.0, OAuth So pick your poison: -* [OAuth 1.0](oauth1.md) -* [OAuth 2](oauth2.md) +* [OAuth 1.0](oauth1.html) +* [OAuth 2](oauth2.html) diff --git a/docs/downloads.md b/docs/downloads.md index f2a6ac4db..ce5f6a359 100644 --- a/docs/downloads.md +++ b/docs/downloads.md @@ -1,3 +1,10 @@ +--- +title: Docs +layout: default +home: ../ +--- + + # Downloads You can download source code bundles from [Github], or clone the repository using git. OAuth for Spring Security is a Maven-based project. @@ -25,4 +32,4 @@ and for snapshots: [mavenrepo]: http://shrub.appspot.com/maven.springframework.org/release/org/springframework/security/oauth/spring-security-oauth/ [central]: http://repo1.maven.org/maven2/org/springframework/security/oauth/spring-security-oauth/ -[Github]: http://github.com/SpringSource/spring-security-oauth \ No newline at end of file +[Github]: http://github.com/SpringSource/spring-security-oauth diff --git a/docs/oauth1.md b/docs/oauth1.md index c7f2f6788..a026c7731 100644 --- a/docs/oauth1.md +++ b/docs/oauth1.md @@ -1,8 +1,15 @@ +--- +title: Docs +layout: default +home: ../ +--- + + # OAuth 1 Developers Guide ## Introduction -This is the developers guide for the support for OAuth 1.0. For OAuth 2.0, everything is different, so [see it's developers guide](oauth2.md). +This is the developers guide for the support for OAuth 1.0. For OAuth 2.0, everything is different, so [see it's developers guide](oauth2.html). This user guide is divided into two parts, the first for the OAuth 1.0 provider, the second for the OAuth 1.0 consumer. Here's a TOC for quick navigation: diff --git a/docs/oauth2.md b/docs/oauth2.md index c9a611f6e..fce1b4e19 100644 --- a/docs/oauth2.md +++ b/docs/oauth2.md @@ -1,8 +1,15 @@ +--- +title: Docs +layout: default +home: ../ +--- + + # OAuth 2 Developers Guide ## Introduction -This is the user guide for the support for [`OAuth 2.0`](http://tools.ietf.org/html/draft-ietf-oauth-v2). For OAuth 1.0, everything is different, so [see its user guide](oauth1.md). +This is the user guide for the support for [`OAuth 2.0`](http://tools.ietf.org/html/draft-ietf-oauth-v2). For OAuth 1.0, everything is different, so [see its user guide](oauth1.html). This user guide is divided into two parts, the first for the OAuth 2.0 provider, the second for the OAuth 2.0 client. diff --git a/docs/support.md b/docs/support.md index 56bffc2f3..33a075765 100644 --- a/docs/support.md +++ b/docs/support.md @@ -1,7 +1,14 @@ +--- +title: Docs +layout: default +home: ../ +--- + + # Support Questions about OAuth for Spring Security can be posed at the [forum at SpringSource](http://forum.springsource.org/forumdisplay.php?f=79). To report bugs, submit enchancement requests or add something to the wish list, use [JIRA](https://jira.springsource.org/browse/SECOAUTH). Commercial support is available through [Web Cohesion](http://www.webcohesion.com). To inquire about commercial support send an email to -"info at webcohesion dot com". \ No newline at end of file +"info at webcohesion dot com". diff --git a/docs/tutorial.md b/docs/tutorial.md index 5cb6ad6ec..c8b01b6d3 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -1,3 +1,10 @@ +--- +title: Docs +layout: default +home: ../ +--- + + # Tutorial ## Introduction @@ -36,17 +43,17 @@ Checkout the Sparklr and Tonr applications, and take a look around. Note especia For Sparklr, you'll notice the definition of the OAuth provider mechanism and the consumer/client details along with the [standard spring security configuration](http://static.springsource.org/spring-security/site/docs/3.0.x/reference/ns-config.html) elements. For Tonr, you'll notice the definition of the OAuth consumer/client mechanism and the resource details. For more information about the necessary -components of an OAuth provider and consumer, see the [developers guide](devguide.md). +components of an OAuth provider and consumer, see the [developers guide](devguide.html). You'll also notice the Spring Security filter chain in `applicationContext.xml` and how it's configured for OAuth support. ### Deploy Sparklr -``` -mvn install -cd samples/oauth(2)/sparklr -mvn tomcat:run -``` +{% highlight text %} + mvn install + cd samples/oauth(2)/sparklr + mvn tomcat:run +{% endhighlight %} Sparklr should be started on port 8080. Go ahead and browse to [http;//localhost:8080/sparklr](http;//localhost:8080/sparklr). Note the basic login page and the page that can be used to browse Marissa's photos. Logout to ensure Marissa's session is no longer valid. (Of course, @@ -57,11 +64,11 @@ confirming authorization for Marissa's protected resources.) Shutdown sparklr (it will be launched in the same container when tonr runs), then -``` -mvn install -cd samples/oauth(2)/tonr -mvn tomcat:run -``` +{% highlight text %} + mvn install + cd samples/oauth(2)/tonr + mvn tomcat:run +{% endhighlight %} Tonr should be started on port 8080. Browse to [http://localhost:8080/tonr(2)](http://localhost:8080/tonr). Note Tonr's home page has a '2' on the end if it is the oauth2 version. diff --git a/docs/twolegged.md b/docs/twolegged.md index 87880bf44..9ffbf78ef 100644 --- a/docs/twolegged.md +++ b/docs/twolegged.md @@ -1,3 +1,10 @@ +--- +title: Docs +layout: default +home: ../ +--- + + # 2-Legged OAuth Two-legged OAuth (also known as "signed fetch") is basically OAuth without the user. It's a way for a consumer (i.e. client) to make a signed request diff --git a/index.md b/index.md new file mode 100644 index 000000000..79d7be3fd --- /dev/null +++ b/index.md @@ -0,0 +1,6 @@ +--- +title: Docs +layout: default +--- + +{% include README.md %} diff --git a/samples/README.md b/samples/README.md old mode 100755 new mode 100644 From 4087fe68139aaa052c96805d1722db6b81214037 Mon Sep 17 00:00:00 2001 From: OhadR Date: Thu, 15 Aug 2013 21:36:25 +0300 Subject: [PATCH 066/831] Create SubdomainRedirectResolver there are cases where the redirect-uri consists of a subdomain, and each customer has its own subdomain, hence a different redirect-uri. So we need a resolver that will validate the URL not as the default impl (that checks startsWith() ), but something that will check only the suffix of the context path. --- .../endpoint/SubdomainRedirectResolver.java | 50 +++++++++++++++++++ .../code/TestSubdomainRedirectResolver.java | 40 +++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/SubdomainRedirectResolver.java create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestSubdomainRedirectResolver.java diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/SubdomainRedirectResolver.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/SubdomainRedirectResolver.java new file mode 100644 index 000000000..cf98a9469 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/SubdomainRedirectResolver.java @@ -0,0 +1,50 @@ +package org.springframework.security.oauth2.provider.endpoint; + +import java.net.URI; +import java.net.URISyntaxException; + +import org.apache.log4j.Logger; + +/** + * there are cases where the we would like to allow all subdomains from a specific domain + * (or other cases that regex might help to solve). this redirect resolver allows to use regex + * for this purpose. + * + * @author Ohad Redlich + * + */ +public class SubdomainRedirectResolver extends DefaultRedirectResolver +{ + private static final Logger log = Logger.getLogger(SubdomainRedirectResolver.class); + + + /** + * + * @param requestedRedirect The requested redirect URI. + * @param registeredHost The registered redirect URI - main domain. + * @return Whether the requested redirect URI "matches" the specified redirect URI. + */ + @Override + protected boolean redirectMatches(String requestedRedirect, String registeredHost) + { + String requestedHost = null; + try + { + URI requesrtedUri = new URI(requestedRedirect); + + requestedHost = requesrtedUri.getHost(); + } + catch (URISyntaxException e) + { + log.info("redirect-uri could not be parsed as a valid URI, delegating call to super; URI: " + requestedRedirect ); + return super.redirectMatches(requestedRedirect, registeredHost); + } + boolean val = requestedHost.endsWith(registeredHost); + if(!val) + { + log.error("redirect resloving failed, registered host: " + registeredHost + ", found: " + requestedHost); + } + return val; + } + +} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestSubdomainRedirectResolver.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestSubdomainRedirectResolver.java new file mode 100644 index 000000000..387d4d3f2 --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestSubdomainRedirectResolver.java @@ -0,0 +1,40 @@ +package org.springframework.security.oauth2.provider.code; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.junit.Test; +import org.springframework.security.oauth2.provider.BaseClientDetails; + +public class TestSubdomainRedirectResolver +{ + private final TestSubdomainRedirectResolver resolver = new TestSubdomainRedirectResolver(); + private final BaseClientDetails client = new BaseClientDetails(); + + { + client.setAuthorizedGrantTypes(Collections.singleton("authorization_code")); + } + + + @Test + public void testRedirectWatchdox() throws Exception + { + Set redirectUris = new HashSet(Arrays.asList("watchdox.com")); + client.setRegisteredRedirectUri(redirectUris); + String requestedRedirect = "http://anywhere.watchdox.com/something"; + assertEquals(requestedRedirect, resolver.resolveRedirect(requestedRedirect, client)); + } + + @Test + public void testRedirectBadWatchdox() throws Exception + { + Set redirectUris = new HashSet(Arrays.asList("http.*(watchdox.com).*")); + client.setRegisteredRedirectUri(redirectUris); + String requestedRedirect = "http://anywhere.google.com/something"; + assertEquals(requestedRedirect, resolver.resolveRedirect(requestedRedirect, client)); + } +} From e16f5586fd5c0b1af846b4d2c43256a37e725aec Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 21 Aug 2013 10:09:15 +0100 Subject: [PATCH 067/831] Merge SubdomainRedirectResolver into DefaultRedirectResolver --- .../endpoint/DefaultRedirectResolver.java | 40 ++++++++++++--- .../endpoint/SubdomainRedirectResolver.java | 50 ------------------- .../code/TestSubdomainRedirectResolver.java | 11 ++-- 3 files changed, 40 insertions(+), 61 deletions(-) delete mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/SubdomainRedirectResolver.java diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolver.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolver.java index 152a64715..11b146a63 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolver.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolver.java @@ -31,7 +31,7 @@ /** * Default implementation for a redirect resolver. - * + * * @author Ryan Heaton * @author Dave Syer */ @@ -39,9 +39,20 @@ public class DefaultRedirectResolver implements RedirectResolver { private Collection redirectGrantTypes = Arrays.asList("implicit", "authorization_code"); + private boolean matchSubdomains = true; + + /** + * Flag to indicate that requested URIs will match if they are a subdomain of the registered value. + * + * @param matchSubdomains the flag value to set (deafult true) + */ + public void setMatchSubdomains(boolean matchSubdomains) { + this.matchSubdomains = matchSubdomains; + } + /** * Grant types that are permitted to have a redirect uri. - * + * * @param redirectGrantTypes the redirect grant types to set */ public void setRedirectGrantTypes(Collection redirectGrantTypes) { @@ -55,7 +66,8 @@ public String resolveRedirect(String requestedRedirect, ClientDetails client) th throw new InvalidGrantException("A client must have at least one authorized grant type."); } if (!containsRedirectGrantType(authorizedGrantTypes)) { - throw new InvalidGrantException("A redirect_uri can only be used by implicit or authorization_code grant types."); + throw new InvalidGrantException( + "A redirect_uri can only be used by implicit or authorization_code grant types."); } Set redirectUris = client.getRegisteredRedirectUri(); @@ -91,7 +103,7 @@ private boolean containsRedirectGrantType(Set grantTypes) { * it is an HTTP URL. *

* For other (non-URL) cases, such as for some implicit clients, the redirect_uri must be an exact match. - * + * * @param requestedRedirect The requested redirect URI. * @param redirectUri The registered redirect URI. * @return Whether the requested redirect URI "matches" the specified redirect URI. @@ -101,8 +113,8 @@ protected boolean redirectMatches(String requestedRedirect, String redirectUri) URL req = new URL(requestedRedirect); URL reg = new URL(redirectUri); - if (reg.getProtocol().equals(req.getProtocol()) && reg.getHost().equals(req.getHost())) { - return requestedRedirect.startsWith(redirectUri); + if (reg.getProtocol().equals(req.getProtocol()) && hostMatches(reg.getHost(), req.getHost())) { + return req.getPath().startsWith(reg.getPath()); } } catch (MalformedURLException e) { @@ -110,9 +122,23 @@ protected boolean redirectMatches(String requestedRedirect, String redirectUri) return requestedRedirect.equals(redirectUri); } + /** + * Check if host matches the registered value. + * + * @param registered the registered host + * @param requested the requested host + * @return true if they match + */ + protected boolean hostMatches(String registered, String requested) { + if (matchSubdomains) { + return requested.endsWith(registered); + } + return registered.equals(requested); + } + /** * Attempt to match one of the registered URIs to the that of the requested one. - * + * * @param redirectUris the set of the registered URIs to try and find a match. This cannot be null or empty. * @param requestedRedirect the URI used as part of the request * @return the matching URI diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/SubdomainRedirectResolver.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/SubdomainRedirectResolver.java deleted file mode 100644 index cf98a9469..000000000 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/SubdomainRedirectResolver.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.springframework.security.oauth2.provider.endpoint; - -import java.net.URI; -import java.net.URISyntaxException; - -import org.apache.log4j.Logger; - -/** - * there are cases where the we would like to allow all subdomains from a specific domain - * (or other cases that regex might help to solve). this redirect resolver allows to use regex - * for this purpose. - * - * @author Ohad Redlich - * - */ -public class SubdomainRedirectResolver extends DefaultRedirectResolver -{ - private static final Logger log = Logger.getLogger(SubdomainRedirectResolver.class); - - - /** - * - * @param requestedRedirect The requested redirect URI. - * @param registeredHost The registered redirect URI - main domain. - * @return Whether the requested redirect URI "matches" the specified redirect URI. - */ - @Override - protected boolean redirectMatches(String requestedRedirect, String registeredHost) - { - String requestedHost = null; - try - { - URI requesrtedUri = new URI(requestedRedirect); - - requestedHost = requesrtedUri.getHost(); - } - catch (URISyntaxException e) - { - log.info("redirect-uri could not be parsed as a valid URI, delegating call to super; URI: " + requestedRedirect ); - return super.redirectMatches(requestedRedirect, registeredHost); - } - boolean val = requestedHost.endsWith(registeredHost); - if(!val) - { - log.error("redirect resloving failed, registered host: " + registeredHost + ", found: " + requestedHost); - } - return val; - } - -} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestSubdomainRedirectResolver.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestSubdomainRedirectResolver.java index 387d4d3f2..79f4e0612 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestSubdomainRedirectResolver.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestSubdomainRedirectResolver.java @@ -8,11 +8,13 @@ import java.util.Set; import org.junit.Test; +import org.springframework.security.oauth2.common.exceptions.RedirectMismatchException; import org.springframework.security.oauth2.provider.BaseClientDetails; +import org.springframework.security.oauth2.provider.endpoint.DefaultRedirectResolver; public class TestSubdomainRedirectResolver { - private final TestSubdomainRedirectResolver resolver = new TestSubdomainRedirectResolver(); + private final DefaultRedirectResolver resolver = new DefaultRedirectResolver(); private final BaseClientDetails client = new BaseClientDetails(); { @@ -23,18 +25,19 @@ public class TestSubdomainRedirectResolver @Test public void testRedirectWatchdox() throws Exception { - Set redirectUris = new HashSet(Arrays.asList("watchdox.com")); + Set redirectUris = new HashSet(Arrays.asList("http://watchdox.com/")); client.setRegisteredRedirectUri(redirectUris); String requestedRedirect = "http://anywhere.watchdox.com/something"; assertEquals(requestedRedirect, resolver.resolveRedirect(requestedRedirect, client)); } - @Test + @Test(expected=RedirectMismatchException.class) public void testRedirectBadWatchdox() throws Exception { - Set redirectUris = new HashSet(Arrays.asList("http.*(watchdox.com).*")); + Set redirectUris = new HashSet(Arrays.asList("http//watchdox.com")); client.setRegisteredRedirectUri(redirectUris); String requestedRedirect = "http://anywhere.google.com/something"; assertEquals(requestedRedirect, resolver.resolveRedirect(requestedRedirect, client)); } + } From 53491e832847c2cd0b13655debaec75b443c50a9 Mon Sep 17 00:00:00 2001 From: Amanda Anganes Date: Thu, 15 Aug 2013 10:35:20 -0400 Subject: [PATCH 068/831] Added responseTypes parameter to OAuth2Request --- .../oauth2/provider/AuthorizationRequest.java | 2 +- .../oauth2/provider/OAuth2Request.java | 56 +++++++++++++------ .../oauth2/provider/TokenRequest.java | 2 +- ...2ClientAuthenticationProcessingFilter.java | 2 +- .../oauth2/provider/RequestTokenFactory.java | 4 +- .../provider/TestOAuth2Authentication.java | 4 +- .../TestOAuth2AuthenticationManager.java | 2 +- ...tOAuth2AuthenticationProcessingFilter.java | 2 +- .../TestAuthorizationCodeServicesBase.java | 4 +- .../TestAuthorizationCodeTokenGranter.java | 10 ++-- ...OAuth2MethodSecurityExpressionHandler.java | 6 +- .../TestOAuth2SecurityExpressionMethods.java | 18 +++--- ...estOAuth2WebSecurityExpressionHandler.java | 4 +- .../AbstractTestDefaultTokenServices.java | 6 +- .../TestDefaultTokenServicesWithInMemory.java | 10 ++-- .../token/TestInMemoryTokenStore.java | 6 +- .../provider/token/TestTokenStoreBase.java | 20 +++---- .../oauth2/provider/vote/TestScopeVoter.java | 10 ++-- 18 files changed, 94 insertions(+), 74 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java index d5b93fd8a..26f3a7a9e 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java @@ -103,7 +103,7 @@ public AuthorizationRequest(Map authorizationParameters, Map responseTypes = new HashSet(); /** * Extension point for custom processing classes which may wish to store additional information about the OAuth2 @@ -56,7 +62,7 @@ public class OAuth2Request extends BaseRequest implements Serializable { public OAuth2Request(Map requestParameters, String clientId, Collection authorities, boolean approved, Set scope, - Set resourceIds, String redirectUri, Map extensionProperties) { + Set resourceIds, String redirectUri, Set responseTypes, Map extensionProperties) { super.setClientId(clientId); super.setRequestParameters(requestParameters); super.setScope(scope); @@ -68,6 +74,9 @@ public OAuth2Request(Map requestParameters, String clientId, } this.approved = approved; this.resourceIds = resourceIds; + if (responseTypes != null) { + this.responseTypes = new HashSet(responseTypes); + } this.redirectUri = redirectUri; if (extensionProperties != null) { this.extensions = extensionProperties; @@ -76,7 +85,7 @@ public OAuth2Request(Map requestParameters, String clientId, protected OAuth2Request(OAuth2Request other) { this(other.getRequestParameters(), other.getClientId(), other.getAuthorities(), other.isApproved(), other - .getScope(), other.getResourceIds(), other.getRedirectUri(), other.getExtensions()); + .getScope(), other.getResourceIds(), other.getRedirectUri(), other.getResponseTypes(), other.getExtensions()); } protected OAuth2Request(String clientId) { @@ -90,6 +99,10 @@ protected OAuth2Request() { public String getRedirectUri() { return redirectUri; } + + public Set getResponseTypes() { + return responseTypes; + } public Collection getAuthorities() { return authorities; @@ -136,7 +149,7 @@ protected void setScope(Collection scope) { protected void setRequestParameters(Map requestParameters) { throw new IllegalStateException("Can't set request parameters on OAuth2Request"); } - + /** * Update the request parameters and return a new object with the same properties except the parameters. * @param parameters new parameters replacing the existing ones @@ -144,7 +157,7 @@ protected void setRequestParameters(Map requestParameters) { */ public OAuth2Request createOAuth2Request(Map parameters) { return new OAuth2Request(parameters, getClientId(), authorities, approved, getScope(), resourceIds, - redirectUri, extensions); + redirectUri, responseTypes, extensions); } // @@ -168,12 +181,18 @@ private void readObject(ObjectInputStream in) throws ClassNotFoundException, IOE @Override public int hashCode() { final int prime = 31; - int result = 1; + int result = super.hashCode(); result = prime * result + (approved ? 1231 : 1237); - result = prime * result + ((authorities == null) ? 0 : authorities.hashCode()); - result = prime * result + ((extensions == null) ? 0 : extensions.hashCode()); - result = prime * result + ((redirectUri == null) ? 0 : redirectUri.hashCode()); - result = prime * result + ((resourceIds == null) ? 0 : resourceIds.hashCode()); + result = prime * result + + ((authorities == null) ? 0 : authorities.hashCode()); + result = prime * result + + ((extensions == null) ? 0 : extensions.hashCode()); + result = prime * result + + ((redirectUri == null) ? 0 : redirectUri.hashCode()); + result = prime * result + + ((resourceIds == null) ? 0 : resourceIds.hashCode()); + result = prime * result + + ((responseTypes == null) ? 0 : responseTypes.hashCode()); return result; } @@ -181,7 +200,7 @@ public int hashCode() { public boolean equals(Object obj) { if (this == obj) return true; - if (obj == null) + if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; @@ -191,26 +210,27 @@ public boolean equals(Object obj) { if (authorities == null) { if (other.authorities != null) return false; - } - else if (!authorities.equals(other.authorities)) + } else if (!authorities.equals(other.authorities)) return false; if (extensions == null) { if (other.extensions != null) return false; - } - else if (!extensions.equals(other.extensions)) + } else if (!extensions.equals(other.extensions)) return false; if (redirectUri == null) { if (other.redirectUri != null) return false; - } - else if (!redirectUri.equals(other.redirectUri)) + } else if (!redirectUri.equals(other.redirectUri)) return false; if (resourceIds == null) { if (other.resourceIds != null) return false; - } - else if (!resourceIds.equals(other.resourceIds)) + } else if (!resourceIds.equals(other.resourceIds)) + return false; + if (responseTypes == null) { + if (other.responseTypes != null) + return false; + } else if (!responseTypes.equals(other.responseTypes)) return false; return true; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java index e19fdf8e9..99c8d9a35 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java @@ -77,7 +77,7 @@ public OAuth2Request createOAuth2Request(ClientDetails client) { Map requestParameters = getRequestParameters(); HashMap modifiable = new HashMap(requestParameters); modifiable.remove("password"); - return new OAuth2Request(modifiable, client.getClientId(), client.getAuthorities(), true, this.getScope(), null, null, null); + return new OAuth2Request(modifiable, client.getClientId(), client.getAuthorities(), true, this.getScope(), null, null, null, null); } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/TestOAuth2ClientAuthenticationProcessingFilter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/TestOAuth2ClientAuthenticationProcessingFilter.java index 91a90f0ff..84cd4365f 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/TestOAuth2ClientAuthenticationProcessingFilter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/TestOAuth2ClientAuthenticationProcessingFilter.java @@ -54,7 +54,7 @@ public void testAuthentication() throws Exception { Mockito.when(restTemplate.getAccessToken()).thenReturn(new DefaultOAuth2AccessToken("FOO")); Set scopes = new HashSet(); scopes.addAll(Arrays.asList("read", "write")); - OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "client", null, false, scopes, null, null, null); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "client", null, false, scopes, null, null, null, null); this.authentication = new OAuth2Authentication(storedOAuth2Request, null); Mockito.when(tokenServices.loadAuthentication("FOO")).thenReturn(authentication); Authentication authentication = filter.attemptAuthentication(null, null); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/RequestTokenFactory.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/RequestTokenFactory.java index 7c3c93f0a..9ac364234 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/RequestTokenFactory.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/RequestTokenFactory.java @@ -30,9 +30,9 @@ public class RequestTokenFactory { public static OAuth2Request createOAuth2Request(Map requestParameters, String clientId, Collection authorities, boolean approved, Set scope, - Set resourceIds, String redirectUri, Map extensionProperties) { + Set resourceIds, String redirectUri, Set responseTypes, Map extensionProperties) { return new OAuth2Request(requestParameters, clientId, authorities, approved, scope, resourceIds, redirectUri, - extensionProperties); + responseTypes, extensionProperties); } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestOAuth2Authentication.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestOAuth2Authentication.java index 75b9ef21a..8a5396dcc 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestOAuth2Authentication.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestOAuth2Authentication.java @@ -16,7 +16,7 @@ public class TestOAuth2Authentication { private OAuth2Request request = RequestTokenFactory.createOAuth2Request(null, "id", null, false, - Collections.singleton("read"), null, null, null); + Collections.singleton("read"), null, null, null, null); private UsernamePasswordAuthenticationToken userAuthentication = new UsernamePasswordAuthenticationToken("foo", "bar", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"))); @@ -25,7 +25,7 @@ public class TestOAuth2Authentication { @Rollback public void testIsAuthenticated() { request = RequestTokenFactory.createOAuth2Request(null, "id", null, true, Collections.singleton("read"), null, - null, null); + null, null, null); OAuth2Authentication authentication = new OAuth2Authentication(request, userAuthentication); assertTrue(authentication.isAuthenticated()); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationManager.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationManager.java index 7355c1d7c..aeea4b049 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationManager.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationManager.java @@ -37,7 +37,7 @@ public class TestOAuth2AuthenticationManager { private Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala"); - private OAuth2Authentication authentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "foo", null, false, null, null, null, null), userAuthentication); + private OAuth2Authentication authentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "foo", null, false, null, null, null, null, null), userAuthentication); { manager.setTokenServices(tokenServices); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationProcessingFilter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationProcessingFilter.java index ef4e23fb2..82dd73855 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationProcessingFilter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationProcessingFilter.java @@ -43,7 +43,7 @@ public class TestOAuth2AuthenticationProcessingFilter { private Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala"); - private OAuth2Authentication authentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "foo", null, false, null, null, null, null), userAuthentication); + private OAuth2Authentication authentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "foo", null, false, null, null, null, null, null), userAuthentication); private FilterChain chain = Mockito.mock(FilterChain.class); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeServicesBase.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeServicesBase.java index 4bdc48eea..f2bcd3429 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeServicesBase.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeServicesBase.java @@ -17,7 +17,7 @@ public abstract class TestAuthorizationCodeServicesBase { @Test public void testCreateAuthorizationCode() { - OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null, null); OAuth2Authentication expectedAuthentication = new OAuth2Authentication( storedOAuth2Request, new TestAuthentication( "test2", false)); @@ -31,7 +31,7 @@ storedOAuth2Request, new TestAuthentication( @Test public void testConsumeRemovesCode() { - OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null, null); OAuth2Authentication expectedAuthentication = new OAuth2Authentication( storedOAuth2Request, new TestAuthentication( "test2", false)); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeTokenGranter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeTokenGranter.java index 69f104d26..1b59691c3 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeTokenGranter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeTokenGranter.java @@ -78,7 +78,7 @@ public void testAuthorizationCodeGrant() { parameters.clear(); parameters.put(OAuth2Utils.CLIENT_ID, "foo"); parameters.put(OAuth2Utils.SCOPE, "scope"); - OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(parameters, "foo", null, true, Collections.singleton("scope"), null, null, null); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(parameters, "foo", null, true, Collections.singleton("scope"), null, null, null, null); String code = authorizationCodeServices.createAuthorizationCode(new OAuth2Authentication( storedOAuth2Request, userAuthentication)); @@ -100,7 +100,7 @@ public void testAuthorizationParametersPreserved() { parameters.put("foo", "bar"); parameters.put(OAuth2Utils.CLIENT_ID, "foo"); parameters.put(OAuth2Utils.SCOPE, "scope"); - OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(parameters, "foo", null, true, Collections.singleton("scope"), null, null, null); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(parameters, "foo", null, true, Collections.singleton("scope"), null, null, null, null); Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); @@ -125,7 +125,7 @@ public void testAuthorizationRequestPreserved() { parameters.clear(); parameters.put(OAuth2Utils.CLIENT_ID, "foo"); parameters.put(OAuth2Utils.SCOPE, "read"); - OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(parameters, "foo", null, true, Collections.singleton("read"), Collections.singleton("resource"), null, null); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(parameters, "foo", null, true, Collections.singleton("read"), Collections.singleton("resource"), null, null, null); Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); @@ -151,7 +151,7 @@ public void testAuthorizationCodeGrantWithNoClientAuthorities() { parameters.clear(); parameters.put(OAuth2Utils.CLIENT_ID, "foo"); parameters.put(OAuth2Utils.SCOPE, "scope"); - OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(parameters, "foo", Collections. emptySet(), true, Collections.singleton("scope"), null, null, null); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(parameters, "foo", Collections. emptySet(), true, Collections.singleton("scope"), null, null, null, null); Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); @@ -176,7 +176,7 @@ public void testAuthorizationRedirectMismatch() { parameters.clear(); parameters.put(OAuth2Utils.REDIRECT_URI, "https://redirectme/"); parameters.put(OAuth2Utils.CLIENT_ID, "foo"); - OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(parameters, "foo", null, true, null, null, "https://redirectme/", null); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(parameters, "foo", null, true, null, null, "https://redirectme/", null, null); Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2MethodSecurityExpressionHandler.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2MethodSecurityExpressionHandler.java index d06773fee..e2b4cfac7 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2MethodSecurityExpressionHandler.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2MethodSecurityExpressionHandler.java @@ -52,7 +52,7 @@ public void testOauthClient() throws Exception { Authentication userAuthentication = null; OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(request.getRequestParameters(), request.getClientId(), request.getAuthorities(), request.isApproved(), request.getScope(), request.getResourceIds(), - request.getRedirectUri(), request.getExtensions()); + request.getRedirectUri(), request.getResponseTypes(), request.getExtensions()); OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); MethodInvocation invocation = new SimpleMethodInvocation(this, ReflectionUtils.findMethod(getClass(), @@ -66,7 +66,7 @@ public void testOauthClient() throws Exception { @Test public void testScopes() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); @@ -107,7 +107,7 @@ public void testReEvaluationWithDifferentRoot() throws Exception { EvaluationContext context = handler.createEvaluationContext(clientAuthentication, invocation); assertFalse((Boolean) expression.getValue(context)); - OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "foo", null, true, Collections.singleton("read"), null, null, null); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "foo", null, true, Collections.singleton("read"), null, null, null, null); OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(storedOAuth2Request, null); EvaluationContext anotherContext = handler.createEvaluationContext(oAuth2Authentication, invocation); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2SecurityExpressionMethods.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2SecurityExpressionMethods.java index c3c122baf..f07bab5d9 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2SecurityExpressionMethods.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2SecurityExpressionMethods.java @@ -47,7 +47,7 @@ public void testOauthClient() throws Exception { Authentication userAuthentication = null; OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(request.getRequestParameters(), request.getClientId(), request.getAuthorities(), request.isApproved(), request.getScope(), request.getResourceIds(), - request.getRedirectUri(), request.getExtensions()); + request.getRedirectUri(), request.getResponseTypes(), request.getExtensions()); OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); assertTrue(new OAuth2SecurityExpressionMethods(oAuth2Authentication, true).clientHasAnyRole("ROLE_CLIENT")); @@ -55,7 +55,7 @@ public void testOauthClient() throws Exception { @Test public void testScopes() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); @@ -65,7 +65,7 @@ public void testScopes() throws Exception { @Test public void testScopesFalse() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); @@ -75,7 +75,7 @@ public void testScopesFalse() throws Exception { @Test(expected = AccessDeniedException.class) public void testScopesWithException() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); @@ -84,7 +84,7 @@ public void testScopesWithException() throws Exception { @Test(expected = AccessDeniedException.class) public void testInsufficientScope() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); @@ -94,7 +94,7 @@ public void testInsufficientScope() throws Exception { @Test public void testSufficientScope() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); @@ -104,7 +104,7 @@ public void testSufficientScope() throws Exception { @Test public void testSufficientScopeWithNoPreviousScopeDecision() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, true, Collections.singleton("read"), null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, true, Collections.singleton("read"), null, null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); @@ -120,7 +120,7 @@ public void testNonOauthClient() throws Exception { @Test public void testClientOnly() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, true, Collections.singleton("read"), null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, true, Collections.singleton("read"), null, null, null, null); Authentication userAuthentication = new UsernamePasswordAuthenticationToken("foo", "bar", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"))); @@ -131,7 +131,7 @@ public void testClientOnly() throws Exception { @Test public void testOAuthUser() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, true, Collections.singleton("read"), null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, true, Collections.singleton("read"), null, null, null, null); Authentication userAuthentication = new UsernamePasswordAuthenticationToken("foo", "bar", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"))); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2WebSecurityExpressionHandler.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2WebSecurityExpressionHandler.java index 978de79fa..8d0ea65e2 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2WebSecurityExpressionHandler.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2WebSecurityExpressionHandler.java @@ -46,7 +46,7 @@ public void testOauthClient() throws Exception { request.setResourceIdsAndAuthoritiesFromClientDetails(new BaseClientDetails("foo", "", "", "client_credentials", "ROLE_CLIENT")); OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(request.getRequestParameters(), request.getClientId(), request.getAuthorities(), request.isApproved(), request.getScope(), request.getResourceIds(), - request.getRedirectUri(), request.getExtensions()); + request.getRedirectUri(), request.getResponseTypes(), request.getExtensions()); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); @@ -57,7 +57,7 @@ public void testOauthClient() throws Exception { @Test public void testScopes() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); FilterInvocation invocation = new FilterInvocation("/foo", "GET"); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractTestDefaultTokenServices.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractTestDefaultTokenServices.java index b4f7a8f4e..b1d3ba879 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractTestDefaultTokenServices.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractTestDefaultTokenServices.java @@ -171,11 +171,11 @@ public void testOneAccessTokenPerAuthentication() throws Exception { @Test public void testOneAccessTokenPerUniqueAuthentication() throws Exception { getTokenServices().createAccessToken( - new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null), + new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null, null), new TestAuthentication("test2", false))); assertEquals(1, getAccessTokenCount()); getTokenServices().createAccessToken( - new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, Collections.singleton("write"), null, null, null), + new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, Collections.singleton("write"), null, null, null, null), new TestAuthentication("test2", false))); assertEquals(2, getAccessTokenCount()); } @@ -207,7 +207,7 @@ public void testNotReuseRefreshTokenMaintainsState() throws Exception { private OAuth2Authentication createAuthentication() { - return new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null), new TestAuthentication("test2", false)); + return new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null, null), new TestAuthentication("test2", false)); } protected abstract int getAccessTokenCount(); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestDefaultTokenServicesWithInMemory.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestDefaultTokenServicesWithInMemory.java index efc085306..659179dd6 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestDefaultTokenServicesWithInMemory.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestDefaultTokenServicesWithInMemory.java @@ -41,7 +41,7 @@ public class TestDefaultTokenServicesWithInMemory extends AbstractTestDefaultTok @Test public void testExpiredToken() throws Exception { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null, null), new TestAuthentication("test2", false)); DefaultOAuth2AccessToken firstAccessToken = (DefaultOAuth2AccessToken) getTokenServices().createAccessToken( expectedAuthentication); // Make it expire (and rely on mutable state in volatile token store) @@ -53,7 +53,7 @@ public void testExpiredToken() throws Exception { @Test public void testExpiredRefreshToken() throws Exception { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null, null), new TestAuthentication("test2", false)); DefaultOAuth2AccessToken firstAccessToken = (DefaultOAuth2AccessToken) getTokenServices().createAccessToken( expectedAuthentication); assertNotNull(firstAccessToken.getRefreshToken()); @@ -69,7 +69,7 @@ public void testExpiredRefreshToken() throws Exception { @Test public void testExpiredRefreshTokenIsRenewedWithNewAccessToken() throws Exception { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null, null), new TestAuthentication("test2", false)); DefaultOAuth2AccessToken firstAccessToken = (DefaultOAuth2AccessToken) getTokenServices().createAccessToken( expectedAuthentication); assertNotNull(firstAccessToken.getRefreshToken()); @@ -96,7 +96,7 @@ public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exceptio return client; } }); - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null, null), new TestAuthentication("test2", false)); DefaultOAuth2AccessToken firstAccessToken = (DefaultOAuth2AccessToken) getTokenServices().createAccessToken( expectedAuthentication); OAuth2RefreshToken expectedExpiringRefreshToken = firstAccessToken.getRefreshToken(); @@ -127,7 +127,7 @@ public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exceptio return client; } }); - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null, null), new TestAuthentication("test2", false)); DefaultOAuth2AccessToken token = (DefaultOAuth2AccessToken) getTokenServices().createAccessToken( expectedAuthentication); assertNull(token.getRefreshToken()); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestInMemoryTokenStore.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestInMemoryTokenStore.java index dc5664395..ae7b0d22e 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestInMemoryTokenStore.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestInMemoryTokenStore.java @@ -31,7 +31,7 @@ public void createStore() { @Test public void testTokenCountConsistency() throws Exception { for (int i = 0; i <= 10; i++) { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id" + i, null, false, null, null, null, null), new TestAuthentication("test", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id" + i, null, false, null, null, null, null, null), new TestAuthentication("test", false)); DefaultOAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken" + i); expectedOAuth2AccessToken.setExpiration(new Date(System.currentTimeMillis() - 1000)); if (i > 1) { @@ -43,7 +43,7 @@ public void testTokenCountConsistency() throws Exception { @Test public void testTokenCountConsistentWithExpiryQueue() throws Exception { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null), new TestAuthentication("test", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null, null), new TestAuthentication("test", false)); DefaultOAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); expectedOAuth2AccessToken.setExpiration(new Date(System.currentTimeMillis()+10000)); for (int i = 0; i <= 10; i++) { @@ -56,7 +56,7 @@ public void testTokenCountConsistentWithExpiryQueue() throws Exception { public void testAutoFlush() throws Exception { getTokenStore().setFlushInterval(3); for (int i = 0; i <= 10; i++) { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id" + i, null, false, null, null, null, null), new TestAuthentication("test", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id" + i, null, false, null, null, null, null, null), new TestAuthentication("test", false)); DefaultOAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken" + i); expectedOAuth2AccessToken.setExpiration(new Date(System.currentTimeMillis() - 1000)); if (i > 2) { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestTokenStoreBase.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestTokenStoreBase.java index 5daccf5e5..8c637b188 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestTokenStoreBase.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestTokenStoreBase.java @@ -46,7 +46,7 @@ public void testReadingAuthenticationForTokenThatDoesNotExist() { @Test public void testStoreAccessToken() { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null, null), new TestAuthentication("test2", false)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); @@ -61,13 +61,13 @@ public void testStoreAccessToken() { @Test public void testRetrieveAccessToken() { //Test approved request - OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "id", null, true, null, null, null, null); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "id", null, true, null, null, null, null, null); OAuth2Authentication authentication = new OAuth2Authentication(storedOAuth2Request, new TestAuthentication("test2", true)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, authentication); //Test unapproved request - storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null); + storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null, null); authentication = new OAuth2Authentication(storedOAuth2Request, new TestAuthentication("test2", true)); OAuth2AccessToken actualOAuth2AccessToken = getTokenStore().getAccessToken(authentication); assertEquals(expectedOAuth2AccessToken, actualOAuth2AccessToken); @@ -84,7 +84,7 @@ public void testRetrieveAccessToken() { @Test public void testFindAccessTokensByUserName() { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null, null), new TestAuthentication("test2", false)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); @@ -94,7 +94,7 @@ public void testFindAccessTokensByUserName() { @Test public void testFindAccessTokensByClientId() { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null, null), new TestAuthentication("test2", false)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); @@ -109,7 +109,7 @@ public void testReadingAccessTokenForTokenThatDoesNotExist() { @Test public void testRefreshTokenIsNotStoredDuringAccessToken() { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null, null), new TestAuthentication("test2", false)); DefaultOAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); expectedOAuth2AccessToken.setRefreshToken(new DefaultOAuth2RefreshToken("refreshToken")); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); @@ -124,7 +124,7 @@ public void testRefreshTokenIsNotStoredDuringAccessToken() { public void testStoreRefreshToken() { DefaultOAuth2RefreshToken expectedExpiringRefreshToken = new DefaultExpiringOAuth2RefreshToken("testToken", new Date()); - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null, null), new TestAuthentication("test2", false)); getTokenStore().storeRefreshToken(expectedExpiringRefreshToken, expectedAuthentication); OAuth2RefreshToken actualExpiringRefreshToken = getTokenStore().readRefreshToken("testToken"); @@ -143,7 +143,7 @@ public void testReadingRefreshTokenForTokenThatDoesNotExist() { @Test public void testGetAccessTokenForDeletedUser() throws Exception { //Test approved request - OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "id", null, true, null, null, null, null); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "id", null, true, null, null, null, null, null); OAuth2Authentication expectedAuthentication = new OAuth2Authentication(storedOAuth2Request, new TestAuthentication("test", true)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); @@ -151,7 +151,7 @@ public void testGetAccessTokenForDeletedUser() throws Exception { assertEquals(expectedAuthentication, getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue())); //Test unapproved request - storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null); + storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null, null); OAuth2Authentication anotherAuthentication = new OAuth2Authentication(storedOAuth2Request, new TestAuthentication("test", true)); assertEquals(expectedOAuth2AccessToken, getTokenStore().getAccessToken(anotherAuthentication)); // The generated key for the authentication is the same as before, but the two auths are not equal. This could @@ -166,7 +166,7 @@ public void testGetAccessTokenForDeletedUser() throws Exception { public void testRemoveRefreshToken() { OAuth2RefreshToken expectedExpiringRefreshToken = new DefaultExpiringOAuth2RefreshToken("testToken", new Date()); - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null, null), new TestAuthentication("test2", false)); getTokenStore().storeRefreshToken(expectedExpiringRefreshToken, expectedAuthentication); getTokenStore().removeRefreshToken(expectedExpiringRefreshToken); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/TestScopeVoter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/TestScopeVoter.java index f31400591..19040a812 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/TestScopeVoter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/TestScopeVoter.java @@ -51,7 +51,7 @@ public void testAbstainIfNotOAuth2() throws Exception { @Test public void testDenyIfOAuth2AndExplictlyDenied() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); assertEquals( @@ -62,7 +62,7 @@ public void testDenyIfOAuth2AndExplictlyDenied() throws Exception { @Test public void testAccessGrantedIfScopesPresent() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); assertEquals( @@ -74,7 +74,7 @@ public void testAccessGrantedIfScopesPresent() throws Exception { @Test public void testAccessGrantedIfScopesPresentWithPrefix() throws Exception { voter.setScopePrefix("scope="); - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); assertEquals( @@ -85,7 +85,7 @@ public void testAccessGrantedIfScopesPresentWithPrefix() throws Exception { @Test public void testAccessDeniedIfWrongScopesPresent() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); voter.setThrowException(false); @@ -97,7 +97,7 @@ public void testAccessDeniedIfWrongScopesPresent() throws Exception { @Test(expected = AccessDeniedException.class) public void testExceptionThrownIfWrongScopesPresent() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); assertEquals( From 7f05a320d91958af7f10f6a5a0adbcfcd2176c89 Mon Sep 17 00:00:00 2001 From: Amanda Anganes Date: Thu, 15 Aug 2013 10:40:17 -0400 Subject: [PATCH 069/831] AuthorizationRequest.createOAuth2Request mistakenly populated the requestParameters map with the approvalParameters map. Fixed method to use correct map. --- .../security/oauth2/provider/AuthorizationRequest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java index 26f3a7a9e..14633f24a 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java @@ -103,7 +103,7 @@ public AuthorizationRequest(Map authorizationParameters, Map Date: Fri, 16 Aug 2013 08:57:16 -0400 Subject: [PATCH 070/831] Added ImplicitGrantService, mimics the AuthorizationCodeService pattern AuthorizationCodeService pattern is used by the code flow. This change allows the ImplicitTokenGranter to retrieve the original AuthorizationRequest, using the incoming TokenRequest as a key. --- ...thorizationServerBeanDefinitionParser.java | 19 +++++++++++ .../endpoint/AuthorizationEndpoint.java | 14 ++++++-- .../implicit/ImplicitGrantService.java | 33 +++++++++++++++++++ .../implicit/ImplicitTokenGranter.java | 14 +++++--- .../InMemoryImplicitGrantService.java | 27 +++++++++++++++ .../oauth2/spring-security-oauth2-1.0.xsd | 9 +++++ .../config/authorization-server-extras.xml | 3 ++ 7 files changed, 113 insertions(+), 6 deletions(-) create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitGrantService.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/InMemoryImplicitGrantService.java diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/AuthorizationServerBeanDefinitionParser.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/AuthorizationServerBeanDefinitionParser.java index 459a64e0f..a60589853 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/AuthorizationServerBeanDefinitionParser.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/AuthorizationServerBeanDefinitionParser.java @@ -35,6 +35,7 @@ import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint; import org.springframework.security.oauth2.provider.endpoint.WhitelabelApprovalEndpoint; import org.springframework.security.oauth2.provider.implicit.ImplicitTokenGranter; +import org.springframework.security.oauth2.provider.implicit.InMemoryImplicitGrantService; import org.springframework.security.oauth2.provider.password.ResourceOwnerPasswordTokenGranter; import org.springframework.security.oauth2.provider.refresh.RefreshTokenGranter; import org.springframework.util.StringUtils; @@ -65,11 +66,21 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P String errorPage = element.getAttribute("error-page"); String approvalParameter = element.getAttribute("approval-parameter-name"); String redirectResolverRef = element.getAttribute("redirect-resolver-ref"); + + String implicitGrantServiceRef = element.getAttribute("implicit-grant-service-ref"); // Create a bean definition speculatively for the auth endpoint BeanDefinitionBuilder authorizationEndpointBean = BeanDefinitionBuilder .rootBeanDefinition(AuthorizationEndpoint.class); + if (!StringUtils.hasText(implicitGrantServiceRef)) { + implicitGrantServiceRef = "inMemoryImplicitGrantService"; + BeanDefinitionBuilder implicitGrantService = BeanDefinitionBuilder + .rootBeanDefinition(InMemoryImplicitGrantService.class); + parserContext.getRegistry().registerBeanDefinition(implicitGrantServiceRef, + implicitGrantService.getBeanDefinition()); + } + if (!StringUtils.hasText(oAuth2RequestFactoryRef)) { oAuth2RequestFactoryRef = "oAuth2AuthorizationRequestManager"; BeanDefinitionBuilder oAuth2RequestManager = BeanDefinitionBuilder @@ -78,6 +89,7 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P parserContext.getRegistry().registerBeanDefinition(oAuth2RequestFactoryRef, oAuth2RequestManager.getBeanDefinition()); } + authorizationEndpointBean.addPropertyReference("implicitGrantService", implicitGrantServiceRef); ManagedList tokenGranters = null; if (!StringUtils.hasText(tokenGranterRef)) { @@ -150,6 +162,13 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P if (implicitElement != null && !"true".equalsIgnoreCase(implicitElement.getAttribute("disabled"))) { BeanDefinitionBuilder implicitGranterBean = BeanDefinitionBuilder .rootBeanDefinition(ImplicitTokenGranter.class); + + String implicitGrantServiceRef2 = implicitElement.getAttribute("implicit-grant-service-ref"); + if (!StringUtils.hasText(implicitGrantServiceRef2)) { + implicitGrantServiceRef2 = implicitGrantServiceRef; + } + implicitGranterBean.addPropertyReference("implicitGrantService", implicitGrantServiceRef2); + implicitGranterBean.addConstructorArgReference(tokenServicesRef); implicitGranterBean.addConstructorArgReference(clientDetailsRef); implicitGranterBean.addConstructorArgReference(oAuth2RequestFactoryRef); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java index 9aefbd351..2c5bc7fbd 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java @@ -40,18 +40,20 @@ import org.springframework.security.oauth2.common.exceptions.UnsupportedResponseTypeException; import org.springframework.security.oauth2.common.exceptions.UserDeniedAuthorizationException; import org.springframework.security.oauth2.common.util.OAuth2Utils; +import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientRegistrationException; import org.springframework.security.oauth2.provider.DefaultOAuth2RequestValidator; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.AuthorizationRequest; -import org.springframework.security.oauth2.provider.OAuth2RequestValidator; import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.OAuth2RequestValidator; import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.approval.DefaultUserApprovalHandler; import org.springframework.security.oauth2.provider.approval.UserApprovalHandler; import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices; +import org.springframework.security.oauth2.provider.implicit.ImplicitGrantService; +import org.springframework.security.oauth2.provider.implicit.InMemoryImplicitGrantService; import org.springframework.util.StringUtils; import org.springframework.web.HttpSessionRequiredException; import org.springframework.web.bind.annotation.ExceptionHandler; @@ -99,6 +101,8 @@ public class AuthorizationEndpoint extends AbstractEndpoint implements Initializ private SessionAttributeStore sessionAttributeStore = new DefaultSessionAttributeStore(); private OAuth2RequestValidator oAuth2RequestValidator = new DefaultOAuth2RequestValidator(); + + private ImplicitGrantService implicitGrantService = new InMemoryImplicitGrantService(); private String userApprovalPage = "forward:/oauth/confirm_access"; @@ -250,6 +254,8 @@ private ModelAndView getUserApprovalPageResponse(Map model, private ModelAndView getImplicitGrantResponse(AuthorizationRequest authorizationRequest) { try { TokenRequest tokenRequest = getOAuth2RequestFactory().createTokenRequest(authorizationRequest, "implicit"); + OAuth2Request storedOAuth2Request = getOAuth2RequestFactory().createOAuth2Request(authorizationRequest); + implicitGrantService.store(storedOAuth2Request, tokenRequest); OAuth2AccessToken accessToken = getTokenGranter().grant("implicit", tokenRequest); if (accessToken == null) { throw new UnsupportedResponseTypeException("Unsupported response type: token"); @@ -446,6 +452,10 @@ public void setUserApprovalHandler(UserApprovalHandler userApprovalHandler) { public void setoAuth2RequestValidator(OAuth2RequestValidator oAuth2RequestValidator) { this.oAuth2RequestValidator = oAuth2RequestValidator; } + + public void setImplicitGrantService(ImplicitGrantService implicitGrantService) { + this.implicitGrantService = implicitGrantService; + } @ExceptionHandler(ClientRegistrationException.class) public ModelAndView handleClientRegistrationException(Exception e, ServletWebRequest webRequest) throws Exception { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitGrantService.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitGrantService.java new file mode 100644 index 000000000..3b81c1aba --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitGrantService.java @@ -0,0 +1,33 @@ +package org.springframework.security.oauth2.provider.implicit; + +import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.TokenRequest; + +/** + * Service to associate & store an incoming AuthorizationRequest with the TokenRequest that is passed + * to the ImplicitTokenGranter during the Implicit flow. This mimics the AuthorizationCodeServices + * functionality from the Authorization Code flow, allowing the ImplicitTokenGranter to reference the original + * AuthorizationRequest, while still allowing the ImplicitTokenGranter to adhere to the TokenGranter interface. + * + * @author Amanda Anganes + * + */ +public interface ImplicitGrantService { + + /** + * Save an association between an OAuth2Request and a TokenRequest. + * + * @param originalRequest + * @param tokenRequest + */ + public void store(OAuth2Request originalRequest, TokenRequest tokenRequest); + + /** + * Look up and return the OAuth2Request associated with the given TokenRequest. + * + * @param tokenRequest + * @return + */ + public OAuth2Request remove(TokenRequest tokenRequest); + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java index 956c895ba..ec96f2029 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java @@ -23,8 +23,8 @@ import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.OAuth2RequestFactory; import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.token.AbstractTokenGranter; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; @@ -37,6 +37,8 @@ public class ImplicitTokenGranter extends AbstractTokenGranter { private static final String GRANT_TYPE = "implicit"; + private ImplicitGrantService service; + public ImplicitTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory) { super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE); } @@ -48,11 +50,15 @@ protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, Tok if (userAuth==null || !userAuth.isAuthenticated()) { throw new InsufficientAuthenticationException("There is no currently logged in user"); } - - OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, clientToken); - return new OAuth2Authentication(storedOAuth2Request, userAuth); + OAuth2Request requestForStorage = service.remove(clientToken); + + return new OAuth2Authentication(requestForStorage, userAuth); } + + public void setImplicitGrantService(ImplicitGrantService service) { + this.service = service; + } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/InMemoryImplicitGrantService.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/InMemoryImplicitGrantService.java new file mode 100644 index 000000000..c6048a4c7 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/InMemoryImplicitGrantService.java @@ -0,0 +1,27 @@ +package org.springframework.security.oauth2.provider.implicit; + +import java.util.concurrent.ConcurrentHashMap; + +import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.TokenRequest; + +/** + * In-memory implementation of the ImplicitGrantService. + * + * @author Amanda Anganes + * + */ +public class InMemoryImplicitGrantService implements ImplicitGrantService { + + protected final ConcurrentHashMap requestStore = new ConcurrentHashMap(); + + public void store(OAuth2Request originalRequest, TokenRequest tokenRequest) { + this.requestStore.put(tokenRequest, originalRequest); + } + + public OAuth2Request remove(TokenRequest tokenRequest) { + OAuth2Request request = this.requestStore.remove(tokenRequest); + return request; + } + +} diff --git a/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.0.xsd b/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.0.xsd index 00f2eaa99..08865c92e 100644 --- a/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.0.xsd +++ b/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.0.xsd @@ -235,6 +235,15 @@ + + + + The reference to the bean that defines the + implicit grant service. + + + + diff --git a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/authorization-server-extras.xml b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/authorization-server-extras.xml index 18c42fcef..93e057508 100644 --- a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/authorization-server-extras.xml +++ b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/authorization-server-extras.xml @@ -8,6 +8,7 @@ @@ -30,6 +31,8 @@ + + From c4641bc86297a7747fc32e1bcc6cea997733b9fa Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 28 Aug 2013 09:07:57 +0100 Subject: [PATCH 071/831] Compiler warnings --- .../springframework/security/oauth2/provider/OAuth2Request.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java index e235564bd..704417a7d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java @@ -164,6 +164,7 @@ public OAuth2Request createOAuth2Request(Map parameters) { // Handle serialization and deserialization to capture fields from parent class // + @SuppressWarnings({ "rawtypes", "unchecked" }) private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); out.writeObject(clientId); @@ -171,6 +172,7 @@ private void writeObject(ObjectOutputStream out) throws IOException { out.writeObject(new HashSet(scope)); } + @SuppressWarnings("unchecked") private void readObject(ObjectInputStream in) throws ClassNotFoundException, IOException { in.defaultReadObject(); clientId = (String) in.readObject(); From 3d25e8ce099ec98ff6066a04e20ece99015f411f Mon Sep 17 00:00:00 2001 From: Ramiro Aparicio Date: Fri, 23 Aug 2013 17:31:09 +0200 Subject: [PATCH 072/831] Updated OAuth2 client documentation All links for JavaDoc replaced with relative links to GH (JavaDoc was really obsolete). Reordered chapters for more streamlined reading (resource -> client -> template -> token persisting). Reworked all the resource details, client parameters and token persisting as was obsolote and misleading. *NOTES:* * Only modified the client section, if needed I can go with the provider but I am not familiarized with that part. * Please someone proofread as English is not my main language. --- docs/oauth2.md | 56 +++++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/docs/oauth2.md b/docs/oauth2.md index fce1b4e19..b8d019041 100644 --- a/docs/oauth2.md +++ b/docs/oauth2.md @@ -134,17 +134,22 @@ The following attributes can be applied to the `resource-server` element: The OAuth 2.0 client mechanism is responsible for access the OAuth 2.0 protected resources of other servers. The configuration involves establishing the relevant protected resources to which users might have access. The client also needs to be supplied with mechanisms for storing authorization codes and access tokens for users. -### Managing Protected Resources - -The entry point into your database of protected resources is defined by the [`OAuth2ProtectedResourceDetailsService`][OAuth2ProtectedResourceDetailsService]. You must define your own `OAuth2ProtectedResourceDetailsService` that will load [`OAuth2ProtectedResourceDetails`][OAuth2ProtectedResourceDetails] by id. Note the existence of an [in-memory implementation][InMemoryOAuth2ProtectedResourceDetailsService] of `OAuth2ProtectedResourceDetailsService`, which might be adequate for your needs. See "Configuring Resource Details" for more information. +### Protected Resource Configuration -### Managing Tokens +Protected resources can be defined using the `resource` configuration element. Each `resource` element is effectively a definition of a bean that is an instance of [`OAuth2ProtectedResourceDetails`][OAuth2ProtectedResourceDetails]. The `resource` element supports the following attributes: -The [`OAuth2ClientTokenServices`][OAuth2ClientTokenServices] interface defines the operations that are necessary to manage OAuth 2.0 tokens for specific users. There is an in-memory implementation provided, but it's likely you'll need to implement your own service for storing the access tokens and associated authentication instances in a persistent database. +* `id`: The id of the resource. The id is only used by the client to lookup the resource; it's never used in the OAuth protocol. It's also used as the id of the bean. +* `type`: The type (i.e. "grant type") of the resource. This is used to specify how an access token is to be obtained for this resource. Valid values include "authorization\_code", "password", and "assertion". Default value is "authorization\_code". +* `client-id`: The OAuth client id. This is the id by with the OAuth provider is to identify your client. +* `client-secret`: The secret associated with the resource. By default, no secret will be supplied for access to the resource. +* `access-token-uri`: The URI of the provider OAuth endpoint that provides the access token. +* `user-authorization-uri`: The uri to which the user will be redirected if the user is ever needed to authorize access to the resource. Note that this is not always required, depending on which OAuth 2 profiles are supported. +* `scope`: Comma-separted list of string specifying the scope of the access to the resource. By default, no scope will be specified. +* `client-authentication-scheme`: The scheme used by your client to authenticate to the access token endpoint. Suggested values: "http\_basic" and "form". Default: "http\_basic". See section 2.1 of the OAuth 2 spec. ### Client Configuration -For the OAuth 2.0 client, configuration is simplified using the custom spring configuration elements. The schema for these elements rests at [http://www.springframework.org/schema/security/spring-security-oauth2.xsd][oauth2.xsd]. The namespace is `http://www.springframework.org/schema/security/oauth2`. You need to supply the `` element with an `id` attribute - this is the bean id for a servlet `Filter` that can be added to the standard Spring Security chain, e.g. +For the OAuth 2.0 client, configuration is simplified using the custom spring configuration elements. The schema for these elements rests at [http://www.springframework.org/schema/security/spring-security-oauth2.xsd][oauth2.xsd]. The namespace is `http://www.springframework.org/schema/security/oauth2`. You need to supply the `` element with an `id` attribute - this is the bean id for a servlet `Filter` that must be added to the standard Spring Security chain, e.g. @@ -152,29 +157,26 @@ For the OAuth 2.0 client, configuration is simplified using the custom spring co - + -The `client` element is used to configure the OAuth 2.0 client mechanism. The following attributes can be applied to the `client` element: +This filter will be needed to store the current request and context, so in the case of needing to authenticate during a request it will manage the redirection to and from the OAuth authentication uri. -* `token-services-ref`: The reference to the bean that stores tokens on behalf of a user. Default value is an instance of [`InMemoryOAuth2ClientTokenServices`][InMemoryOAuth2ClientTokenServices]. -* `resource-details-service-ref`: The reference to the bean that services the known resource details. +### Accessing Protected Resources -### Protected Resource Configuration +Once you've supplied all the configuration for the resources, you can now access those resources. The suggested method for accessing those resources is by using [the `RestTemplate` introduced in Spring 3][restTemplate]. OAuth for Spring Security has provided [an extension of RestTemplate][OAuth2RestTemplate] that only needs to be supplied an instance of [`OAuth2ProtectedResourceDetails`][OAuth2ProtectedResourceDetails]. To use it with user-tokens (authorization code grants) you should consider using the XML namespace shortcut `` which creates some request and session scoped context objects so that requests for different users do not collide at runtime. -Protected resources can be defined using the `resource` configuration element. Each `resource` element is effectively a definition of a bean that is an instance of [`OAuth2ProtectedResourceDetails`][OAuth2ProtectedResourceDetails]. The `resource` element supports the following attributes: +### Persisting Tokens -* `id`: The id of the resource. The id is only used by the client to lookup the resource; it's never used in the OAuth protocol. It's also used as the id of the bean. -* `type`: The type (i.e. "grant type") of the resource. This is used to specify how an access token is to be obtained for this resource. Valid values include "authorization\_code", "password", and "assertion". Default value is "authorization\_code". -* `client-id`: The OAuth client id. This is the id by with the OAuth provider is to identify your client. -* `client-secret`: The secret associated with the resource. By default, no secret will be supplied for access to the resource. -* `access-token-uri`: The URI of the provider OAuth endpoint that provides the access token. -* `user-authorization-uri`: The uri to which the user will be redirected if the user is ever needed to authorize access to the resource. Note that this is not always required, depending on which OAuth 2 profiles are supported. -* `scope`: Comma-separted list of string specifying the scope of the access to the resource. By default, no scope will be specified. -* `client-authentication-scheme`: The scheme used by your client to authenticate to the access token endpoint. Suggested values: "http\_basic" and "form". Default: "http\_basic". See section 2.1 of the OAuth 2 spec. +The [`ClientTokenServices`](/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/ClientTokenServices.java) interface defines the operations that are necessary to persist OAuth 2.0 tokens for specific users. There is an jdbc implementation provided, but it's likely you'll need to implement your own service for storing the access tokens and associated authentication instances in a persistent database. +If you want to use this feature you need provide a specially configured [`AccessTokenProviderChain`][AccessTokenProviderChain] to your [`OAuth2RestTemplate`][OAuth2RestTemplate] e.g. -### Accessing Protected Resources + -Once you've supplied all the configuration for the resources, you can now access those resources. The suggested method for accessing those resources is by using [the `RestTemplate` introduced in Spring 3][restTemplate]. OAuth for Spring Security has provided [an extension of RestTemplate][OAuth2RestTemplate] that only needs to be supplied an instance of [`OAuth2ProtectedResourceDetails`][OAuth2ProtectedResourceDetails]. To use it with user-tokens (authorization code grants) you should consider using the XML namespace shortcut `` which creates some request and session scoped context objects so that requests for different users do not collide at runtime. + + + + + ## Customizations for Clients of External OAuth2 Providers @@ -197,11 +199,9 @@ Facebook token responses also contain a non-compliant JSON entry for the expiry [OAuth2AuthenticationProcessingFilter]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/filter/OAuth2AuthenticationProcessingFilter.html "OAuth2AuthenticationProcessingFilter" [oauth2.xsd]: http://www.springframework.org/schema/security/spring-security-oauth2.xsd "oauth2.xsd" [expressions]: http://static.springsource.org/spring-security/site/docs/3.0.x/reference/el-access.html "Expression Access Control" - [OAuth2ProtectedResourceDetailsService]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/client/OAuth2ProtectedResourceDetailsService.html "OAuth2ProtectedResourceDetailsService" - [InMemoryOAuth2ProtectedResourceDetailsService]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/client/InMemoryOAuth2ProtectedResourceDetailsService.html "InMemoryOAuth2ProtectedResourceDetailsService" - [InMemoryOAuth2ClientTokenServices]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/client/token/service/InMemoryOAuth2ConsumerTokenServices.html "InMemoryOAuth2ClientTokenServices" - [OAuth2ClientTokenServices]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/client/token/OAuth2ClientTokenServices.html "OAuth2ClientTokenServices" + + [AccessTokenProviderChain]: /spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/AccessTokenProviderChain.java + [OAuth2RestTemplate]: /spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/OAuth2RestTemplate.java + [OAuth2ProtectedResourceDetails]: /spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/resource/OAuth2ProtectedResourceDetails.java [restTemplate]: http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/web/client/RestTemplate.html "RestTemplate" - [OAuth2RestTemplate]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/client/OAuth2RestTemplate.html "OAuth2RestTemplate" - [OAuth2ProtectedResourceDetails]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/client/OAuth2ProtectedResourceDetails.html "OAuth2ProtectedResourceDetails" [Facebook]: http://developers.facebook.com/docs/authentication "Facebook" From b4ebc5951339f51424602dbe4e804f4763745016 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 28 Aug 2013 09:15:25 +0100 Subject: [PATCH 073/831] Polish oauth2 docs --- docs/oauth2.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/oauth2.md b/docs/oauth2.md index b8d019041..722960554 100644 --- a/docs/oauth2.md +++ b/docs/oauth2.md @@ -140,11 +140,11 @@ Protected resources can be defined using the `resource` configuration element. E * `id`: The id of the resource. The id is only used by the client to lookup the resource; it's never used in the OAuth protocol. It's also used as the id of the bean. * `type`: The type (i.e. "grant type") of the resource. This is used to specify how an access token is to be obtained for this resource. Valid values include "authorization\_code", "password", and "assertion". Default value is "authorization\_code". -* `client-id`: The OAuth client id. This is the id by with the OAuth provider is to identify your client. -* `client-secret`: The secret associated with the resource. By default, no secret will be supplied for access to the resource. +* `client-id`: The OAuth client id. This is the id by which the OAuth provider identifies your client. +* `client-secret`: The secret associated with the resource. By default, no secret is empty. * `access-token-uri`: The URI of the provider OAuth endpoint that provides the access token. * `user-authorization-uri`: The uri to which the user will be redirected if the user is ever needed to authorize access to the resource. Note that this is not always required, depending on which OAuth 2 profiles are supported. -* `scope`: Comma-separted list of string specifying the scope of the access to the resource. By default, no scope will be specified. +* `scope`: Comma-separted list of strings specifying the scope of the access to the resource. By default, no scope will be specified. * `client-authentication-scheme`: The scheme used by your client to authenticate to the access token endpoint. Suggested values: "http\_basic" and "form". Default: "http\_basic". See section 2.1 of the OAuth 2 spec. ### Client Configuration @@ -167,7 +167,7 @@ Once you've supplied all the configuration for the resources, you can now access ### Persisting Tokens -The [`ClientTokenServices`](/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/ClientTokenServices.java) interface defines the operations that are necessary to persist OAuth 2.0 tokens for specific users. There is an jdbc implementation provided, but it's likely you'll need to implement your own service for storing the access tokens and associated authentication instances in a persistent database. +A client does not *need* to persist tokens, but it can be nice for users to not be required to approve a new token grant every time the client app is restarted. The [`ClientTokenServices`](/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/ClientTokenServices.java) interface defines the operations that are necessary to persist OAuth 2.0 tokens for specific users. There is a JDBC implementation provided, but you can if you prefer implement your own service for storing the access tokens and associated authentication instances in a persistent database. If you want to use this feature you need provide a specially configured [`AccessTokenProviderChain`][AccessTokenProviderChain] to your [`OAuth2RestTemplate`][OAuth2RestTemplate] e.g. From ceff3dcfbd19e630e43d197a86ab147d2ccbfb5f Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 5 Sep 2013 17:33:41 +0100 Subject: [PATCH 074/831] Bump README to maven 3 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9f527180a..8c593947f 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Security programming models and configuration idioms. [Download](https://github.com/SpringSource/spring-security-oauth/tags) or clone from [GIT](https://github.com/SpringSource/spring-security-oauth) and then -use Maven (2.2.\*): +use Maven (3.0.\*) and Java (1.6 or better): $ git clone ... $ mvn install -P bootstrap From 033aa948945448f634565fe4b58908773b5c8931 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 18 Sep 2013 15:04:43 +0100 Subject: [PATCH 075/831] Remove remnants of gh-pages on master --- _includes/README.md | 84 -------------------------------------------- _includes/header.txt | 7 ---- index.md | 6 ---- 3 files changed, 97 deletions(-) delete mode 100644 _includes/README.md delete mode 100644 _includes/header.txt delete mode 100644 index.md diff --git a/_includes/README.md b/_includes/README.md deleted file mode 100644 index 9f527180a..000000000 --- a/_includes/README.md +++ /dev/null @@ -1,84 +0,0 @@ -This project provides support for using Spring Security with OAuth -(1a) and OAuth2. It provides features for implementing both consumers -and providers of these protocols using standard Spring and Spring -Security programming models and configuration idioms. - -# Getting Started - -[Download](https://github.com/SpringSource/spring-security-oauth/tags) -or clone from -[GIT](https://github.com/SpringSource/spring-security-oauth) and then -use Maven (2.2.\*): - - $ git clone ... - $ mvn install -P bootstrap - -Use the `bootstrap` profile only the first time - it enables some -repositories that can't be exposed in the poms by default. You may -find it useful to add this profile to your local `settings.xml`. - -SpringSource ToolSuite users (or Eclipse users with the latest -m2eclipse plugin) can import the projects as existing Maven projects. - -Spring Security OAuth is released under the terms of the Apache -Software License Version 2.0 (see license.txt). - -## Samples - -Samples and integration tests are in [a subdirectory](samples). There -is a separate README there for orientation and information. Once you -have installed the artifacts locally (as per the getting started -instructions above) you should be able to - - $ cd samples/oauth2/tonr - $ mvn tomcat:run - -and visit the app in your browser at [http://localhost:8080/tonr2/](http://localhost:8080/tonr2/) -to check that it works. (This is for the OAuth 2.0 sample, for the -OAuth 1.0a sample just remove the "2" from the directory path.) - -## Changelog - -Lists of issues addressed per release can be found in -[JIRA](https://jira.springsource.org/browse/SECOAUTH#selectedTab=com.atlassian.jira.plugin.system.project%3Aversions-panel). - -## Additional Resources - -* [Spring Security OAuth User Guide](docs/Home.html) -* [Spring Security OAuth Source](http://github.com/SpringSource/spring-security-oauth) -* [Spring Security OAuth Forum](http://forum.springsource.org/forumdisplay.php?f=79) - -# Contributing to Spring Security OAuth - -Here are some ways for you to get involved in the community: - -* Get involved with the Spring community on the Spring Community Forums. Please help out on the - [forum](http://forum.springsource.org/forumdisplay.php?f=79) by responding to questions and joining the debate. -* Create [JIRA](https://jira.springsource.org/browse/SECOAUTH) tickets for bugs and new features and comment and - vote on the ones that you are interested in. -* Github is for social coding: if you want to write code, we encourage contributions through pull requests from - [forks of this repository](http://help.github.com/forking/). If you want to contribute code this way, please - reference a JIRA ticket as well covering the specific issue you are addressing. -* Watch for upcoming articles on Spring by [subscribing](http://www.springsource.org/node/feed) to springframework.org - -Before we accept a non-trivial patch or pull request we will need you to sign the -[contributor's agreement](https://support.springsource.com/spring_committer_signup). -Signing the contributor's agreement does not grant anyone commit rights to the main repository, but it does mean that we -can accept your contributions, and you will get an author credit if we do. Active contributors might be asked to join -the core team, and given the ability to merge pull requests. - -## Code Conventions and Housekeeping - -None of these is essential for a pull request, but they will all help. They can also be added after the original pull -request but before a merge. - -* Use the Spring Framework code format conventions. Import `eclipse-code-formatter.xml` from the root of the project - if you are using Eclipse. If using IntelliJ, copy `spring-intellij-code-style.xml` to `~/.IntelliJIdea*/config/codestyles` - and select spring-intellij-code-style from Settings -> Code Styles. -* Make sure all new .java files to have a simple Javadoc class comment with at least an @author tag identifying you, and - preferably at least a paragraph on what the class is for. -* Add the ASF license header comment to all new .java files (copy from existing files in the project) -* Add yourself as an @author to the .java files that you modify substantially (moew than cosmetic changes). -* Add some Javadocs and, if you change the namespace, some XSD doc elements. -* A few unit tests would help a lot as well - someone has to do it. -* If no-one else is using your branch, please rebase it against the current master (or other target branch in the main project). diff --git a/_includes/header.txt b/_includes/header.txt deleted file mode 100644 index aaecc2497..000000000 --- a/_includes/header.txt +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Docs -layout: default -home: ---- - - diff --git a/index.md b/index.md deleted file mode 100644 index 79d7be3fd..000000000 --- a/index.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: Docs -layout: default ---- - -{% include README.md %} From 1fa0d37ea24cb6d9a233c2bd680d0aae7b87c309 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 12 Dec 2012 12:21:41 +0000 Subject: [PATCH 076/831] SECOAUTH-370: Add JwtTokenServices (no ConsumerTokenServices so no revokes) --- spring-security-oauth2/pom.xml | 8 + .../provider/token/AccessTokenConverter.java | 56 +++ .../token/DefaultAccessTokenConverter.java | 110 ++++++ .../DefaultUserAuthenticationConverter.java | 83 +++++ .../provider/token/JwtTokenEnhancer.java | 198 ++++++++++ .../provider/token/JwtTokenServices.java | 345 ++++++++++++++++++ .../token/UserAuthenticationConverter.java | 44 +++ .../provider/token/TestJwtTokenEnhancer.java | 114 ++++++ .../provider/token/TestJwtTokenServices.java | 248 +++++++++++++ 9 files changed, 1206 insertions(+) create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AccessTokenConverter.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultUserAuthenticationConverter.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancer.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenServices.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/UserAuthenticationConverter.java create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJwtTokenEnhancer.java create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJwtTokenServices.java diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 24c90d12b..1bb803bdc 100644 --- a/spring-security-oauth2/pom.xml +++ b/spring-security-oauth2/pom.xml @@ -15,6 +15,7 @@ 1.9.2 2.1.1 + 1.0.0.RELEASE @@ -126,6 +127,13 @@ ${spring.security.version} + + org.springframework.security + spring-security-jwt + ${spring.security.jwt.version} + true + + org.springframework.security spring-security-web diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AccessTokenConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AccessTokenConverter.java new file mode 100644 index 000000000..9d40a8be7 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AccessTokenConverter.java @@ -0,0 +1,56 @@ +/* + * Cloud Foundry 2012.02.03 Beta + * Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved. + * + * This product is licensed to you under the Apache License, Version 2.0 (the "License"). + * You may not use this product except in compliance with the License. + * + * This product includes a number of subcomponents with + * separate copyright notices and license terms. Your use of these + * subcomponents is subject to the terms and conditions of the + * subcomponent's license, as noted in the LICENSE file. + */ +package org.springframework.security.oauth2.provider.token; + +import java.util.Map; + +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.provider.OAuth2Authentication; + +/** + * Converter interface for token service implementations that store authentication data inside the token. + * + * @author Dave Syer + * + */ +public interface AccessTokenConverter { + + /** + * @param token an access token + * @param authentication the current OAuth authentication + * + * @return a map representation of the token suitable for a JSON response + * + */ + Map convertAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication); + + /** + * Recover an access token from the converted value. Half the inverse of + * {@link #convertAccessToken(OAuth2AccessToken, OAuth2Authentication)}. + * + * @param value the token value + * @param map information decoded from an access token + * @return an access token + */ + OAuth2AccessToken extractAccessToken(String value, Map map); + + /** + * Recover an {@link OAuth2Authentication} from the converted access token. Half the inverse of + * {@link #convertAccessToken(OAuth2AccessToken, OAuth2Authentication)}. + * + * @param map information decoded from an access token + * @return an authentication representing the client and user (if there is one) + */ + OAuth2Authentication extractAuthentication(Map map); + +} \ No newline at end of file diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java new file mode 100644 index 000000000..c2848789a --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java @@ -0,0 +1,110 @@ +/* + * Cloud Foundry 2012.02.03 Beta + * Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved. + * + * This product is licensed to you under the Apache License, Version 2.0 (the "License"). + * You may not use this product except in compliance with the License. + * + * This product includes a number of subcomponents with + * separate copyright notices and license terms. Your use of these + * subcomponents is subject to the terms and conditions of the + * subcomponent's license, as noted in the LICENSE file. + */ +package org.springframework.security.oauth2.provider.token; + +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; + +import org.springframework.security.core.Authentication; +import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Authentication; + +/** + * Default implementation of {@link AccessTokenConverter}. + * + * @author Dave Syer + * + */ +public class DefaultAccessTokenConverter implements AccessTokenConverter { + + private static final String AUD = "aud"; + + private static final String CLIENT_ID = "client_id"; + + private static final String EXP = "exp"; + + private static final String JTI = JwtTokenEnhancer.TOKEN_ID; + + private static final String SCOPE = OAuth2AccessToken.SCOPE; + + private UserAuthenticationConverter userTokenConverter = new DefaultUserAuthenticationConverter(); + + public Map convertAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) { + Map response = new HashMap(); + AuthorizationRequest clientToken = authentication.getAuthorizationRequest(); + + if (!authentication.isClientOnly()) { + response.putAll(userTokenConverter.convertUserAuthentication(authentication.getUserAuthentication())); + } + + response.put(SCOPE, token.getScope()); + if (token.getAdditionalInformation().containsKey(JTI)) { + response.put(JTI, token.getAdditionalInformation().get(JTI)); + } + + if (token.getExpiration() != null) { + response.put(EXP, token.getExpiration().getTime() / 1000); + } + + response.putAll(token.getAdditionalInformation()); + + response.put(CLIENT_ID, clientToken.getClientId()); + if (clientToken.getResourceIds() != null && !clientToken.getResourceIds().isEmpty()) { + response.put(AUD, clientToken.getResourceIds()); + } + return response; + } + + public OAuth2AccessToken extractAccessToken(String value, Map map) { + DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(value); + Map info = new HashMap(map); + info.remove(EXP); + info.remove(AUD); + info.remove(CLIENT_ID); + info.remove(SCOPE); + if (map.containsKey(EXP)) { + token.setExpiration(new Date((Integer) map.get(EXP) * 1000L)); + } + if (map.containsKey(JTI)) { + info.put(JTI, map.get(JTI)); + } + @SuppressWarnings("unchecked") + Collection scope = (Collection) map.get(SCOPE); + if (scope!=null) { + token.setScope(new HashSet(scope)); + } + token.setAdditionalInformation(info); + return token; + } + + public OAuth2Authentication extractAuthentication(Map map) { + Map parameters = new HashMap(); + @SuppressWarnings("unchecked") + Collection scope = (Collection) map.get(SCOPE); + Authentication user = userTokenConverter.extractAuthentication(map); + String clientId = (String) map.get(CLIENT_ID); + parameters.put(CLIENT_ID, clientId); + DefaultAuthorizationRequest request = new DefaultAuthorizationRequest(parameters); + if (scope != null) { + request.setScope(new HashSet(scope)); + } + return new OAuth2Authentication(request, user); + } + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultUserAuthenticationConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultUserAuthenticationConverter.java new file mode 100644 index 000000000..42ed6783c --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultUserAuthenticationConverter.java @@ -0,0 +1,83 @@ +/* + * Cloud Foundry 2012.02.03 Beta + * Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved. + * + * This product is licensed to you under the Apache License, Version 2.0 (the "License"). + * You may not use this product except in compliance with the License. + * + * This product includes a number of subcomponents with + * separate copyright notices and license terms. Your use of these + * subcomponents is subject to the terms and conditions of the + * subcomponent's license, as noted in the LICENSE file. + */ + +package org.springframework.security.oauth2.provider.token; + +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.util.StringUtils; + +/** + * Default implementation of {@link UserAuthenticationConverter}. Converts to and from an Authentication using only its name and + * authorities. + * + * @author Dave Syer + * + */ +public class DefaultUserAuthenticationConverter implements UserAuthenticationConverter { + + private static final String AUTHORITIES = "authorities"; + + private static final String USERNAME = "user_name"; + + private Collection defaultAuthorities; + + /** + * Default value for authorities if an Authentication is being created and the input has no data for authorities. + * Note that unless this property is set, the default Authentication created by {@link #extractAuthentication(Map)} + * will be unauthenticated. + * + * @param defaultAuthorities the defaultAuthorities to set. Default null. + */ + public void setDefaultAuthorities(String[] defaultAuthorities) { + this.defaultAuthorities = AuthorityUtils.commaSeparatedStringToAuthorityList(StringUtils + .arrayToCommaDelimitedString(defaultAuthorities)); + } + + public Map convertUserAuthentication(Authentication authentication) { + Map response = new LinkedHashMap(); + response.put(USERNAME, authentication.getName()); + if (authentication.getAuthorities() != null && !authentication.getAuthorities().isEmpty()) { + response.put(AUTHORITIES, AuthorityUtils.authorityListToSet(authentication.getAuthorities())); + } + return response; + } + + public Authentication extractAuthentication(Map map) { + if (map.containsKey(USERNAME)) { + return new UsernamePasswordAuthenticationToken(map.get(USERNAME), "N/A", getAuthorities(map)); + } + return null; + } + + private Collection getAuthorities(Map map) { + if (!map.containsKey(AUTHORITIES)) { + return defaultAuthorities; + } + Object authorities = map.get(AUTHORITIES); + if (authorities instanceof String) { + AuthorityUtils.commaSeparatedStringToAuthorityList((String) authorities); + } + if (authorities instanceof Collection) { + return AuthorityUtils.commaSeparatedStringToAuthorityList(StringUtils + .collectionToCommaDelimitedString((Collection) authorities)); + } + throw new IllegalArgumentException("Authorities must be either a String or a Collection"); + } +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancer.java new file mode 100644 index 000000000..75d5c447e --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancer.java @@ -0,0 +1,198 @@ +/* + * Cloud Foundry 2012.02.03 Beta + * Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved. + * + * This product is licensed to you under the Apache License, Version 2.0 (the "License"). + * You may not use this product except in compliance with the License. + * + * This product includes a number of subcomponents with + * separate copyright notices and license terms. Your use of these + * subcomponents is subject to the terms and conditions of the + * subcomponent's license, as noted in the LICENSE file. + */ +package org.springframework.security.oauth2.provider.token; + +import java.security.Principal; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.codehaus.jackson.map.ObjectMapper; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.security.jwt.Jwt; +import org.springframework.security.jwt.JwtHelper; +import org.springframework.security.jwt.crypto.sign.InvalidSignatureException; +import org.springframework.security.jwt.crypto.sign.MacSigner; +import org.springframework.security.jwt.crypto.sign.RsaSigner; +import org.springframework.security.jwt.crypto.sign.RsaVerifier; +import org.springframework.security.jwt.crypto.sign.SignatureVerifier; +import org.springframework.security.jwt.crypto.sign.Signer; +import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; +import org.springframework.security.oauth2.common.util.RandomValueStringGenerator; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.util.Assert; + +/** + * OAuth2 token services that produces JWT encoded token values. + * + * @author Dave Syer + * @author Luke Taylor + */ +public class JwtTokenEnhancer implements TokenEnhancer, InitializingBean { + + /** + * Field name for token id. + */ + public static final String TOKEN_ID = "jti"; + + private static final Log logger = LogFactory.getLog(JwtTokenEnhancer.class); + + private AccessTokenConverter tokenConverter = new DefaultAccessTokenConverter(); + + private ObjectMapper objectMapper = new ObjectMapper(); + + private String verifierKey = new RandomValueStringGenerator().generate(); + + private Signer signer = new MacSigner(verifierKey); + + private String signingKey = verifierKey; + + private SignatureVerifier verifier; + + /** + * Get the verification key for the token signatures. + * + * @return the key used to verify tokens + */ + public Map getKey(Principal principal) { + Map result = new LinkedHashMap(); + result.put("alg", signer.algorithm()); + result.put("value", verifierKey); + return result; + } + + /** + * Sets the JWT signing key. It can be either a simple MAC key or an RSA key. RSA keys should be in OpenSSH format, + * as produced by ssh-keygen. + * + * @param key the key to be used for signing JWTs. + */ + public void setSigningKey(String key) { + Assert.hasText(key); + key = key.trim(); + + this.signingKey = key; + + if (isPublic(key)) { + signer = new RsaSigner(key); + logger.info("Configured with RSA signing key"); + } + else { + // Assume it's a MAC key + this.verifierKey = key; + signer = new MacSigner(key); + } + } + + /** + * @return true if the key has a public verifier + */ + private boolean isPublic(String key) { + return key.startsWith("-----BEGIN"); + } + + /** + * The key used for verifying signatures produced by this class. This is not used but is returned from the endpoint + * to allow resource servers to obtain the key. + * + * For an HMAC key it will be the same value as the signing key and does not need to be set. For and RSA key, it + * should be set to the String representation of the public key, in a standard format (e.g. OpenSSH keys) + * + * @param key the signature verification key (typically an RSA public key) + */ + public void setVerifierKey(String key) { + this.verifierKey = key; + try { + new RsaSigner(verifierKey); + throw new IllegalArgumentException("Private key cannot be set as verifierKey property"); + } + catch (Exception expected) { + // Expected + } + } + + public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { + DefaultOAuth2AccessToken result = new DefaultOAuth2AccessToken(accessToken); + Map info = new LinkedHashMap(accessToken.getAdditionalInformation()); + String tokenId = result.getValue(); + if (!info.containsKey(TOKEN_ID)) { + info.put(TOKEN_ID, tokenId); + } + result.setAdditionalInformation(info); + return result.setValue(encode(result, authentication)); + } + + protected String encode(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { + String content; + try { + content = objectMapper.writeValueAsString(tokenConverter.convertAccessToken(accessToken, authentication)); + } + catch (Exception e) { + throw new IllegalStateException("Cannot convert access token to JSON", e); + } + String token = JwtHelper.encode(content, signer).getEncoded(); + return token; + } + + protected Map decode(String token) { + Jwt jwt = JwtHelper.decodeAndVerify(token, verifier); + String content = jwt.getClaims(); + try { + @SuppressWarnings("unchecked") + Map map = objectMapper.readValue(content, Map.class); + return map; + } + catch (Exception e) { + throw new InvalidTokenException("Cannot convert access token to JSON", e); + } + } + + public void afterPropertiesSet() throws Exception { + // Check the signing and verification keys match + if (signer instanceof RsaSigner) { + RsaVerifier verifier; + try { + verifier = new RsaVerifier(verifierKey); + } + catch (Exception e) { + logger.warn("Unable to create an RSA verifier from verifierKey"); + return; + } + + byte[] test = "test".getBytes(); + try { + verifier.verify(test, signer.sign(test)); + logger.info("Signing and verification RSA keys match"); + } + catch (InvalidSignatureException e) { + logger.error("Signing and verification RSA keys do not match"); + } + } + else { + // Avoid a race condition where + Assert.state(this.signingKey == this.verifierKey, + "For MAC signing you do not need to specify the verifier key separately, and if you do it must match the signing key"); + } + SignatureVerifier verifier = new MacSigner(verifierKey); + try { + verifier = new RsaVerifier(verifierKey); + } + catch (Exception e) { + logger.warn("Unable to create an RSA verifier from verifierKey"); + } + this.verifier = verifier; + } +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenServices.java new file mode 100644 index 000000000..757c34c29 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenServices.java @@ -0,0 +1,345 @@ +/* + * Cloud Foundry 2012.02.03 Beta + * Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved. + * + * This product is licensed to you under the Apache License, Version 2.0 (the "License"). + * You may not use this product except in compliance with the License. + * + * This product includes a number of subcomponents with + * separate copyright notices and license terms. Your use of these + * subcomponents is subject to the terms and conditions of the + * subcomponent's license, as noted in the LICENSE file. + */ + +package org.springframework.security.oauth2.provider.token; + +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +import org.springframework.beans.factory.InitializingBean; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.oauth2.common.DefaultExpiringOAuth2RefreshToken; +import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; +import org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.common.OAuth2RefreshToken; +import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; +import org.springframework.security.oauth2.common.exceptions.InvalidScopeException; +import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; +import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.OAuth2Authentication; + +/** + * Token services for authorization server and resource server based on JWT encoded token values. There is no need for + * shared storage because all of the state is carried in the token values. + * + * @author Dave Syer + * + */ +public class JwtTokenServices implements AuthorizationServerTokenServices, ResourceServerTokenServices, + InitializingBean { + + /** + * Field name for token id. + */ + public static final String TOKEN_ID = "jti"; + + private AccessTokenConverter tokenConverter = new DefaultAccessTokenConverter(); + + private ClientDetailsService clientDetailsService; + + private TokenEnhancer accessTokenEnhancer; + + private JwtTokenEnhancer jwtTokenEnhancer = new JwtTokenEnhancer(); + + private int refreshTokenValiditySeconds = 60 * 60 * 24 * 30; // default 30 days. + + private int accessTokenValiditySeconds = 60 * 60 * 12; // default 12 hours. + + private boolean supportRefreshToken = false; + + private boolean reuseRefreshToken = true; + + private AuthenticationKeyGenerator authenticationKeyGenerator = new DefaultAuthenticationKeyGenerator(); + + /** + * Whether to support the refresh token. + * + * @param supportRefreshToken Whether to support the refresh token. + */ + public void setSupportRefreshToken(boolean supportRefreshToken) { + this.supportRefreshToken = supportRefreshToken; + } + + /** + * Whether to reuse refresh tokens (until expired). + * + * @param reuseRefreshToken Whether to reuse refresh tokens (until expired). + */ + public void setReuseRefreshToken(boolean reuseRefreshToken) { + this.reuseRefreshToken = reuseRefreshToken; + } + + /** + * An access token enhancer that will be applied to a new token before it is saved in the token store. + * + * @param accessTokenEnhancer the access token enhancer to set + */ + public void setTokenEnhancer(TokenEnhancer accessTokenEnhancer) { + this.accessTokenEnhancer = accessTokenEnhancer; + } + + /** + * The validity (in seconds) of the refresh token. + * + * @param refreshTokenValiditySeconds The validity (in seconds) of the refresh token. + */ + public void setRefreshTokenValiditySeconds(int refreshTokenValiditySeconds) { + this.refreshTokenValiditySeconds = refreshTokenValiditySeconds; + } + + /** + * The default validity (in seconds) of the access token. Zero or negative for non-expiring tokens. If a client + * details service is set the validity period will be read from he client, defaulting to this value if not defined + * by the client. + * + * @param accessTokenValiditySeconds The validity (in seconds) of the access token. + */ + public void setAccessTokenValiditySeconds(int accessTokenValiditySeconds) { + this.accessTokenValiditySeconds = accessTokenValiditySeconds; + } + + /** + * The client details service to use for looking up clients (if necessary). Optional if the access token expiry is + * set globally via {@link #setAccessTokenValiditySeconds(int)}. + * + * @param clientDetailsService the client details service + */ + public void setClientDetailsService(ClientDetailsService clientDetailsService) { + this.clientDetailsService = clientDetailsService; + } + + /** + * The key generator that is used to extract a unique identifier for an access token. + * + * @param authenticationKeyGenerator a key generator + */ + public void setAuthenticationKeyGenerator(AuthenticationKeyGenerator authenticationKeyGenerator) { + this.authenticationKeyGenerator = authenticationKeyGenerator; + } + + /** + * The key used for verifying signatures produced by this class. This is not used but is returned from the endpoint + * to allow resource servers to obtain the key. + * + * @param key the signature verification key (typically an RSA public key) + */ + public void setVerifierKey(String key) { + jwtTokenEnhancer.setVerifierKey(key); + } + + /** + * Sets the JWT signing key. It can be either a simple MAC key or an RSA key. RSA keys should be in OpenSSH format, + * as produced by ssh-keygen. + * + * @param key the key to be used for signing JWTs. + */ + public void setSigningKey(String key) { + jwtTokenEnhancer.setSigningKey(key); + } + + public void afterPropertiesSet() throws Exception { + jwtTokenEnhancer.afterPropertiesSet(); + } + + public OAuth2Authentication loadAuthentication(String token) throws AuthenticationException { + return tokenConverter.extractAuthentication(decode(token)); + } + + public OAuth2AccessToken readAccessToken(String token) { + return tokenConverter.extractAccessToken(token, decode(token)); + } + + public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication) throws AuthenticationException { + DefaultOAuth2AccessToken result = new DefaultOAuth2AccessToken(getAccessToken(authentication)); + result.setRefreshToken(createRefreshToken(authentication)); + return result; + } + + public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, AuthorizationRequest request) + throws AuthenticationException { + + if (!supportRefreshToken) { + throw new InvalidGrantException("Invalid refresh token: " + refreshTokenValue); + } + + OAuth2Authentication authentication = loadAuthentication(refreshTokenValue); + String clientId = authentication.getAuthorizationRequest().getClientId(); + if (clientId == null || !clientId.equals(request.getClientId())) { + throw new InvalidGrantException("Wrong client for this refresh token: " + refreshTokenValue); + } + + OAuth2AccessToken refreshTokenData = readAccessToken(refreshTokenValue); + if (isExpired(refreshTokenData)) { + throw new InvalidTokenException("Invalid refresh token (expired): " + refreshTokenValue); + } + + authentication = createRefreshedAuthentication(authentication, request.getScope()); + + OAuth2AccessToken accessToken = createAccessToken(authentication); + if (!reuseRefreshToken) { + OAuth2RefreshToken refreshToken = createRefreshToken(authentication); + DefaultOAuth2AccessToken result = new DefaultOAuth2AccessToken(accessToken); + result.setRefreshToken(refreshToken); + } + + return accessToken; + } + + public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) { + + String tokenId = authenticationKeyGenerator.extractKey(authentication); + DefaultOAuth2AccessToken result = new DefaultOAuth2AccessToken(tokenId); + + Map info = new LinkedHashMap(); + info.put(TOKEN_ID, tokenId); + result.setAdditionalInformation(info); + + int validitySeconds = getAccessTokenValiditySeconds(authentication.getAuthorizationRequest()); + if (validitySeconds > 0) { + result.setExpiration(new Date(System.currentTimeMillis() + (validitySeconds * 1000L))); + } + + result.setScope(authentication.getAuthorizationRequest().getScope()); + + if (accessTokenEnhancer != null) { + result = new DefaultOAuth2AccessToken(accessTokenEnhancer.enhance(result, authentication)); + } + + DefaultOAuth2AccessToken token = result.setValue(encode(result, authentication)); + + return token; + + } + + /** + * Utility method to check if a token is expired. + * + * @param expiringToken an access token + * @return true if it is expired + */ + protected boolean isExpired(OAuth2AccessToken expiringToken) { + return expiringToken.getExpiration() != null + && System.currentTimeMillis() > expiringToken.getExpiration().getTime(); + } + + /** + * Is a refresh token supported for this client (or the global setting if + * {@link #setClientDetailsService(ClientDetailsService) clientDetailsService} is not set. + * @param authorizationRequest the current authorization request + * @return boolean to indicate if refresh token is supported + */ + protected boolean isSupportRefreshToken(AuthorizationRequest authorizationRequest) { + if (clientDetailsService != null) { + ClientDetails client = clientDetailsService.loadClientByClientId(authorizationRequest.getClientId()); + return client.getAuthorizedGrantTypes().contains("refresh_token"); + } + return this.supportRefreshToken; + } + + /** + * The access token validity period in seconds + * @param authorizationRequest the current authorization request + * @return the access token validity period in seconds + */ + protected int getAccessTokenValiditySeconds(AuthorizationRequest authorizationRequest) { + if (clientDetailsService != null) { + ClientDetails client = clientDetailsService.loadClientByClientId(authorizationRequest.getClientId()); + Integer validity = client.getAccessTokenValiditySeconds(); + if (validity != null) { + return validity; + } + } + return accessTokenValiditySeconds; + } + + /** + * The refresh token validity period in seconds + * @param authorizationRequest the current authorization request + * @return the refresh token validity period in seconds + */ + protected int getRefreshTokenValiditySeconds(AuthorizationRequest authorizationRequest) { + if (clientDetailsService != null) { + ClientDetails client = clientDetailsService.loadClientByClientId(authorizationRequest.getClientId()); + Integer validity = client.getRefreshTokenValiditySeconds(); + if (validity != null) { + return validity; + } + } + return refreshTokenValiditySeconds; + } + + /** + * @param accessToken the access token whose value needs to be encoded + * @param authentication the current authentication + * @return an access token value encoding the contents of the input token + */ + private String encode(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { + return jwtTokenEnhancer.encode(accessToken, authentication); + } + + private Map decode(String token) { + return jwtTokenEnhancer.decode(token); + } + + /** + * Create a refreshed authentication taking into account the requested scope and the scope of the original + * authentication. + * + * @param authentication The authentication. + * @param scope The scope for the refreshed token. + * @return The refreshed authentication. + * @throws InvalidScopeException If the scope requested is invalid or wider than the original scope. + */ + private OAuth2Authentication createRefreshedAuthentication(OAuth2Authentication authentication, Set scope) { + OAuth2Authentication narrowed = authentication; + if (scope != null && !scope.isEmpty()) { + AuthorizationRequest clientAuth = authentication.getAuthorizationRequest(); + Set originalScope = clientAuth.getScope(); + if (originalScope == null || !originalScope.containsAll(scope)) { + throw new InvalidScopeException("Unable to narrow the scope of the client authentication to " + scope + + ".", originalScope); + } + else { + narrowed = new OAuth2Authentication(clientAuth, authentication.getUserAuthentication()); + } + } + return narrowed; + } + + /** + * Create a refresh token (if supported) by encoding an authentication, so it can be recovered when needed without + * any need for shared storage. + * + * @param authentication the current authentication + * @return a refresh token with a JWT encoded value + */ + private ExpiringOAuth2RefreshToken createRefreshToken(OAuth2Authentication authentication) { + if (!isSupportRefreshToken(authentication.getAuthorizationRequest())) { + return null; + } + DefaultOAuth2AccessToken accessToken = new DefaultOAuth2AccessToken(getAccessToken(authentication)); + int validitySeconds = getRefreshTokenValiditySeconds(authentication.getAuthorizationRequest()); + Date expiration = new Date(System.currentTimeMillis() + (validitySeconds * 1000L)); + accessToken.setExpiration(expiration); + accessToken.setValue(encode(accessToken, authentication)); + ExpiringOAuth2RefreshToken refreshToken = new DefaultExpiringOAuth2RefreshToken(accessToken.getValue(), + expiration); + return refreshToken; + } + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/UserAuthenticationConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/UserAuthenticationConverter.java new file mode 100644 index 000000000..42e55991b --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/UserAuthenticationConverter.java @@ -0,0 +1,44 @@ +/* + * Cloud Foundry 2012.02.03 Beta + * Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved. + * + * This product is licensed to you under the Apache License, Version 2.0 (the "License"). + * You may not use this product except in compliance with the License. + * + * This product includes a number of subcomponents with + * separate copyright notices and license terms. Your use of these + * subcomponents is subject to the terms and conditions of the + * subcomponent's license, as noted in the LICENSE file. + */ + +package org.springframework.security.oauth2.provider.token; + +import java.util.Map; + +import org.springframework.security.core.Authentication; + +/** + * Utility interface for converting a user authentication to and from a Map. + * + * @author Dave Syer + * + */ +public interface UserAuthenticationConverter { + + /** + * Extract information about the user to be used in an access token (i.e. for resource servers). + * + * @param userAuthentication an authentication representing a user + * @return a map of key values representing the unique information about the user + */ + Map convertUserAuthentication(Authentication userAuthentication); + + /** + * Inverse of {@link #convertUserAuthentication(Authentication)}. Extracts an Authentication from a map. + * + * @param map a map of user information + * @return an Authentication representing the user or null if there is none + */ + Authentication extractAuthentication(Map map); + +} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJwtTokenEnhancer.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJwtTokenEnhancer.java new file mode 100644 index 000000000..e93e76de5 --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJwtTokenEnhancer.java @@ -0,0 +1,114 @@ +/** + * Cloud Foundry 2012.02.03 Beta Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved. + * + * This product is licensed to you under the Apache License, Version 2.0 (the "License"). You may not use this product + * except in compliance with the License. + * + * This product includes a number of subcomponents with separate copyright notices and license terms. Your use of these + * subcomponents is subject to the terms and conditions of the subcomponent's license, as noted in the LICENSE file. + */ +package org.springframework.security.oauth2.provider.token; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.Map; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.authentication.AnonymousAuthenticationToken; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.jwt.JwtHelper; +import org.springframework.security.jwt.crypto.sign.RsaVerifier; +import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.token.AbstractTestDefaultTokenServices.TestAuthentication; + +/** + * @author Dave Syer + * @author Luke Taylor + */ +public class TestJwtTokenEnhancer { + + private JwtTokenEnhancer tokenEnhancer; + + private Authentication userAuthentication; + + @Before + public void setUp() throws Exception { + tokenEnhancer = new JwtTokenEnhancer(); + userAuthentication = new TestAuthentication("test2", true); + } + + @Test + public void testEnhanceAccessToken() { + OAuth2Authentication authentication = new OAuth2Authentication(new DefaultAuthorizationRequest("foo", null), + userAuthentication); + OAuth2AccessToken token = tokenEnhancer.enhance(new DefaultOAuth2AccessToken("FOO"), authentication); + assertNotNull(token.getValue()); + assertEquals("FOO", token.getAdditionalInformation().get(JwtTokenEnhancer.TOKEN_ID)); + String claims = JwtHelper.decode(token.getValue()).getClaims(); + assertTrue("Wrong claims: " + claims, claims.contains("\"" + JwtTokenEnhancer.TOKEN_ID + "\"")); + } + + @Test + public void rsaKeyCreatesValidRsaSignedTokens() throws Exception { + String rsaKey = "-----BEGIN RSA PRIVATE KEY----- \n" + + "MIIBywIBAAJhAOTeb4AZ+NwOtPh+ynIgGqa6UWNVe6JyJi+loPmPZdpHtzoqubnC \n" + + "wEs6JSiSZ3rButEAw8ymgLV6iBY02hdjsl3h5Z0NWaxx8dzMZfXe4EpfB04ISoqq\n" + + "hZCxchvuSDP4eQIDAQABAmEAqUuYsuuDWFRQrZgsbGsvC7G6zn3HLIy/jnM4NiJK\n" + + "t0JhWNeN9skGsR7bqb1Sak2uWqW8ZqnqgAC32gxFRYHTavJEk6LTaHWovwDEhPqc\n" + + "Zs+vXd6tZojJQ35chR/slUEBAjEA/sAd1oFLWb6PHkaz7r2NllwUBTvXL4VcMWTS\n" + + "pN+5cU41i9fsZcHw6yZEl+ZCicDxAjEA5f3R+Bj42htNI7eylebew1+sUnFv1xT8\n" + + "jlzxSzwVkoZo+vef7OD6OcFLeInAHzAJAjEAs6izolK+3ETa1CRSwz0lPHQlnmdM\n" + + "Y/QuR5tuPt6U/saEVuJpkn4LNRtg5qt6I4JRAjAgFRYTG7irBB/wmZFp47izXEc3\n" + + "gOdvA1hvq3tlWU5REDrYt24xpviA0fvrJpwMPbECMAKDKdiDi6Q4/iBkkzNMefA8\n" + + "7HX27b9LR33don/1u/yvzMUo+lrRdKAFJ+9GPE9XFA== \n" + "-----END RSA PRIVATE KEY----- "; + tokenEnhancer.setSigningKey(rsaKey); + OAuth2Authentication authentication = new OAuth2Authentication(new DefaultAuthorizationRequest("foo", null), + userAuthentication); + OAuth2AccessToken token = tokenEnhancer.enhance(new DefaultOAuth2AccessToken("FOO"), authentication); + JwtHelper.decodeAndVerify(token.getValue(), new RsaVerifier(rsaKey)); + } + + @Test + public void publicKeyStringIsReturnedFromTokenKeyEndpoint() throws Exception { + tokenEnhancer.setVerifierKey("-----BEGIN RSA PUBLIC KEY-----\n" + + "MGgCYQDk3m+AGfjcDrT4fspyIBqmulFjVXuiciYvpaD5j2XaR7c6Krm5wsBLOiUo\n" + + "kmd6wbrRAMPMpoC1eogWNNoXY7Jd4eWdDVmscfHczGX13uBKXwdOCEqKqoWQsXIb\n" + "7kgz+HkCAwEAAQ==\n" + + "-----END RSA PUBLIC KEY-----"); + Map key = tokenEnhancer.getKey(new UsernamePasswordAuthenticationToken("foo", "bar")); + assertTrue("Wrong key: " + key, key.get("value").contains("-----BEGIN")); + } + + @Test + public void publicKeyStringIsReturnedFromTokenKeyEndpointWithNullPrincipal() throws Exception { + tokenEnhancer.setVerifierKey("-----BEGIN RSA PUBLIC KEY-----\n" + + "MGgCYQDk3m+AGfjcDrT4fspyIBqmulFjVXuiciYvpaD5j2XaR7c6Krm5wsBLOiUo\n" + + "kmd6wbrRAMPMpoC1eogWNNoXY7Jd4eWdDVmscfHczGX13uBKXwdOCEqKqoWQsXIb\n" + "7kgz+HkCAwEAAQ==\n" + + "-----END RSA PUBLIC KEY-----"); + Map key = tokenEnhancer.getKey(null); + assertTrue("Wrong key: " + key, key.get("value").contains("-----BEGIN")); + } + + @Test + public void sharedSecretIsReturnedFromTokenKeyEndpoint() throws Exception { + tokenEnhancer.setVerifierKey("someKey"); + assertEquals("{alg=HMACSHA256, value=someKey}", + tokenEnhancer.getKey(new UsernamePasswordAuthenticationToken("foo", "bar")).toString()); + } + + @Test(expected = IllegalStateException.class) + public void keysNotMatchingWithMacSigner() throws Exception { + tokenEnhancer.setSigningKey("aKey"); + tokenEnhancer.setVerifierKey("someKey"); + tokenEnhancer.afterPropertiesSet(); + } + +} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJwtTokenServices.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJwtTokenServices.java new file mode 100644 index 000000000..e4b945258 --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJwtTokenServices.java @@ -0,0 +1,248 @@ +/* + * Cloud Foundry 2012.02.03 Beta + * Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved. + * + * This product is licensed to you under the Apache License, Version 2.0 (the "License"). + * You may not use this product except in compliance with the License. + * + * This product includes a number of subcomponents with + * separate copyright notices and license terms. Your use of these + * subcomponents is subject to the terms and conditions of the + * subcomponent's license, as noted in the LICENSE file. + */ + +package org.springframework.security.oauth2.provider.token; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.jwt.JwtHelper; +import org.springframework.security.jwt.crypto.sign.MacSigner; +import org.springframework.security.oauth2.common.DefaultExpiringOAuth2RefreshToken; +import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; +import org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.common.OAuth2RefreshToken; +import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; +import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; +import org.springframework.security.oauth2.provider.BaseClientDetails; +import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.token.TokenEnhancer; +import org.springframework.test.util.ReflectionTestUtils; + +/** + * @author Dave Syer + * + */ +public class TestJwtTokenServices { + + private JwtTokenServices services = new JwtTokenServices(); + + private JwtTokenEnhancer enhancer; + + @Before + public void init() throws Exception { + services.setVerifierKey("FOO"); + services.setSigningKey("FOO"); + services.afterPropertiesSet(); + enhancer = (JwtTokenEnhancer) ReflectionTestUtils.getField(services, "jwtTokenEnhancer"); + services.setSupportRefreshToken(true); + } + + + @Test + public void testReadAccessToken() throws Exception { + String token = JwtHelper.encode("{\"client_id\":\"client\"}", new MacSigner("FOO")).getEncoded(); + OAuth2AccessToken accessToken = services.readAccessToken(token); + assertEquals(token, accessToken.getValue()); + } + + @Test + public void testLoadAuthentication() throws Exception { + String token = JwtHelper.encode("{\"client_id\":\"client\"}", new MacSigner("FOO")).getEncoded(); + OAuth2Authentication authentication = services.loadAuthentication(token); + assertEquals(null, authentication.getUserAuthentication()); + assertEquals("client", authentication.getAuthorizationRequest().getClientId()); + } + + @Test + public void testTokenEnhancerUpdatesTokens() throws Exception { + services.setTokenEnhancer(new TokenEnhancer() { + public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { + DefaultOAuth2AccessToken result = new DefaultOAuth2AccessToken(accessToken); + ExpiringOAuth2RefreshToken refreshToken = new DefaultExpiringOAuth2RefreshToken("testToken", new Date( + System.currentTimeMillis() + 100000)); + result.setRefreshToken(refreshToken); + return result; + } + }); + OAuth2Authentication authentication = createAuthentication(); + OAuth2AccessToken original = services.createAccessToken(authentication); + String result = enhancer.encode(original, authentication); + assertEquals(original.getValue(), result); + } + + @Test + public void testJwtTokenEnhancerIdempotent() throws Exception { + OAuth2Authentication authentication = createAuthentication(); + OAuth2AccessToken original = services.createAccessToken(authentication); + services.setTokenEnhancer(enhancer); + OAuth2AccessToken updated = services.createAccessToken(authentication); + assertEquals(original.getValue(), updated.getValue()); + } + + @Test + public void testRefreshedTokenIsEnhanced() throws Exception { + services.setTokenEnhancer(new TokenEnhancer() { + public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { + DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(accessToken); + token.setAdditionalInformation(Collections.singletonMap("foo", "bar")); + return token; + } + }); + + OAuth2AccessToken accessToken = services.createAccessToken(createAuthentication()); + assertEquals("bar", accessToken.getAdditionalInformation().get("foo")); + OAuth2AccessToken refreshedAccessToken = services.refreshAccessToken( + accessToken.getRefreshToken().getValue(), new DefaultAuthorizationRequest("id", null)); + assertEquals("bar", refreshedAccessToken.getAdditionalInformation().get("foo")); + } + + @Test + public void testRefreshedTokenHasScopes() throws Exception { + ExpiringOAuth2RefreshToken expectedExpiringRefreshToken = (ExpiringOAuth2RefreshToken) services.createAccessToken(createAuthentication()).getRefreshToken(); + OAuth2AccessToken refreshedAccessToken = services.refreshAccessToken( + expectedExpiringRefreshToken.getValue(), new DefaultAuthorizationRequest("id", null)); + assertEquals("[read]", refreshedAccessToken.getScope().toString()); + } + + @Test(expected=InvalidGrantException.class) + public void testRefreshedTokenInvalidWithWrongClient() throws Exception { + ExpiringOAuth2RefreshToken expectedExpiringRefreshToken = (ExpiringOAuth2RefreshToken) services.createAccessToken(createAuthentication()).getRefreshToken(); + OAuth2AccessToken refreshedAccessToken = services.refreshAccessToken( + expectedExpiringRefreshToken.getValue(), new DefaultAuthorizationRequest("wrong", null)); + assertEquals("[read]", refreshedAccessToken.getScope().toString()); + } + + @Test + public void testUnlimitedTokenExpiry() throws Exception { + services.setAccessTokenValiditySeconds(0); + OAuth2AccessToken accessToken = services.createAccessToken(createAuthentication()); + assertEquals(0, accessToken.getExpiresIn()); + assertEquals(null, accessToken.getExpiration()); + } + + @Test + public void testDefaultTokenExpiry() throws Exception { + services.setAccessTokenValiditySeconds(100); + OAuth2AccessToken accessToken = services.createAccessToken(createAuthentication()); + assertTrue(100 >= accessToken.getExpiresIn()); + } + + @Test + public void testClientSpecificTokenExpiry() throws Exception { + services.setAccessTokenValiditySeconds(1000); + services.setClientDetailsService(new ClientDetailsService() { + public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exception { + BaseClientDetails client = new BaseClientDetails(); + client.setAccessTokenValiditySeconds(100); + return client; + } + }); + OAuth2AccessToken accessToken = services.createAccessToken(createAuthentication()); + assertTrue(100 >= accessToken.getExpiresIn()); + } + + @Test + public void testClientSpecificRefreshTokenExpiry() throws Exception { + services.setRefreshTokenValiditySeconds(1000); + services.setClientDetailsService(new ClientDetailsService() { + public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exception { + BaseClientDetails client = new BaseClientDetails(); + client.setRefreshTokenValiditySeconds(100); + client.setAuthorizedGrantTypes(Arrays.asList("authorization_code", "refresh_token")); + return client; + } + }); + OAuth2AccessToken accessToken = services.createAccessToken(createAuthentication()); + DefaultExpiringOAuth2RefreshToken refreshToken = (DefaultExpiringOAuth2RefreshToken) accessToken + .getRefreshToken(); + Date expectedExpiryDate = new Date(System.currentTimeMillis() + 102 * 1000L); + assertTrue(expectedExpiryDate.after(refreshToken.getExpiration())); + } + + @Test + public void testOneAccessTokenPerAuthentication() throws Exception { + OAuth2Authentication authentication = createAuthentication(); + OAuth2AccessToken first = services.createAccessToken(authentication); + OAuth2AccessToken second = services.createAccessToken(authentication); + assertEquals(first, second); + } + + @Test + public void testOneAccessTokenPerUniqueAuthentication() throws Exception { + services.createAccessToken( + new OAuth2Authentication(new DefaultAuthorizationRequest("id", Collections.singleton("read")), + new TestAuthentication("test2", false))); + services.createAccessToken( + new OAuth2Authentication(new DefaultAuthorizationRequest("id", Collections.singleton("write")), + new TestAuthentication("test2", false))); + } + + @Test + public void testRefreshTokenMaintainsState() throws Exception { + services.setSupportRefreshToken(true); + OAuth2AccessToken accessToken = services.createAccessToken(createAuthentication()); + OAuth2RefreshToken expectedExpiringRefreshToken = accessToken.getRefreshToken(); + OAuth2AccessToken refreshedAccessToken = services.refreshAccessToken( + expectedExpiringRefreshToken.getValue(), new DefaultAuthorizationRequest("id", null)); + assertNotNull(refreshedAccessToken); + } + + @Test + public void testNotReuseRefreshTokenMaintainsState() throws Exception { + services.setSupportRefreshToken(true); + services.setReuseRefreshToken(false); + OAuth2AccessToken accessToken = services.createAccessToken(createAuthentication()); + OAuth2RefreshToken expectedExpiringRefreshToken = accessToken.getRefreshToken(); + OAuth2AccessToken refreshedAccessToken = services.refreshAccessToken( + expectedExpiringRefreshToken.getValue(), new DefaultAuthorizationRequest("id", null)); + assertNotNull(refreshedAccessToken); + } + + + private OAuth2Authentication createAuthentication() { + return new OAuth2Authentication(new DefaultAuthorizationRequest("id", + Collections.singleton("read")), new TestAuthentication("test2", false)); + } + + protected static class TestAuthentication extends AbstractAuthenticationToken { + private String principal; + + public TestAuthentication(String name, boolean authenticated) { + super(null); + setAuthenticated(authenticated); + this.principal = name; + } + + public Object getCredentials() { + return null; + } + + public Object getPrincipal() { + return this.principal; + } + } + +} From f7501c26f6fc4c095a9e2ed2ef69adc8484a5fc0 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 23 Aug 2013 14:16:28 +0100 Subject: [PATCH 077/831] Adapt JWT tokens to 1.1 codebase --- .../oauth2/provider/OAuth2Request.java | 5 +- .../token/DefaultAccessTokenConverter.java | 24 +++++--- .../provider/token/JwtTokenServices.java | 25 ++++---- .../provider/token/TestJwtTokenEnhancer.java | 16 +++-- .../provider/token/TestJwtTokenServices.java | 61 ++++++++++--------- 5 files changed, 72 insertions(+), 59 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java index 704417a7d..7c06205ab 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java @@ -164,12 +164,11 @@ public OAuth2Request createOAuth2Request(Map parameters) { // Handle serialization and deserialization to capture fields from parent class // - @SuppressWarnings({ "rawtypes", "unchecked" }) private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); out.writeObject(clientId); - out.writeObject(new HashMap(requestParameters)); - out.writeObject(new HashSet(scope)); + out.writeObject(new HashMap(requestParameters)); + out.writeObject(new HashSet(scope)); } @SuppressWarnings("unchecked") diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java index c2848789a..2b8a4ef5d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java @@ -13,20 +13,22 @@ package org.springframework.security.oauth2.provider.token; import java.util.Collection; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Map; +import java.util.Set; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.provider.AuthorizationRequest; -import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.OAuth2Request; /** - * Default implementation of {@link AccessTokenConverter}. + * Default implementation of {@link AccessTokenConverter}. * * @author Dave Syer * @@ -47,7 +49,7 @@ public class DefaultAccessTokenConverter implements AccessTokenConverter { public Map convertAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) { Map response = new HashMap(); - AuthorizationRequest clientToken = authentication.getAuthorizationRequest(); + OAuth2Request clientToken = authentication.getOAuth2Request(); if (!authentication.isClientOnly()) { response.putAll(userTokenConverter.convertUserAuthentication(authentication.getUserAuthentication())); @@ -86,7 +88,7 @@ public OAuth2AccessToken extractAccessToken(String value, Map map) { } @SuppressWarnings("unchecked") Collection scope = (Collection) map.get(SCOPE); - if (scope!=null) { + if (scope != null) { token.setScope(new HashSet(scope)); } token.setAdditionalInformation(info); @@ -96,14 +98,16 @@ public OAuth2AccessToken extractAccessToken(String value, Map map) { public OAuth2Authentication extractAuthentication(Map map) { Map parameters = new HashMap(); @SuppressWarnings("unchecked") - Collection scope = (Collection) map.get(SCOPE); + Set scope = new LinkedHashSet(map.containsKey(SCOPE) ? (Collection) map.get(SCOPE) + : Collections.emptySet()); Authentication user = userTokenConverter.extractAuthentication(map); String clientId = (String) map.get(CLIENT_ID); parameters.put(CLIENT_ID, clientId); - DefaultAuthorizationRequest request = new DefaultAuthorizationRequest(parameters); - if (scope != null) { - request.setScope(new HashSet(scope)); - } + @SuppressWarnings("unchecked") + Set resourceIds = new LinkedHashSet(map.containsKey(AUD) ? (Collection) map.get(AUD) + : Collections.emptySet()); + OAuth2Request request = new OAuth2Request(parameters, clientId, null, true, scope, resourceIds, null, null, + null); return new OAuth2Authentication(request, user); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenServices.java index 757c34c29..daea32435 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenServices.java @@ -28,10 +28,11 @@ import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; import org.springframework.security.oauth2.common.exceptions.InvalidScopeException; import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; -import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.TokenRequest; /** * Token services for authorization server and resource server based on JWT encoded token values. There is no need for @@ -169,8 +170,8 @@ public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication) result.setRefreshToken(createRefreshToken(authentication)); return result; } - - public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, AuthorizationRequest request) + + public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, TokenRequest request) throws AuthenticationException { if (!supportRefreshToken) { @@ -178,7 +179,7 @@ public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, Authorizat } OAuth2Authentication authentication = loadAuthentication(refreshTokenValue); - String clientId = authentication.getAuthorizationRequest().getClientId(); + String clientId = authentication.getOAuth2Request().getClientId(); if (clientId == null || !clientId.equals(request.getClientId())) { throw new InvalidGrantException("Wrong client for this refresh token: " + refreshTokenValue); } @@ -209,12 +210,12 @@ public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) { info.put(TOKEN_ID, tokenId); result.setAdditionalInformation(info); - int validitySeconds = getAccessTokenValiditySeconds(authentication.getAuthorizationRequest()); + int validitySeconds = getAccessTokenValiditySeconds(authentication.getOAuth2Request()); if (validitySeconds > 0) { result.setExpiration(new Date(System.currentTimeMillis() + (validitySeconds * 1000L))); } - result.setScope(authentication.getAuthorizationRequest().getScope()); + result.setScope(authentication.getOAuth2Request().getScope()); if (accessTokenEnhancer != null) { result = new DefaultOAuth2AccessToken(accessTokenEnhancer.enhance(result, authentication)); @@ -243,7 +244,7 @@ protected boolean isExpired(OAuth2AccessToken expiringToken) { * @param authorizationRequest the current authorization request * @return boolean to indicate if refresh token is supported */ - protected boolean isSupportRefreshToken(AuthorizationRequest authorizationRequest) { + protected boolean isSupportRefreshToken(OAuth2Request authorizationRequest) { if (clientDetailsService != null) { ClientDetails client = clientDetailsService.loadClientByClientId(authorizationRequest.getClientId()); return client.getAuthorizedGrantTypes().contains("refresh_token"); @@ -256,7 +257,7 @@ protected boolean isSupportRefreshToken(AuthorizationRequest authorizationReques * @param authorizationRequest the current authorization request * @return the access token validity period in seconds */ - protected int getAccessTokenValiditySeconds(AuthorizationRequest authorizationRequest) { + protected int getAccessTokenValiditySeconds(OAuth2Request authorizationRequest) { if (clientDetailsService != null) { ClientDetails client = clientDetailsService.loadClientByClientId(authorizationRequest.getClientId()); Integer validity = client.getAccessTokenValiditySeconds(); @@ -272,7 +273,7 @@ protected int getAccessTokenValiditySeconds(AuthorizationRequest authorizationRe * @param authorizationRequest the current authorization request * @return the refresh token validity period in seconds */ - protected int getRefreshTokenValiditySeconds(AuthorizationRequest authorizationRequest) { + protected int getRefreshTokenValiditySeconds(OAuth2Request authorizationRequest) { if (clientDetailsService != null) { ClientDetails client = clientDetailsService.loadClientByClientId(authorizationRequest.getClientId()); Integer validity = client.getRefreshTokenValiditySeconds(); @@ -308,7 +309,7 @@ private Map decode(String token) { private OAuth2Authentication createRefreshedAuthentication(OAuth2Authentication authentication, Set scope) { OAuth2Authentication narrowed = authentication; if (scope != null && !scope.isEmpty()) { - AuthorizationRequest clientAuth = authentication.getAuthorizationRequest(); + OAuth2Request clientAuth = authentication.getOAuth2Request(); Set originalScope = clientAuth.getScope(); if (originalScope == null || !originalScope.containsAll(scope)) { throw new InvalidScopeException("Unable to narrow the scope of the client authentication to " + scope @@ -329,11 +330,11 @@ private OAuth2Authentication createRefreshedAuthentication(OAuth2Authentication * @return a refresh token with a JWT encoded value */ private ExpiringOAuth2RefreshToken createRefreshToken(OAuth2Authentication authentication) { - if (!isSupportRefreshToken(authentication.getAuthorizationRequest())) { + if (!isSupportRefreshToken(authentication.getOAuth2Request())) { return null; } DefaultOAuth2AccessToken accessToken = new DefaultOAuth2AccessToken(getAccessToken(authentication)); - int validitySeconds = getRefreshTokenValiditySeconds(authentication.getAuthorizationRequest()); + int validitySeconds = getRefreshTokenValiditySeconds(authentication.getOAuth2Request()); Date expiration = new Date(System.currentTimeMillis() + (validitySeconds * 1000L)); accessToken.setExpiration(expiration); accessToken.setValue(encode(accessToken, authentication)); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJwtTokenEnhancer.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJwtTokenEnhancer.java index e93e76de5..5126e9c9a 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJwtTokenEnhancer.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJwtTokenEnhancer.java @@ -13,21 +13,20 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import java.util.Collections; import java.util.Map; +import java.util.Set; import org.junit.Before; import org.junit.Test; -import org.springframework.security.access.AccessDeniedException; -import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; -import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.jwt.JwtHelper; import org.springframework.security.jwt.crypto.sign.RsaVerifier; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.token.AbstractTestDefaultTokenServices.TestAuthentication; /** @@ -48,7 +47,7 @@ public void setUp() throws Exception { @Test public void testEnhanceAccessToken() { - OAuth2Authentication authentication = new OAuth2Authentication(new DefaultAuthorizationRequest("foo", null), + OAuth2Authentication authentication = new OAuth2Authentication(createOAuth2Request("foo", null), userAuthentication); OAuth2AccessToken token = tokenEnhancer.enhance(new DefaultOAuth2AccessToken("FOO"), authentication); assertNotNull(token.getValue()); @@ -71,7 +70,7 @@ public void rsaKeyCreatesValidRsaSignedTokens() throws Exception { + "gOdvA1hvq3tlWU5REDrYt24xpviA0fvrJpwMPbECMAKDKdiDi6Q4/iBkkzNMefA8\n" + "7HX27b9LR33don/1u/yvzMUo+lrRdKAFJ+9GPE9XFA== \n" + "-----END RSA PRIVATE KEY----- "; tokenEnhancer.setSigningKey(rsaKey); - OAuth2Authentication authentication = new OAuth2Authentication(new DefaultAuthorizationRequest("foo", null), + OAuth2Authentication authentication = new OAuth2Authentication(createOAuth2Request("foo", null), userAuthentication); OAuth2AccessToken token = tokenEnhancer.enhance(new DefaultOAuth2AccessToken("FOO"), authentication); JwtHelper.decodeAndVerify(token.getValue(), new RsaVerifier(rsaKey)); @@ -111,4 +110,9 @@ public void keysNotMatchingWithMacSigner() throws Exception { tokenEnhancer.afterPropertiesSet(); } + private OAuth2Request createOAuth2Request(String clientId, Set scope) { + return new OAuth2Request(Collections. emptyMap(), clientId, null, true, scope, null, null, + null, null); + } + } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJwtTokenServices.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJwtTokenServices.java index e4b945258..e1c4d404e 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJwtTokenServices.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJwtTokenServices.java @@ -20,6 +20,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.Date; +import java.util.Set; import org.junit.Before; import org.junit.Test; @@ -36,9 +37,9 @@ import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; -import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.token.TokenEnhancer; +import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.test.util.ReflectionTestUtils; /** @@ -48,7 +49,7 @@ public class TestJwtTokenServices { private JwtTokenServices services = new JwtTokenServices(); - + private JwtTokenEnhancer enhancer; @Before @@ -60,7 +61,6 @@ public void init() throws Exception { services.setSupportRefreshToken(true); } - @Test public void testReadAccessToken() throws Exception { String token = JwtHelper.encode("{\"client_id\":\"client\"}", new MacSigner("FOO")).getEncoded(); @@ -73,7 +73,7 @@ public void testLoadAuthentication() throws Exception { String token = JwtHelper.encode("{\"client_id\":\"client\"}", new MacSigner("FOO")).getEncoded(); OAuth2Authentication authentication = services.loadAuthentication(token); assertEquals(null, authentication.getUserAuthentication()); - assertEquals("client", authentication.getAuthorizationRequest().getClientId()); + assertEquals("client", authentication.getOAuth2Request().getClientId()); } @Test @@ -107,31 +107,33 @@ public void testRefreshedTokenIsEnhanced() throws Exception { services.setTokenEnhancer(new TokenEnhancer() { public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(accessToken); - token.setAdditionalInformation(Collections.singletonMap("foo", "bar")); + token.setAdditionalInformation(Collections. singletonMap("foo", "bar")); return token; } }); OAuth2AccessToken accessToken = services.createAccessToken(createAuthentication()); assertEquals("bar", accessToken.getAdditionalInformation().get("foo")); - OAuth2AccessToken refreshedAccessToken = services.refreshAccessToken( - accessToken.getRefreshToken().getValue(), new DefaultAuthorizationRequest("id", null)); + OAuth2AccessToken refreshedAccessToken = services.refreshAccessToken(accessToken.getRefreshToken().getValue(), + new TokenRequest(null, "id", null, null)); assertEquals("bar", refreshedAccessToken.getAdditionalInformation().get("foo")); } @Test public void testRefreshedTokenHasScopes() throws Exception { - ExpiringOAuth2RefreshToken expectedExpiringRefreshToken = (ExpiringOAuth2RefreshToken) services.createAccessToken(createAuthentication()).getRefreshToken(); - OAuth2AccessToken refreshedAccessToken = services.refreshAccessToken( - expectedExpiringRefreshToken.getValue(), new DefaultAuthorizationRequest("id", null)); + ExpiringOAuth2RefreshToken expectedExpiringRefreshToken = (ExpiringOAuth2RefreshToken) services + .createAccessToken(createAuthentication()).getRefreshToken(); + OAuth2AccessToken refreshedAccessToken = services.refreshAccessToken(expectedExpiringRefreshToken.getValue(), + new TokenRequest(null, "id", null, null)); assertEquals("[read]", refreshedAccessToken.getScope().toString()); } - @Test(expected=InvalidGrantException.class) + @Test(expected = InvalidGrantException.class) public void testRefreshedTokenInvalidWithWrongClient() throws Exception { - ExpiringOAuth2RefreshToken expectedExpiringRefreshToken = (ExpiringOAuth2RefreshToken) services.createAccessToken(createAuthentication()).getRefreshToken(); - OAuth2AccessToken refreshedAccessToken = services.refreshAccessToken( - expectedExpiringRefreshToken.getValue(), new DefaultAuthorizationRequest("wrong", null)); + ExpiringOAuth2RefreshToken expectedExpiringRefreshToken = (ExpiringOAuth2RefreshToken) services + .createAccessToken(createAuthentication()).getRefreshToken(); + OAuth2AccessToken refreshedAccessToken = services.refreshAccessToken(expectedExpiringRefreshToken.getValue(), + new TokenRequest(null, "wrong", null, null)); assertEquals("[read]", refreshedAccessToken.getScope().toString()); } @@ -192,12 +194,11 @@ public void testOneAccessTokenPerAuthentication() throws Exception { @Test public void testOneAccessTokenPerUniqueAuthentication() throws Exception { - services.createAccessToken( - new OAuth2Authentication(new DefaultAuthorizationRequest("id", Collections.singleton("read")), - new TestAuthentication("test2", false))); - services.createAccessToken( - new OAuth2Authentication(new DefaultAuthorizationRequest("id", Collections.singleton("write")), - new TestAuthentication("test2", false))); + String clientId = "id"; + services.createAccessToken(new OAuth2Authentication( + createOAuth2Request(clientId, Collections.singleton("read")), new TestAuthentication("test2", false))); + services.createAccessToken(new OAuth2Authentication(createOAuth2Request(clientId, + Collections.singleton("write")), new TestAuthentication("test2", false))); } @Test @@ -205,8 +206,8 @@ public void testRefreshTokenMaintainsState() throws Exception { services.setSupportRefreshToken(true); OAuth2AccessToken accessToken = services.createAccessToken(createAuthentication()); OAuth2RefreshToken expectedExpiringRefreshToken = accessToken.getRefreshToken(); - OAuth2AccessToken refreshedAccessToken = services.refreshAccessToken( - expectedExpiringRefreshToken.getValue(), new DefaultAuthorizationRequest("id", null)); + OAuth2AccessToken refreshedAccessToken = services.refreshAccessToken(expectedExpiringRefreshToken.getValue(), + new TokenRequest(null, "id", null, null)); assertNotNull(refreshedAccessToken); } @@ -216,15 +217,19 @@ public void testNotReuseRefreshTokenMaintainsState() throws Exception { services.setReuseRefreshToken(false); OAuth2AccessToken accessToken = services.createAccessToken(createAuthentication()); OAuth2RefreshToken expectedExpiringRefreshToken = accessToken.getRefreshToken(); - OAuth2AccessToken refreshedAccessToken = services.refreshAccessToken( - expectedExpiringRefreshToken.getValue(), new DefaultAuthorizationRequest("id", null)); + OAuth2AccessToken refreshedAccessToken = services.refreshAccessToken(expectedExpiringRefreshToken.getValue(), + new TokenRequest(null, "id", null, null)); assertNotNull(refreshedAccessToken); } - private OAuth2Authentication createAuthentication() { - return new OAuth2Authentication(new DefaultAuthorizationRequest("id", - Collections.singleton("read")), new TestAuthentication("test2", false)); + return new OAuth2Authentication(createOAuth2Request("id", Collections.singleton("read")), + new TestAuthentication("test2", false)); + } + + private OAuth2Request createOAuth2Request(String clientId, Set scope) { + return new OAuth2Request(Collections. emptyMap(), clientId, null, true, scope, null, null, + null, null); } protected static class TestAuthentication extends AbstractAuthenticationToken { From 5347c1e03626f50e007c1761b7460d5622310638 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 28 Aug 2013 13:46:59 +0100 Subject: [PATCH 078/831] Extract token query methods from ConsumerTokenServices --- .../examples/sparklr/mvc/AdminController.java | 14 ++++++++++++-- .../src/main/webapp/WEB-INF/spring-servlet.xml | 1 + .../provider/token/ConsumerTokenServices.java | 7 ------- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AdminController.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AdminController.java index 0df38bdb3..19746f31c 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AdminController.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AdminController.java @@ -14,6 +14,7 @@ import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.token.ConsumerTokenServices; +import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @@ -31,6 +32,8 @@ public class AdminController { private ConsumerTokenServices tokenServices; + private TokenStore tokenStore; + private SparklrUserApprovalHandler userApprovalHandler; @RequestMapping("/oauth/cache_approvals") @@ -50,7 +53,7 @@ public void stopCaching() throws Exception { public Collection listTokensForUser(@PathVariable String user, Principal principal) throws Exception { checkResourceOwner(user, principal); - return enhance(tokenServices.findTokensByUserName(user)); + return enhance(tokenStore.findTokensByUserName(user)); } @RequestMapping(value = "/oauth/users/{user}/tokens/{token}", method = RequestMethod.DELETE) @@ -67,7 +70,7 @@ public ResponseEntity revokeToken(@PathVariable String user, @PathVariable @RequestMapping("/oauth/clients/{client}/tokens") @ResponseBody public Collection listTokensForClient(@PathVariable String client) throws Exception { - return enhance(tokenServices.findTokensByClientId(client)); + return enhance(tokenStore.findTokensByClientId(client)); } private Collection enhance(Collection tokens) { @@ -108,5 +111,12 @@ public void setUserApprovalHandler(SparklrUserApprovalHandler userApprovalHandle public void setTokenServices(ConsumerTokenServices tokenServices) { this.tokenServices = tokenServices; } + + /** + * @param tokenStore the tokenStore to set + */ + public void setTokenStore(TokenStore tokenStore) { + this.tokenStore = tokenStore; + } } diff --git a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml index d9996d15c..0bae22bae 100644 --- a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml +++ b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml @@ -211,6 +211,7 @@ + diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/ConsumerTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/ConsumerTokenServices.java index e8ea0b855..807e114e1 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/ConsumerTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/ConsumerTokenServices.java @@ -12,9 +12,6 @@ */ package org.springframework.security.oauth2.provider.token; -import java.util.Collection; - -import org.springframework.security.oauth2.common.OAuth2AccessToken; /** * @author Dave Syer @@ -22,10 +19,6 @@ */ public interface ConsumerTokenServices { - Collection findTokensByUserName(String userName); - - Collection findTokensByClientId(String clientId); - boolean revokeToken(String tokenValue); String getClientId(String tokenValue); From a90b9dfc2de10e43a51248877734cf996a922311 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 28 Aug 2013 15:52:42 +0100 Subject: [PATCH 079/831] TokenServicesUserApprovalHandler -> TokenStoreUserApprovalHandler --- .../oauth/SparklrUserApprovalHandler.java | 37 +++++++++--------- .../main/webapp/WEB-INF/spring-servlet.xml | 2 +- .../approval/DefaultUserApprovalHandler.java | 3 ++ ...ava => TokenStoreUserApprovalHandler.java} | 38 ++++++++++++------- .../TestDefaultUserApprovalHandler.java | 8 ++-- ...=> TestTokenStoreUserApprovalHandler.java} | 17 +++++---- 6 files changed, 60 insertions(+), 45 deletions(-) rename spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/{TokenServicesUserApprovalHandler.java => TokenStoreUserApprovalHandler.java} (83%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/{TestTokenServicesUserApprovalHandler.java => TestTokenStoreUserApprovalHandler.java} (84%) diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrUserApprovalHandler.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrUserApprovalHandler.java index 546491efb..7c1bafbe5 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrUserApprovalHandler.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrUserApprovalHandler.java @@ -20,18 +20,17 @@ import java.util.HashSet; import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.common.util.OAuth2Utils; import org.springframework.security.oauth2.provider.AuthorizationRequest; -import org.springframework.security.oauth2.provider.approval.TokenServicesUserApprovalHandler; +import org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler; /** * @author Dave Syer * */ -public class SparklrUserApprovalHandler extends TokenServicesUserApprovalHandler { +public class SparklrUserApprovalHandler extends TokenStoreUserApprovalHandler { private Collection autoApproveClients = new HashSet(); - + private boolean useTokenServices = true; /** @@ -54,26 +53,28 @@ public void setAutoApproveClients(Collection autoApproveClients) { * @param authorizationRequest The authorization request. * @param userAuthentication the current user authentication * - * @return Whether the specified request has been approved by the current user. + * @return An updated request if it has already been approved by the current user. */ @Override - public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { - + public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest, + Authentication userAuthentication) { + + boolean approved = false; // If we are allowed to check existing approvals this will short circuit the decision - if (useTokenServices && super.isApproved(authorizationRequest, userAuthentication)) { - return true; + if (useTokenServices) { + authorizationRequest = super.checkForPreApproval(authorizationRequest, userAuthentication); + approved = authorizationRequest.isApproved(); } - - if (!userAuthentication.isAuthenticated()) { - return false; + else if (!userAuthentication.isAuthenticated()) { + approved = false; } + else { + approved = (authorizationRequest.getResponseTypes().contains("token") && autoApproveClients + .contains(authorizationRequest.getClientId())); + } + authorizationRequest.setApproved(approved); - String flag = authorizationRequest.getApprovalParameters().get(OAuth2Utils.USER_OAUTH_APPROVAL); - boolean approved = flag != null && flag.toLowerCase().equals("true"); - - return approved - || (authorizationRequest.getResponseTypes().contains("token") && autoApproveClients - .contains(authorizationRequest.getClientId())); + return authorizationRequest; } diff --git a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml index 0bae22bae..780545d1d 100644 --- a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml +++ b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml @@ -134,7 +134,7 @@ my-less-trusted-autoapprove-client - + diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/DefaultUserApprovalHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/DefaultUserApprovalHandler.java index ff70103aa..53d9d4cef 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/DefaultUserApprovalHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/DefaultUserApprovalHandler.java @@ -49,6 +49,9 @@ public void setApprovalParameter(String approvalParameter) { * @return Whether the specified request has been approved by the current user. */ public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { + if (authorizationRequest.isApproved()) { + return true; + } Map approvalParameters = authorizationRequest.getApprovalParameters(); String flag = approvalParameters.get(approvalParameter); boolean approved = flag != null && flag.toLowerCase().equals("true"); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenServicesUserApprovalHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandler.java similarity index 83% rename from spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenServicesUserApprovalHandler.java rename to spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandler.java index e9e9d5270..51f990e1a 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenServicesUserApprovalHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandler.java @@ -16,17 +16,19 @@ package org.springframework.security.oauth2.provider.approval; +import java.util.Map; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.util.OAuth2Utils; -import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.AuthorizationRequest; -import org.springframework.security.oauth2.provider.OAuth2RequestFactory; +import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; -import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; +import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.util.Assert; /** @@ -35,9 +37,9 @@ * @author Dave Syer * */ -public class TokenServicesUserApprovalHandler implements UserApprovalHandler, InitializingBean { +public class TokenStoreUserApprovalHandler implements UserApprovalHandler, InitializingBean { - private static Log logger = LogFactory.getLog(TokenServicesUserApprovalHandler.class); + private static Log logger = LogFactory.getLog(TokenStoreUserApprovalHandler.class); private String approvalParameter = OAuth2Utils.USER_OAUTH_APPROVAL; @@ -48,13 +50,13 @@ public void setApprovalParameter(String approvalParameter) { this.approvalParameter = approvalParameter; } - private AuthorizationServerTokenServices tokenServices; + private TokenStore tokenServices; /** - * @param tokenServices the token services to set + * @param tokenStore the token services to set */ - public void setTokenServices(AuthorizationServerTokenServices tokenServices) { - this.tokenServices = tokenServices; + public void setTokenStore(TokenStore tokenStore) { + this.tokenServices = tokenStore; } private OAuth2RequestFactory requestFactory; @@ -79,9 +81,20 @@ public void afterPropertiesSet() { */ public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { - String flag = authorizationRequest.getApprovalParameters().get(approvalParameter); + if (authorizationRequest.isApproved()) { + return true; + } + Map approvalParameters = authorizationRequest.getApprovalParameters(); + String flag = approvalParameters.get(approvalParameter); boolean approved = flag != null && flag.toLowerCase().equals("true"); + return userAuthentication.isAuthenticated() && approved; + + } + public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { + + boolean approved = false; + OAuth2Request storedOAuth2Request = requestFactory.createOAuth2Request(authorizationRequest); OAuth2Authentication authentication = new OAuth2Authentication(storedOAuth2Request, userAuthentication); @@ -105,11 +118,8 @@ public boolean isApproved(AuthorizationRequest authorizationRequest, Authenticat approved = userAuthentication.isAuthenticated() && approved; } - return approved; + authorizationRequest.setApproved(approved); - } - - public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { return authorizationRequest; } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestDefaultUserApprovalHandler.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestDefaultUserApprovalHandler.java index c51981730..2ca751936 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestDefaultUserApprovalHandler.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestDefaultUserApprovalHandler.java @@ -12,7 +12,7 @@ */ package org.springframework.security.oauth2.provider.approval; -import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import java.util.HashMap; @@ -30,9 +30,9 @@ public class TestDefaultUserApprovalHandler { @Test public void testBasicApproval() { - AuthorizationRequest request =new AuthorizationRequest(new HashMap(), null, null, null, null, null, false, null, null, null); - request.setApproved(true); // This isn't enough to be explicitly approved - assertFalse(handler.isApproved(request, new TestAuthentication("marissa", true))); + AuthorizationRequest request = new AuthorizationRequest(new HashMap(), null, null, null, null, null, false, null, null, null); + request.setApproved(true); // This is enough to be explicitly approved + assertTrue(handler.isApproved(request, new TestAuthentication("marissa", true))); } protected static class TestAuthentication extends AbstractAuthenticationToken { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenServicesUserApprovalHandler.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenStoreUserApprovalHandler.java similarity index 84% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenServicesUserApprovalHandler.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenStoreUserApprovalHandler.java index 49d662076..54c6156a5 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenServicesUserApprovalHandler.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenStoreUserApprovalHandler.java @@ -12,7 +12,6 @@ */ package org.springframework.security.oauth2.provider.approval; -import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.util.HashMap; @@ -31,23 +30,24 @@ * @author Dave Syer * */ -public class TestTokenServicesUserApprovalHandler { +public class TestTokenStoreUserApprovalHandler { - private TokenServicesUserApprovalHandler handler = new TokenServicesUserApprovalHandler(); + private TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler(); private DefaultTokenServices tokenServices = new DefaultTokenServices(); private DefaultOAuth2RequestFactory requestFactory = new DefaultOAuth2RequestFactory(null); { - tokenServices.setTokenStore(new InMemoryTokenStore()); - handler.setTokenServices(tokenServices); + InMemoryTokenStore tokenStore = new InMemoryTokenStore(); + tokenServices.setTokenStore(tokenStore); + handler.setTokenStore(tokenStore); handler.setRequestFactory(requestFactory); } @Test(expected = IllegalStateException.class) public void testMandatoryProperties() throws Exception { - handler = new TokenServicesUserApprovalHandler(); + handler = new TokenStoreUserApprovalHandler(); handler.afterPropertiesSet(); } @@ -56,8 +56,8 @@ public void testBasicApproval() { HashMap parameters = new HashMap(); parameters.put(OAuth2Utils.USER_OAUTH_APPROVAL, "true"); AuthorizationRequest request = new AuthorizationRequest(parameters, null, null, null, null, null, false, null, null, null); - request.setApproved(true); // This isn't enough to be explicitly approved - assertFalse(handler.isApproved(request , new TestAuthentication("marissa", true))); + request.setApproved(true); // This is enough to be explicitly approved + assertTrue(handler.isApproved(request , new TestAuthentication("marissa", true))); } @Test @@ -71,6 +71,7 @@ public void testMemorizedApproval() { OAuth2Request storedOAuth2Request = requestFactory.createOAuth2Request(authorizationRequest); tokenServices.createAccessToken(new OAuth2Authentication(storedOAuth2Request, userAuthentication)); + authorizationRequest = handler.checkForPreApproval(authorizationRequest, userAuthentication); assertTrue(handler.isApproved(authorizationRequest, userAuthentication)); } From c1df944db4c4472694e8c7cf808a955f77aac7bc Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 29 Aug 2013 10:09:45 +0100 Subject: [PATCH 080/831] First draft of approvals and store --- pom.xml | 5 +- .../common/util/JsonDateDeserializer.java | 46 ++++ .../common/util/JsonDateSerializer.java | 41 ++++ .../oauth2/common/util/OAuth2Utils.java | 20 +- .../oauth2/provider/approval/Approval.java | 162 +++++++++++++ .../provider/approval/ApprovalStore.java | 34 +++ .../approval/InMemoryApprovalStore.java | 117 ++++++++++ .../provider/approval/JdbcApprovalStore.java | 217 ++++++++++++++++++ .../provider/approval/TokenApprovalStore.java | 104 +++++++++ .../TokenStoreUserApprovalHandler.java | 10 +- .../approval/AbstractTestApprovalStore.java | 91 ++++++++ .../approval/TestInMemoryApprovalStore.java | 32 +++ .../approval/TestJdbcApprovalStore.java | 66 ++++++ .../approval/TestTokenApprovalStore.java | 89 +++++++ .../src/test/resources/schema.sql | 10 + 15 files changed, 1034 insertions(+), 10 deletions(-) create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JsonDateDeserializer.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JsonDateSerializer.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/Approval.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStore.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/InMemoryApprovalStore.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/JdbcApprovalStore.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenApprovalStore.java create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/AbstractTestApprovalStore.java create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestInMemoryApprovalStore.java create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestJdbcApprovalStore.java create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenApprovalStore.java diff --git a/pom.xml b/pom.xml index 0294301d8..4d4b04d8f 100644 --- a/pom.xml +++ b/pom.xml @@ -20,6 +20,7 @@ 3.1.3.RELEASE [3.1.0,4.0.0) [3.1.0,4.0.0) + 1.6 @@ -159,8 +160,8 @@ maven-compiler-plugin 2.3.2 - 1.5 - 1.5 + ${java.version} + ${java.version} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JsonDateDeserializer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JsonDateDeserializer.java new file mode 100644 index 000000000..81a614334 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JsonDateDeserializer.java @@ -0,0 +1,46 @@ +/* + * Cloud Foundry 2012.02.03 Beta + * Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved. + * + * This product is licensed to you under the Apache License, Version 2.0 (the "License"). + * You may not use this product except in compliance with the License. + * + * This product includes a number of subcomponents with + * separate copyright notices and license terms. Your use of these + * subcomponents is subject to the terms and conditions of the + * subcomponent's license, as noted in the LICENSE file. + */ +package org.springframework.security.oauth2.common.util; + +import org.codehaus.jackson.JsonParseException; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.JsonDeserializer; + +import java.io.IOException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * JSON deserializer for Jackson to handle regular date instances as timestamps in ISO format. + * + * @author Dave Syer + * + */ +public class JsonDateDeserializer extends JsonDeserializer { + + private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); + + @Override + public Date deserialize(JsonParser parser, DeserializationContext context) throws IOException, JsonProcessingException { + try { + return dateFormat.parse(parser.getText()); + } + catch (ParseException e) { + throw new JsonParseException("Could not parse date", parser.getCurrentLocation(), e); + } + } + +} \ No newline at end of file diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JsonDateSerializer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JsonDateSerializer.java new file mode 100644 index 000000000..41843ffc2 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JsonDateSerializer.java @@ -0,0 +1,41 @@ +/* + * Cloud Foundry 2012.02.03 Beta + * Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved. + * + * This product is licensed to you under the Apache License, Version 2.0 (the "License"). + * You may not use this product except in compliance with the License. + * + * This product includes a number of subcomponents with + * separate copyright notices and license terms. Your use of these + * subcomponents is subject to the terms and conditions of the + * subcomponent's license, as noted in the LICENSE file. + */ +package org.springframework.security.oauth2.common.util; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.JsonSerializer; +import org.codehaus.jackson.map.SerializerProvider; + +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * JSON serializer for Jackson to handle regular date instances as timestamps in ISO format. + * + * @author Dave Syer + * + */ +public class JsonDateSerializer extends JsonSerializer { + + private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); + + @Override + public void serialize(Date date, JsonGenerator generator, SerializerProvider provider) throws IOException, + JsonProcessingException { + String formatted = dateFormat.format(date); + generator.writeString(formatted); + } + +} \ No newline at end of file diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/OAuth2Utils.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/OAuth2Utils.java index c28a64037..1adf39ff1 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/OAuth2Utils.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/OAuth2Utils.java @@ -18,6 +18,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Properties; import java.util.Set; @@ -60,12 +61,12 @@ public abstract class OAuth2Utils { * Constant to use while parsing and formatting parameter maps for OAuth2 requests */ public static final String USER_OAUTH_APPROVAL = "user_oauth_approval"; - + /** * Constant to use while parsing and formatting parameter maps for OAuth2 requests */ public static final String GRANT_TYPE = "grant_type"; - + /** * Parses a string parameter value into a set of strings. * @@ -81,7 +82,7 @@ public static Set parseParameterList(String values) { } return result; } - + /** * Formats a set of string values into a format appropriate for sending as a single-valued form value. * @@ -109,4 +110,17 @@ public static Map extractMap(String query) { } return map; } + + /** + * Compare 2 sets and check that one contains all members of the other. + * + * @param target set of strings to check + * @param members the members to compare to + * @return true if all members are in the target + */ + public static boolean containsAll(Set target, Set members) { + target = new HashSet(target); + target.retainAll(members); + return target.size() == members.size(); + } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/Approval.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/Approval.java new file mode 100644 index 000000000..6e838ed14 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/Approval.java @@ -0,0 +1,162 @@ +/* + * Copyright 2012-2013 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.approval; + +import java.util.Calendar; +import java.util.Date; + +import org.codehaus.jackson.annotate.JsonIgnore; +import org.codehaus.jackson.map.annotate.JsonDeserialize; +import org.codehaus.jackson.map.annotate.JsonSerialize; +import org.springframework.security.oauth2.common.util.JsonDateDeserializer; +import org.springframework.security.oauth2.common.util.JsonDateSerializer; + +/** + * @author Dave Syer + * @author Vidya Val + * + */ +@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +public class Approval { + + private String userId; + + private String clientId; + + private String scope; + + public enum ApprovalStatus { + APPROVED, + DENIED; + } + + private ApprovalStatus status; + + private Date expiresAt; + + private Date lastUpdatedAt; + + public Approval(String userId, String clientId, String scope, int expiresIn, ApprovalStatus status) { + this(userId, clientId, scope, new Date(), status, new Date()); + Calendar expiresAt = Calendar.getInstance(); + expiresAt.add(Calendar.MILLISECOND, expiresIn); + setExpiresAt(expiresAt.getTime()); + } + + public Approval(String userId, String clientId, String scope, Date expiresAt, ApprovalStatus status) { + this(userId, clientId, scope, expiresAt, status, new Date()); + } + + public Approval(String userId, String clientId, String scope, Date expiresAt, ApprovalStatus status, Date lastUpdatedAt) { + this.userId = userId; + this.clientId = clientId; + this.scope = scope; + this.expiresAt = expiresAt; + this.status = status; + this.lastUpdatedAt = lastUpdatedAt; + } + + protected Approval() { } + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId == null ? "" : userId; + } + + public String getClientId() { + return clientId; + } + + public void setClientId(String clientId) { + this.clientId = clientId == null ? "" : clientId; + } + + public String getScope() { + return scope; + } + + public void setScope(String scope) { + this.scope = scope == null ? "" : scope; + } + + @JsonSerialize(using = JsonDateSerializer.class, include = JsonSerialize.Inclusion.NON_NULL) + public Date getExpiresAt() { + return expiresAt; + } + + @JsonDeserialize(using = JsonDateDeserializer.class) + public void setExpiresAt(Date expiresAt) { + if (expiresAt == null) { + Calendar thirtyMinFromNow = Calendar.getInstance(); + thirtyMinFromNow.add(Calendar.MINUTE, 30); + expiresAt = thirtyMinFromNow.getTime(); + } + this.expiresAt = expiresAt; + } + + @JsonSerialize(using = JsonDateSerializer.class, include = JsonSerialize.Inclusion.NON_NULL) + public Date getLastUpdatedAt() { + return lastUpdatedAt; + } + + @JsonDeserialize(using = JsonDateDeserializer.class) + public void setLastUpdatedAt(Date lastUpdatedAt) { + this.lastUpdatedAt = lastUpdatedAt; + } + + @JsonIgnore + public boolean isCurrentlyActive() { + return expiresAt != null && expiresAt.after(new Date()); + } + + public void setStatus(ApprovalStatus status) { + this.status = status; + } + + public ApprovalStatus getStatus() { + return status; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + userId.hashCode(); + result = prime * result + clientId.hashCode(); + result = prime * result + scope.hashCode(); + result = prime * result + status.hashCode(); + return result; + } + + @Override + public boolean equals(Object o) { + if (o == null || !(o instanceof Approval)) { + return false; + } + Approval other = (Approval) o; + return userId.equals(other.userId) && clientId.equals(other.clientId) && scope.equals(other.scope) && status == other.status; + } + + @Override + public String toString() { + return String.format("[%s, %s, %s, %s, %s, %s]", userId, scope, clientId, expiresAt, status.toString(), lastUpdatedAt); + } + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStore.java new file mode 100644 index 000000000..2f6063310 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStore.java @@ -0,0 +1,34 @@ +/* + * Copyright 2012-2013 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.approval; + +import java.util.Collection; + +/** + * Interface for saving, retrieving and revoking user approvals (per client, per scope). + * + * @author Dave Syer + * + */ +public interface ApprovalStore { + + public boolean addApprovals(Collection approvals); + + public boolean revokeApprovals(Collection approvals); + + public Collection getApprovals(String userId, String clientId); + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/InMemoryApprovalStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/InMemoryApprovalStore.java new file mode 100644 index 000000000..b6d7c3c7e --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/InMemoryApprovalStore.java @@ -0,0 +1,117 @@ +/* + * Copyright 2012-2013 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.approval; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * @author Dave Syer + * + */ +public class InMemoryApprovalStore implements ApprovalStore { + + private ConcurrentMap> map = new ConcurrentHashMap>(); + + @Override + public boolean addApprovals(Collection approvals) { + for (Approval approval : approvals) { + Collection collection = getApprovals(approval); + collection.add(approval); + } + return true; + } + + @Override + public boolean revokeApprovals(Collection approvals) { + boolean success = true; + for (Approval approval : approvals) { + Collection collection = getApprovals(approval); + boolean removed = collection.remove(approval); + if (!removed) { + success = false; + } + } + return success; + } + + private Collection getApprovals(Approval approval) { + Key key = new Key(approval.getUserId(), approval.getClientId()); + if (!map.containsKey(key)) { + map.putIfAbsent(key, new HashSet()); + } + return map.get(key); + } + + @Override + public Collection getApprovals(String userId, String clientId) { + Approval approval = new Approval(); + approval.setUserId(userId); + approval.setClientId(clientId); + return Collections.unmodifiableCollection(getApprovals(approval)); + } + + private static class Key { + + String userId; + + String clientId; + + public Key(String userId, String clientId) { + this.userId = userId; + this.clientId = clientId; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((clientId == null) ? 0 : clientId.hashCode()); + result = prime * result + ((userId == null) ? 0 : userId.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Key other = (Key) obj; + if (clientId == null) { + if (other.clientId != null) + return false; + } + else if (!clientId.equals(other.clientId)) + return false; + if (userId == null) { + if (other.userId != null) + return false; + } + else if (!userId.equals(other.userId)) + return false; + return true; + } + + } + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/JdbcApprovalStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/JdbcApprovalStore.java new file mode 100644 index 000000000..eedac92d9 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/JdbcApprovalStore.java @@ -0,0 +1,217 @@ +/* + * Copyright 2012-2013 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.approval; + +import static org.springframework.security.oauth2.provider.approval.Approval.ApprovalStatus.APPROVED; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.Collection; +import java.util.Date; +import java.util.List; + +import javax.sql.DataSource; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.PreparedStatementSetter; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.security.oauth2.provider.approval.Approval.ApprovalStatus; +import org.springframework.util.Assert; + +/** + * @author Dave Syer + * + */ +public class JdbcApprovalStore implements ApprovalStore { + + private final JdbcTemplate jdbcTemplate; + + private final Log logger = LogFactory.getLog(getClass()); + + private final RowMapper rowMapper = new AuthorizationRowMapper(); + + private static final String TABLE_NAME = "oauth_approvals"; + + private static final String FIELDS = "expiresAt,status,lastModifiedAt,userId,clientId,scope"; + + private static final String WHERE_KEY = "where userId=? and clientId=?"; + + private static final String WHERE_KEY_AND_SCOPE = WHERE_KEY + " and scope=?"; + + private static final String DEFAULT_ADD_APPROVAL_STATEMENT = String.format("insert into %s ( %s ) values (?,?,?,?,?,?)", TABLE_NAME, + FIELDS); + + private static final String DEFAULT_REFRESH_APPROVAL_STATEMENT = String.format( + "update %s set expiresAt=?, status=?, lastModifiedAt=? " + WHERE_KEY_AND_SCOPE, TABLE_NAME); + + private static final String DEFAULT_GET_APPROVAL_SQL = String.format("select %s from %s " + WHERE_KEY, FIELDS, TABLE_NAME); + + private static final String DEFAULT_DELETE_APPROVAL_SQL = String.format("delete from %s " + WHERE_KEY_AND_SCOPE, + TABLE_NAME); + + private static final String DEFAULT_EXPIRE_APPROVAL_STATEMENT = String.format("update %s set expiresAt = ? " + WHERE_KEY_AND_SCOPE, + TABLE_NAME); + + private String addApprovalStatement = DEFAULT_ADD_APPROVAL_STATEMENT; + + private String refreshApprovalStatement = DEFAULT_REFRESH_APPROVAL_STATEMENT; + + private String findApprovalStatement = DEFAULT_GET_APPROVAL_SQL; + + private String deleteApprovalStatment = DEFAULT_DELETE_APPROVAL_SQL; + + private String expireApprovalStatement = DEFAULT_EXPIRE_APPROVAL_STATEMENT; + + private boolean handleRevocationsAsExpiry = false; + + public JdbcApprovalStore(DataSource dataSource) { + Assert.notNull(dataSource); + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + public void setHandleRevocationsAsExpiry(boolean handleRevocationsAsExpiry) { + this.handleRevocationsAsExpiry = handleRevocationsAsExpiry; + } + + public void setAddApprovalStatement(String addApprovalStatement) { + this.addApprovalStatement = addApprovalStatement; + } + + public void setFindApprovalStatement(String findApprovalStatement) { + this.findApprovalStatement = findApprovalStatement; + } + + public void setDeleteApprovalStatment(String deleteApprovalStatment) { + this.deleteApprovalStatment = deleteApprovalStatment; + } + + public void setExpireApprovalStatement(String expireApprovalStatement) { + this.expireApprovalStatement = expireApprovalStatement; + } + + @Override + public boolean addApprovals(final Collection approvals) { + logger.debug(String.format("adding approvals: [%s]", approvals)); + boolean success = true; + for (Approval approval : approvals) { + if (!updateApproval(refreshApprovalStatement, approval)) { + if (!updateApproval(addApprovalStatement, approval)) { + success = false; + } + } + } + return success; + } + + @Override + public boolean revokeApprovals(Collection approvals) { + logger.debug(String.format("Revoking approvals: [%s]", approvals)); + boolean success = true; + for (final Approval approval : approvals) { + if (handleRevocationsAsExpiry) { + int refreshed = jdbcTemplate.update(expireApprovalStatement, new PreparedStatementSetter() { + @Override + public void setValues(PreparedStatement ps) throws SQLException { + ps.setTimestamp(1, new Timestamp(System.currentTimeMillis())); + ps.setString(2, approval.getUserId()); + ps.setString(3, approval.getClientId()); + ps.setString(4, approval.getScope()); + } + }); + if (refreshed != 1) { + success = false; + } + } + else { + int refreshed = jdbcTemplate.update(deleteApprovalStatment, new PreparedStatementSetter() { + @Override + public void setValues(PreparedStatement ps) throws SQLException { + ps.setString(1, approval.getUserId()); + ps.setString(2, approval.getClientId()); + ps.setString(3, approval.getScope()); + } + }); + if (refreshed != 1) { + success = false; + } + } + } + return success; + } + + public boolean purgeExpiredApprovals() { + logger.debug("Purging expired approvals from database"); + try { + int deleted = jdbcTemplate.update(deleteApprovalStatment + " where expiresAt <= ?", + new PreparedStatementSetter() { + @Override + public void setValues(PreparedStatement ps) throws SQLException { + ps.setTimestamp(1, new Timestamp(new Date().getTime())); + } + }); + logger.debug(deleted + " expired approvals deleted"); + } + catch (DataAccessException ex) { + logger.error("Error purging expired approvals", ex); + return false; + } + return true; + } + + @Override + public List getApprovals(String userName, String clientId) { + return jdbcTemplate.query(findApprovalStatement, rowMapper, userName, clientId); + } + + private boolean updateApproval(final String sql, final Approval approval) { + logger.debug(String.format("refreshing approval: [%s]", approval)); + int refreshed = jdbcTemplate.update(sql, new PreparedStatementSetter() { + @Override + public void setValues(PreparedStatement ps) throws SQLException { + ps.setTimestamp(1, new Timestamp(approval.getExpiresAt().getTime())); + ps.setString(2, (approval.getStatus() == null ? APPROVED : approval.getStatus()).toString()); + ps.setTimestamp(3, new Timestamp(approval.getLastUpdatedAt().getTime())); + ps.setString(4, approval.getUserId()); + ps.setString(5, approval.getClientId()); + ps.setString(6, approval.getScope()); + } + }); + if (refreshed != 1) { + return false; + } + return true; + } + + private static class AuthorizationRowMapper implements RowMapper { + + @Override + public Approval mapRow(ResultSet rs, int rowNum) throws SQLException { + String userName = rs.getString(4); + String clientId = rs.getString(5); + String scope = rs.getString(6); + Date expiresAt = rs.getTimestamp(1); + String status = rs.getString(2); + Date lastUpdatedAt = rs.getTimestamp(3); + + return new Approval(userName, clientId, scope, expiresAt, ApprovalStatus.valueOf(status), lastUpdatedAt); + } + } +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenApprovalStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenApprovalStore.java new file mode 100644 index 000000000..8dd2c461c --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenApprovalStore.java @@ -0,0 +1,104 @@ +/* + * Copyright 2012-2013 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.approval; + +import java.util.Collection; +import java.util.Date; +import java.util.HashSet; + +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.approval.Approval.ApprovalStatus; +import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; +import org.springframework.security.oauth2.provider.token.TokenStore; + +/** + * An {@link ApprovalStore} that works with an existing {@link TokenStore}, extracting implicit {@link Approval + * Approvals} from the content of tokens already in the store. Useful interface so that users can list and revoke + * approvals even if they are not really represented in such a way internally. For full fine-grained control of user + * approvals don't use a TokenStore at all, and don't use this ApprovalStore with Approval-based + * {@link AuthorizationServerTokenServices} implementations. + * + * @author Dave Syer + * + */ +public class TokenApprovalStore implements ApprovalStore { + + private TokenStore store; + + /** + * @param store the token store to set + */ + public void setTokenStore(TokenStore store) { + this.store = store; + } + + /** + * This implementation is a no-op. We assume that the {@link TokenStore} is populated elsewhere, by (for example) a + * token services instance that knows more about granted tokens than we could possibly infer from the approvals. + * + * @see org.springframework.security.oauth2.provider.approval.ApprovalStore#addApprovals(java.util.Collection) + */ + @Override + public boolean addApprovals(Collection approvals) { + return true; + } + + /** + * Revoke all tokens that match the client and user in the approvals supplied. + * + * @see org.springframework.security.oauth2.provider.approval.ApprovalStore#revokeApprovals(java.util.Collection) + */ + @Override + public boolean revokeApprovals(Collection approvals) { + boolean success = true; + for (Approval approval : approvals) { + Collection tokens = store.findTokensByUserName(approval.getUserId()); + for (OAuth2AccessToken token : tokens) { + OAuth2Authentication authentication = store.readAuthentication(token); + if (authentication != null + && approval.getClientId().equals(authentication.getOAuth2Request().getClientId())) { + store.removeAccessToken(token); + } + } + } + return success; + } + + /** + * Extract the implied approvals from any tokens associated with the user and client id supplied. + * + * @see org.springframework.security.oauth2.provider.approval.ApprovalStore#getApprovals(java.lang.String, + * java.lang.String) + */ + @Override + public Collection getApprovals(String userId, String clientId) { + Collection result = new HashSet(); + Collection tokens = store.findTokensByUserName(userId); + for (OAuth2AccessToken token : tokens) { + OAuth2Authentication authentication = store.readAuthentication(token); + if (authentication != null && clientId.equals(authentication.getOAuth2Request().getClientId())) { + Date expiresAt = token.getExpiration(); + for (String scope : token.getScope()) { + result.add(new Approval(userId, clientId, scope, expiresAt, ApprovalStatus.APPROVED)); + } + } + } + return result; + } + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandler.java index 51f990e1a..e9672a2b0 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandler.java @@ -50,13 +50,13 @@ public void setApprovalParameter(String approvalParameter) { this.approvalParameter = approvalParameter; } - private TokenStore tokenServices; + private TokenStore tokenStore; /** - * @param tokenStore the token services to set + * @param tokenStore the token store to set */ public void setTokenStore(TokenStore tokenStore) { - this.tokenServices = tokenStore; + this.tokenStore = tokenStore; } private OAuth2RequestFactory requestFactory; @@ -66,7 +66,7 @@ public void setRequestFactory(OAuth2RequestFactory requestFactory) { } public void afterPropertiesSet() { - Assert.state(tokenServices != null, "AuthorizationServerTokenServices must be provided"); + Assert.state(tokenStore != null, "TokenStore must be provided"); Assert.state(requestFactory != null, "OAuth2RequestFactory must be provided"); } @@ -106,7 +106,7 @@ public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizati logger.debug(builder.toString()); } - OAuth2AccessToken accessToken = tokenServices.getAccessToken(authentication); + OAuth2AccessToken accessToken = tokenStore.getAccessToken(authentication); logger.debug("Existing access token=" + accessToken); if (accessToken != null && !accessToken.isExpired()) { logger.debug("User already approved with token=" + accessToken); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/AbstractTestApprovalStore.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/AbstractTestApprovalStore.java new file mode 100644 index 000000000..68124cb0f --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/AbstractTestApprovalStore.java @@ -0,0 +1,91 @@ +/* + * Copyright 2012-2013 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.approval; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.Collection; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.security.oauth2.provider.approval.Approval.ApprovalStatus; + +/** + * @author Dave Syer + * + */ +public abstract class AbstractTestApprovalStore { + + private ApprovalStore store; + + @Before + public void setupStore() { + store = getApprovalStore(); + } + + protected abstract ApprovalStore getApprovalStore(); + + protected boolean addApprovals(Collection approvals) { + return store.addApprovals(approvals); + } + + @Test + public void testAddEmptyCollection() { + assertTrue(addApprovals(Arrays. asList())); + assertEquals(0, store.getApprovals("foo", "bar").size()); + } + + @Test + public void testAddDifferentScopes() { + assertTrue(addApprovals(Arrays. asList(new Approval("user", "client", "read", 1000, + ApprovalStatus.APPROVED), new Approval("user", "client", "write", 1000, ApprovalStatus.APPROVED)))); + assertEquals(2, store.getApprovals("user", "client").size()); + } + + @Test + public void testIdempotentAdd() { + assertTrue(addApprovals(Arrays. asList(new Approval("user", "client", "read", 1000, + ApprovalStatus.APPROVED), new Approval("user", "client", "write", 1000, ApprovalStatus.APPROVED)))); + assertTrue(addApprovals(Arrays. asList(new Approval("user", "client", "read", 1000, + ApprovalStatus.APPROVED), new Approval("user", "client", "write", 1000, ApprovalStatus.APPROVED)))); + assertEquals(2, store.getApprovals("user", "client").size()); + } + + @Test + public void testAddDifferentClients() { + assertTrue(addApprovals(Arrays. asList(new Approval("user", "client", "read", 1000, + ApprovalStatus.APPROVED), new Approval("user", "other", "write", 1000, ApprovalStatus.APPROVED)))); + assertEquals(1, store.getApprovals("user", "client").size()); + assertEquals(1, store.getApprovals("user", "other").size()); + } + + @Test + public void testVanillaRevoke() { + Approval approval1 = new Approval("user", "client", "read", 1000, ApprovalStatus.APPROVED); + Approval approval2 = new Approval("user", "client", "write", 1000, ApprovalStatus.APPROVED); + assertTrue(addApprovals(Arrays. asList(approval1, approval2))); + store.revokeApprovals(Arrays.asList(approval1)); + assertEquals(getExpectedNumberOfApprovalsAfterRevoke(), store.getApprovals("user", "client").size()); + } + + protected int getExpectedNumberOfApprovalsAfterRevoke() { + return 1; + } + +} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestInMemoryApprovalStore.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestInMemoryApprovalStore.java new file mode 100644 index 000000000..fc4e20b34 --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestInMemoryApprovalStore.java @@ -0,0 +1,32 @@ +/* + * Copyright 2012-2013 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.approval; + +/** + * @author Dave Syer + * + */ +public class TestInMemoryApprovalStore extends AbstractTestApprovalStore { + + private ApprovalStore store = new InMemoryApprovalStore(); + + @Override + protected ApprovalStore getApprovalStore() { + return store ; + } + +} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestJdbcApprovalStore.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestJdbcApprovalStore.java new file mode 100644 index 000000000..12bd0cce7 --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestJdbcApprovalStore.java @@ -0,0 +1,66 @@ +/* + * Copyright 2012-2013 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.approval; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.Date; + +import org.junit.After; +import org.junit.Test; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.security.oauth2.provider.approval.Approval.ApprovalStatus; + +/** + * @author Dave Syer + * + */ +public class TestJdbcApprovalStore extends AbstractTestApprovalStore { + + private JdbcApprovalStore store; + + private EmbeddedDatabase db; + + @After + public void tearDown() throws Exception { + db.shutdown(); + } + + @Override + protected ApprovalStore getApprovalStore() { + db = new EmbeddedDatabaseBuilder().addDefaultScripts().build(); + store = new JdbcApprovalStore(db); + return store; + } + + @Test + public void testRevokeByExpiry() { + store.setHandleRevocationsAsExpiry(true); + Approval approval1 = new Approval("user", "client", "read", 10000, ApprovalStatus.APPROVED); + Approval approval2 = new Approval("user", "client", "write", 10000, ApprovalStatus.APPROVED); + assertTrue(store.addApprovals(Arrays. asList(approval1, approval2))); + store.revokeApprovals(Arrays.asList(approval1)); + assertEquals(2, store.getApprovals("user", "client").size()); + assertEquals(1, new JdbcTemplate(db).queryForInt( + "SELECT COUNT(*) from oauth_approvals where userId='user' AND expiresAt < ?", + new Date(System.currentTimeMillis() + 1000))); + } +} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenApprovalStore.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenApprovalStore.java new file mode 100644 index 000000000..95a9ca4b1 --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenApprovalStore.java @@ -0,0 +1,89 @@ +/* + * Copyright 2012-2013 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.approval; + +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; +import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; + +/** + * @author Dave Syer + * + */ +public class TestTokenApprovalStore extends AbstractTestApprovalStore { + + private TokenApprovalStore store = new TokenApprovalStore(); + private InMemoryTokenStore tokenStore = new InMemoryTokenStore(); + + @Override + protected ApprovalStore getApprovalStore() { + store.setTokenStore(tokenStore); + return store ; + } + + @Override + protected boolean addApprovals(Collection approvals) { + + Map>> clientIds = new HashMap>>(); + for (Approval approval : approvals) { + String clientId = approval.getClientId(); + if (!clientIds.containsKey(clientId)) { + clientIds.put(clientId, new HashMap>()); + } + String userId = approval.getUserId(); + Map> users = clientIds.get(clientId); + if (!users.containsKey(userId)) { + users.put(userId, new HashSet()); + } + Set scopes = users.get(userId); + scopes.add(approval.getScope()); + } + + for (String clientId : clientIds.keySet()) { + Map> users = clientIds.get(clientId); + for (String userId : users.keySet()) { + Authentication user = new UsernamePasswordAuthenticationToken(userId, "N/A", AuthorityUtils.commaSeparatedStringToAuthorityList("USER")); + AuthorizationRequest authorizationRequest = new AuthorizationRequest(); + authorizationRequest.setClientId(clientId); + Set scopes = users.get(userId); + authorizationRequest.setScope(scopes); + OAuth2Request request = authorizationRequest.createOAuth2Request(); + OAuth2Authentication authentication = new OAuth2Authentication(request, user); + DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(UUID.randomUUID().toString()); + token.setScope(scopes); + tokenStore.storeAccessToken(token, authentication); + } + } + return super.addApprovals(approvals); + } + + protected int getExpectedNumberOfApprovalsAfterRevoke() { + return 0; + } +} diff --git a/spring-security-oauth2/src/test/resources/schema.sql b/spring-security-oauth2/src/test/resources/schema.sql index 52681fedc..e6d1ecfca 100644 --- a/spring-security-oauth2/src/test/resources/schema.sql +++ b/spring-security-oauth2/src/test/resources/schema.sql @@ -40,6 +40,16 @@ create table oauth_code ( code VARCHAR(256), authentication LONGVARBINARY ); +create table oauth_approvals ( + userId VARCHAR(256), + clientId VARCHAR(256), + scope VARCHAR(256), + status VARCHAR(10), + expiresAt TIMESTAMP, + lastModifiedAt TIMESTAMP +); + + -- customized oauth_client_details table create table ClientDetails ( appId VARCHAR(256) PRIMARY KEY, From 796bc2ffbc5ebc6e889cbd574848d901cac2df9a Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 5 Sep 2013 17:24:21 +0100 Subject: [PATCH 081/831] Add ApprovalStoreUserApprovalHandler --- ...thorizationServerBeanDefinitionParser.java | 13 +- .../InMemoryClientDetailsService.java | 9 +- .../ApprovalStoreUserApprovalHandler.java | 200 ++++++++++++++++++ .../TestApprovalStoreUserApprovalHandler.java | 83 ++++++++ 4 files changed, 289 insertions(+), 16 deletions(-) create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TestApprovalStoreUserApprovalHandler.java diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/config/TestAuthorizationServerBeanDefinitionParser.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/config/TestAuthorizationServerBeanDefinitionParser.java index e69660ac3..3569e770d 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/config/TestAuthorizationServerBeanDefinitionParser.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/config/TestAuthorizationServerBeanDefinitionParser.java @@ -16,17 +16,13 @@ package org.springframework.security.oauth.config; -import java.io.IOException; -import java.lang.reflect.Field; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; +import java.lang.reflect.Field; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.Mock; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.oauth.provider.filter.UserAuthorizationProcessingFilter; import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; @@ -36,9 +32,6 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.util.ReflectionUtils; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) public class TestAuthorizationServerBeanDefinitionParser { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/InMemoryClientDetailsService.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/InMemoryClientDetailsService.java index ea1806f10..476d830a7 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/InMemoryClientDetailsService.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/InMemoryClientDetailsService.java @@ -28,7 +28,7 @@ */ public class InMemoryClientDetailsService implements ClientDetailsService { - private Map clientDetailsStore = new HashMap(); + private Map clientDetailsStore = new HashMap(); public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exception { ClientDetails details = clientDetailsStore.get(clientId); @@ -38,11 +38,8 @@ public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exceptio return details; } - public Map getClientDetailsStore() { - return clientDetailsStore; - } - public void setClientDetailsStore(Map clientDetailsStore) { - this.clientDetailsStore = clientDetailsStore; + this.clientDetailsStore = new HashMap(clientDetailsStore); } + } \ No newline at end of file diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java new file mode 100644 index 000000000..2f9ad99bb --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java @@ -0,0 +1,200 @@ +/* + * 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.approval; + +import java.util.Calendar; +import java.util.Collection; +import java.util.Date; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.security.core.Authentication; +import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; +import org.springframework.security.oauth2.provider.approval.Approval.ApprovalStatus; +import org.springframework.util.Assert; + +/** + * A user approval handler that remembers approval decisions by consulting existing approvals. + * + * @author Dave Syer + * + */ +public class ApprovalStoreUserApprovalHandler implements UserApprovalHandler, InitializingBean { + + private static Log logger = LogFactory.getLog(ApprovalStoreUserApprovalHandler.class); + + private static final String DEFAULT_SCOPE_PREFIX = "scope."; + + private String scopePrefix = DEFAULT_SCOPE_PREFIX; + + private ApprovalStore approvalStore; + + private int approvalExpiryInMillis = -1; + + /** + * The prefix applied to incoming parameters that signal approval or denial of a scope. + * + * @param scopePrefix the prefix (default "scope.") + */ + public void setScopePrefix(String scopePrefix) { + this.scopePrefix = scopePrefix; + } + + /** + * @param store the approval to set + */ + public void setApprovalStore(ApprovalStore store) { + this.approvalStore = store; + } + + private OAuth2RequestFactory requestFactory; + + public void setRequestFactory(OAuth2RequestFactory requestFactory) { + this.requestFactory = requestFactory; + } + + public void setApprovalExpiryInSeconds(int approvalExpirySeconds) { + this.approvalExpiryInMillis = approvalExpirySeconds * 1000; + } + + public void afterPropertiesSet() { + Assert.state(approvalStore != null, "ApprovalStore must be provided"); + Assert.state(requestFactory != null, "OAuth2RequestFactory must be provided"); + } + + /** + * Requires the authorization request to be explicitly approved, including all individual scopes, and the user to be + * authenticated. A scope that was requested in the authorization request can be approved by sending a request + * parameter scope.<scopename> equal to "true" or "approved" (otherwise it will be assumed to + * have been denied). The {@link ApprovalStore} will be updated to reflect the inputs. + * + * @param authorizationRequest The authorization request. + * @param userAuthentication the current user authentication + * + * @return Whether the specified request has been approved by the current user. + */ + public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { + + boolean approved = authorizationRequest.isApproved(); + if (approved) { + return approved; + } + + // Store the scopes that have been approved / denied + Date expiry = computeExpiry(); + + // Get the approved scopes + Set approvedScopes = new HashSet(); + Set approvals = new HashSet(); + + Map approvalParameters = authorizationRequest.getApprovalParameters(); + for (String requestedScope : authorizationRequest.getScope()) { + String approvalParameter = scopePrefix + requestedScope; + String value = approvalParameters.get(approvalParameter); + value = value == null ? "" : value.toLowerCase(); + if ("true".equals(value) || value.startsWith("approve")) { + approvedScopes.add(requestedScope); + approvals.add(new Approval(userAuthentication.getName(), authorizationRequest.getClientId(), + requestedScope, expiry, ApprovalStatus.APPROVED)); + } + else { + approvals.add(new Approval(userAuthentication.getName(), authorizationRequest.getClientId(), + requestedScope, expiry, ApprovalStatus.DENIED)); + } + } + approvalStore.addApprovals(approvals); + + authorizationRequest.setScope(approvedScopes); + if (approvedScopes.isEmpty()) { + approved = false; + } + else { + approved = true; + } + authorizationRequest.setApproved(true); + return approved; + + } + + public AuthorizationRequest checkForPreApproval( + + AuthorizationRequest authorizationRequest, Authentication userAuthentication) { + + if (logger.isDebugEnabled()) { + StringBuilder builder = new StringBuilder("Looking up user approved authorizations for "); + builder.append("client_id=" + authorizationRequest.getClientId()); + builder.append(" and username=" + userAuthentication.getName()); + logger.debug(builder.toString()); + } + + Collection requestedScopes = authorizationRequest.getScope(); + + // Find the stored approvals for that user and client + Collection userApprovals = approvalStore.getApprovals(userAuthentication.getName(), + authorizationRequest.getClientId()); + + // Look at the scopes and see if they have expired + Set validUserApprovedScopes = new HashSet(); + Set approvedScopes = new HashSet(); + Date today = new Date(); + for (Approval approval : userApprovals) { + if (approval.getExpiresAt().after(today)) { + validUserApprovedScopes.add(approval.getScope()); + if (approval.getStatus() == ApprovalStatus.APPROVED) { + approvedScopes.add(approval.getScope()); + } + } + } + + if (logger.isDebugEnabled()) { + logger.debug("Valid user approved/denied scopes are " + validUserApprovedScopes); + } + + // If the requested scopes have already been acted upon by the user, + // this request is approved + if (validUserApprovedScopes.containsAll(requestedScopes)) { + approvedScopes.retainAll(requestedScopes); + // Set only the scopes that have been approved by the user + authorizationRequest.setScope(approvedScopes); + authorizationRequest.setApproved(true); + } + + return authorizationRequest; + + } + + private Date computeExpiry() { + Calendar expiresAt = Calendar.getInstance(); + if (approvalExpiryInMillis == -1) { // use default of 1 month + expiresAt.add(Calendar.MONTH, 1); + } + else { + expiresAt.add(Calendar.MILLISECOND, approvalExpiryInMillis); + } + return expiresAt.getTime(); + } + + public AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizationRequest, + Authentication userAuthentication) { + return authorizationRequest; + } +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TestApprovalStoreUserApprovalHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TestApprovalStoreUserApprovalHandler.java new file mode 100644 index 000000000..63e4c0d88 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TestApprovalStoreUserApprovalHandler.java @@ -0,0 +1,83 @@ +package org.springframework.security.oauth2.provider.approval; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.BaseClientDetails; +import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.DefaultOAuth2RequestFactory; +import org.springframework.security.oauth2.provider.InMemoryClientDetailsService; + +public class TestApprovalStoreUserApprovalHandler { + + private ApprovalStoreUserApprovalHandler handler = new ApprovalStoreUserApprovalHandler(); + + private InMemoryApprovalStore store = new InMemoryApprovalStore(); + + private Authentication userAuthentication; + + @Before + public void init() { + handler.setApprovalStore(store); + InMemoryClientDetailsService clientDetailsService = new InMemoryClientDetailsService(); + Map map = new HashMap(); + map.put("client", new BaseClientDetails("client", null, "read,write", "authorization_code", null)); + clientDetailsService.setClientDetailsStore(map); + handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService)); + userAuthentication = new UsernamePasswordAuthenticationToken("user", "N/A", + AuthorityUtils.commaSeparatedStringToAuthorityList("USER")); + } + + @Test + public void testExplicitlyApprovedScopes() { + AuthorizationRequest authorizationRequest = new AuthorizationRequest("client", Arrays.asList("read")); + authorizationRequest.setApprovalParameters(Collections.singletonMap("scope.read", "approved")); + assertTrue(handler.isApproved(authorizationRequest, userAuthentication)); + assertEquals(1, store.getApprovals("user", "client").size()); + assertEquals(1, authorizationRequest.getScope().size()); + assertTrue(authorizationRequest.isApproved()); + } + + @Test + public void testImplicitlyDeniedScope() { + AuthorizationRequest authorizationRequest = new AuthorizationRequest("client", Arrays.asList("read", "write")); + authorizationRequest.setApprovalParameters(Collections.singletonMap("scope.read", "approved")); + assertTrue(handler.isApproved(authorizationRequest, userAuthentication)); + Collection approvals = store.getApprovals("user", "client"); + assertEquals(2, approvals.size()); + approvals.contains(new Approval("user", "client", "read", new Date(), Approval.ApprovalStatus.APPROVED)); + approvals.contains(new Approval("user", "client", "write", new Date(), Approval.ApprovalStatus.DENIED)); + assertEquals(1, authorizationRequest.getScope().size()); + } + + @Test + public void testExplicitlyPreapprovedScopes() { + store.addApprovals(Arrays.asList(new Approval("user", "client", "read", new Date(System.currentTimeMillis() + 10000), Approval.ApprovalStatus.APPROVED))); + AuthorizationRequest authorizationRequest = new AuthorizationRequest("client", Arrays.asList("read")); + AuthorizationRequest result = handler.checkForPreApproval(authorizationRequest, userAuthentication); + assertTrue(result.isApproved()); + } + + @Test + public void testExpiredPreapprovedScopes() { + store.addApprovals(Arrays.asList(new Approval("user", "client", "read", new Date(System.currentTimeMillis() - 10000), Approval.ApprovalStatus.APPROVED))); + AuthorizationRequest authorizationRequest = new AuthorizationRequest("client", Arrays.asList("read")); + AuthorizationRequest result = handler.checkForPreApproval(authorizationRequest, userAuthentication); + assertFalse(result.isApproved()); + } + +} From 8c16b3092ba0de10d63d06e6c9610a53f72546af Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 6 Sep 2013 14:01:08 +0100 Subject: [PATCH 082/831] Remove another method from ConsumerTokenServices --- .../examples/sparklr/mvc/AdminController.java | 38 +++++++++---------- .../examples/sparklr/mvc/PhotoController.java | 15 ++++++++ .../sparklr/oauth/SparklrTokenEnhancer.java | 31 +++++++++++++++ .../main/webapp/WEB-INF/spring-servlet.xml | 3 ++ .../provider/token/ConsumerTokenServices.java | 2 - 5 files changed, 66 insertions(+), 23 deletions(-) create mode 100644 samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrTokenEnhancer.java diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AdminController.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AdminController.java index 19746f31c..e7aa9bf5a 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AdminController.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AdminController.java @@ -1,16 +1,27 @@ +/* + * Copyright 2012-2013 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.oauth.examples.sparklr.mvc; import java.security.Principal; -import java.util.ArrayList; import java.util.Collection; -import java.util.HashMap; -import java.util.Map; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.oauth.examples.sparklr.oauth.SparklrUserApprovalHandler; -import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.token.ConsumerTokenServices; @@ -53,7 +64,7 @@ public void stopCaching() throws Exception { public Collection listTokensForUser(@PathVariable String user, Principal principal) throws Exception { checkResourceOwner(user, principal); - return enhance(tokenStore.findTokensByUserName(user)); + return tokenStore.findTokensByUserName(user); } @RequestMapping(value = "/oauth/users/{user}/tokens/{token}", method = RequestMethod.DELETE) @@ -70,22 +81,7 @@ public ResponseEntity revokeToken(@PathVariable String user, @PathVariable @RequestMapping("/oauth/clients/{client}/tokens") @ResponseBody public Collection listTokensForClient(@PathVariable String client) throws Exception { - return enhance(tokenStore.findTokensByClientId(client)); - } - - private Collection enhance(Collection tokens) { - Collection result = new ArrayList(); - for (OAuth2AccessToken prototype : tokens) { - DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(prototype); - String clientId = tokenServices.getClientId(token.getValue()); - if (clientId != null) { - Map map = new HashMap(token.getAdditionalInformation()); - map.put("client_id", clientId); - token.setAdditionalInformation(map); - result.add(token); - } - } - return result; + return tokenStore.findTokensByClientId(client); } private void checkResourceOwner(String user, Principal principal) { diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/PhotoController.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/PhotoController.java index 023e498fc..3062db63c 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/PhotoController.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/PhotoController.java @@ -1,3 +1,18 @@ +/* + * Copyright 2012-2013 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.oauth.examples.sparklr.mvc; import java.io.ByteArrayOutputStream; diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrTokenEnhancer.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrTokenEnhancer.java new file mode 100644 index 000000000..505ac4903 --- /dev/null +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrTokenEnhancer.java @@ -0,0 +1,31 @@ +/* + * Copyright 2012-2013 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.oauth.examples.sparklr.oauth; + +import java.util.Collections; + +import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.token.TokenEnhancer; + +public class SparklrTokenEnhancer implements TokenEnhancer { + + @Override + public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { + DefaultOAuth2AccessToken result = new DefaultOAuth2AccessToken(accessToken); + result.setAdditionalInformation(Collections.singletonMap("client_id", (Object) authentication.getOAuth2Request().getClientId())); + return result; + } + +} diff --git a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml index 780545d1d..a09cd3b57 100644 --- a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml +++ b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml @@ -120,10 +120,13 @@ + + + diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/ConsumerTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/ConsumerTokenServices.java index 807e114e1..68dbb019a 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/ConsumerTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/ConsumerTokenServices.java @@ -21,6 +21,4 @@ public interface ConsumerTokenServices { boolean revokeToken(String tokenValue); - String getClientId(String tokenValue); - } From d421b58e01b30c5a084d8851604a0623bd998ed5 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 6 Sep 2013 17:46:40 +0100 Subject: [PATCH 083/831] User approvals UI for sprarkl2 --- .../mvc/AccessConfirmationController.java | 31 +++++- .../examples/sparklr/mvc/AdminController.java | 4 +- .../oauth/SparklrUserApprovalHandler.java | 17 ++- .../WEB-INF/jsp/access_confirmation.jsp | 11 +- .../main/webapp/WEB-INF/spring-servlet.xml | 7 +- .../oauth2/provider/TestImplicitProvider.java | 1 + .../oauth2/client/OAuth2RestTemplate.java | 4 +- .../AuthorizationCodeAccessTokenProvider.java | 14 +++ .../OAuth2ExceptionJackson1Deserializer.java | 4 + .../oauth2/common/util/OAuth2Utils.java | 5 + .../ApprovalStoreUserApprovalHandler.java | 104 +++++++++--------- .../approval/DefaultUserApprovalHandler.java | 9 +- .../TokenStoreUserApprovalHandler.java | 14 +-- .../endpoint/AuthorizationEndpoint.java | 1 + 14 files changed, 134 insertions(+), 92 deletions(-) diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AccessConfirmationController.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AccessConfirmationController.java index 30a50d18d..0239b1994 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AccessConfirmationController.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AccessConfirmationController.java @@ -1,11 +1,16 @@ package org.springframework.security.oauth.examples.sparklr.mvc; +import java.security.Principal; +import java.util.LinkedHashMap; import java.util.Map; -import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.oauth2.common.util.OAuth2Utils; +import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; -import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.approval.Approval; +import org.springframework.security.oauth2.provider.approval.Approval.ApprovalStatus; +import org.springframework.security.oauth2.provider.approval.ApprovalStore; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.SessionAttributes; @@ -22,12 +27,26 @@ public class AccessConfirmationController { private ClientDetailsService clientDetailsService; + private ApprovalStore approvalStore; + @RequestMapping("/oauth/confirm_access") - public ModelAndView getAccessConfirmation(Map model) throws Exception { + public ModelAndView getAccessConfirmation(Map model, Principal principal) throws Exception { AuthorizationRequest clientAuth = (AuthorizationRequest) model.remove("authorizationRequest"); ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId()); model.put("auth_request", clientAuth); model.put("client", client); + Map scopes = new LinkedHashMap(); + for (Approval approval : approvalStore.getApprovals(principal.getName(), client.getClientId())) { + if (clientAuth.getScope().contains(approval.getScope())) { + scopes.put(OAuth2Utils.SCOPE_PREFIX + approval.getScope(), approval.getStatus()==ApprovalStatus.APPROVED ? "true" : "false"); + } + } + for (String scope : clientAuth.getScope()) { + if (!scopes.containsKey(OAuth2Utils.SCOPE_PREFIX + scope)) { + scopes.put(OAuth2Utils.SCOPE_PREFIX + scope, "false"); + } + } + model.put("scopes", scopes); return new ModelAndView("access_confirmation", model); } @@ -39,8 +58,12 @@ public String handleError(Map model) throws Exception { return "oauth_error"; } - @Autowired public void setClientDetailsService(ClientDetailsService clientDetailsService) { this.clientDetailsService = clientDetailsService; } + + public void setApprovalStore(ApprovalStore approvalStore) { + this.approvalStore = approvalStore; + } + } diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AdminController.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AdminController.java index e7aa9bf5a..e7e0e8212 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AdminController.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AdminController.java @@ -50,13 +50,13 @@ public class AdminController { @RequestMapping("/oauth/cache_approvals") @ResponseStatus(HttpStatus.NO_CONTENT) public void startCaching() throws Exception { - userApprovalHandler.setUseTokenServices(true); + userApprovalHandler.setUseApprovalStore(true); } @RequestMapping("/oauth/uncache_approvals") @ResponseStatus(HttpStatus.NO_CONTENT) public void stopCaching() throws Exception { - userApprovalHandler.setUseTokenServices(false); + userApprovalHandler.setUseApprovalStore(false); } @RequestMapping("/oauth/users/{user}/tokens") diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrUserApprovalHandler.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrUserApprovalHandler.java index 7c1bafbe5..77059775b 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrUserApprovalHandler.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrUserApprovalHandler.java @@ -21,23 +21,23 @@ import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.provider.AuthorizationRequest; -import org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler; +import org.springframework.security.oauth2.provider.approval.ApprovalStoreUserApprovalHandler; /** * @author Dave Syer * */ -public class SparklrUserApprovalHandler extends TokenStoreUserApprovalHandler { +public class SparklrUserApprovalHandler extends ApprovalStoreUserApprovalHandler { private Collection autoApproveClients = new HashSet(); - private boolean useTokenServices = true; + private boolean useApprovalStore = true; /** - * @param useTokenServices the useTokenServices to set + * @param useApprovalStore the useTokenServices to set */ - public void setUseTokenServices(boolean useTokenServices) { - this.useTokenServices = useTokenServices; + public void setUseApprovalStore(boolean useApprovalStore) { + this.useApprovalStore = useApprovalStore; } /** @@ -61,13 +61,10 @@ public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizati boolean approved = false; // If we are allowed to check existing approvals this will short circuit the decision - if (useTokenServices) { + if (useApprovalStore) { authorizationRequest = super.checkForPreApproval(authorizationRequest, userAuthentication); approved = authorizationRequest.isApproved(); } - else if (!userAuthentication.isAuthenticated()) { - approved = false; - } else { approved = (authorizationRequest.getResponseTypes().contains("token") && autoApproveClients .contains(authorizationRequest.getClientId())); diff --git a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/jsp/access_confirmation.jsp b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/jsp/access_confirmation.jsp index 2ef9ca924..ea8cb8f90 100644 --- a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/jsp/access_confirmation.jsp +++ b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/jsp/access_confirmation.jsp @@ -33,11 +33,12 @@

- -
-
- - +
    + checked checked +
  • ${scope.key}: ApproveDeny
  • +
    +
+
diff --git a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml index a09cd3b57..d863055b1 100644 --- a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml +++ b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml @@ -137,9 +137,13 @@ my-less-trusted-autoapprove-client
- + + + + + @@ -221,6 +225,7 @@ + diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestImplicitProvider.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestImplicitProvider.java index 9d8e18cdc..e8e813f9d 100644 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestImplicitProvider.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestImplicitProvider.java @@ -100,6 +100,7 @@ public void testPostForNonAutomaticApprovalToken() throws Exception { } // add user approval parameter for the second request context.getAccessTokenRequest().add(OAuth2Utils.USER_OAUTH_APPROVAL, "true"); + context.getAccessTokenRequest().add("scope.read", "true"); assertNotNull(context.getAccessToken()); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/OAuth2RestTemplate.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/OAuth2RestTemplate.java index b37c0fb61..dbeb25532 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/OAuth2RestTemplate.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/OAuth2RestTemplate.java @@ -130,7 +130,7 @@ protected T doExecute(URI url, HttpMethod method, RequestCallback requestCal } catch (InvalidTokenException e) { // Don't reveal the token value in case it is logged - rethrow = new OAuth2AccessDeniedException("Invalid token for client="+getClientId()); + rethrow = new OAuth2AccessDeniedException("Invalid token for client=" + getClientId()); } if (accessToken != null && retryBadAccessTokens) { context.setAccessToken(null); @@ -139,7 +139,7 @@ protected T doExecute(URI url, HttpMethod method, RequestCallback requestCal } catch (InvalidTokenException e) { // Don't reveal the token value in case it is logged - rethrow = new OAuth2AccessDeniedException("Invalid token for client="+getClientId()); + rethrow = new OAuth2AccessDeniedException("Invalid token for client=" + getClientId()); } } throw rethrow; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProvider.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProvider.java index 77ce2355a..1dc5748d2 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProvider.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProvider.java @@ -70,6 +70,17 @@ public class AuthorizationCodeAccessTokenProvider extends OAuth2AccessTokenSupport implements AccessTokenProvider { private StateKeyGenerator stateKeyGenerator = new DefaultStateKeyGenerator(); + + private String scopePrefix = OAuth2Utils.SCOPE_PREFIX; + + /** + * Prefix for scope approval pamaremeters. + * + * @param scopePrefix + */ + public void setScopePrefix(String scopePrefix) { + this.scopePrefix = scopePrefix; + } /** * @param stateKeyGenerator the stateKeyGenerator to set @@ -98,6 +109,9 @@ public String obtainAuthorizationCode(OAuth2ProtectedResourceDetails details, Ac if (request.containsKey(OAuth2Utils.USER_OAUTH_APPROVAL)) { form.set(OAuth2Utils.USER_OAUTH_APPROVAL, request.getFirst(OAuth2Utils.USER_OAUTH_APPROVAL)); + for (String scope : details.getScope()) { + form.set(scopePrefix + scope, request.getFirst(OAuth2Utils.USER_OAUTH_APPROVAL)); + } } else { form.putAll(getParametersForAuthorizeRequest(resource, request)); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson1Deserializer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson1Deserializer.java index 52221d953..8bf9fbffa 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson1Deserializer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson1Deserializer.java @@ -23,6 +23,7 @@ import org.codehaus.jackson.JsonToken; import org.codehaus.jackson.map.DeserializationContext; import org.codehaus.jackson.map.JsonDeserializer; +import org.springframework.security.oauth2.common.util.OAuth2Utils; /** * @author Dave Syer @@ -100,6 +101,9 @@ else if ("unsupported_response_type".equals(errorCode)) { else if ("access_denied".equals(errorCode)) { ex = new UserDeniedAuthorizationException(errorMessage); } + else if ("insufficient_scope".equals(errorCode)) { + ex = new InsufficientScopeException(errorMessage, OAuth2Utils.parseParameterList((String)errorParams.get("scope"))); + } else { ex = new OAuth2Exception(errorMessage); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/OAuth2Utils.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/OAuth2Utils.java index 1adf39ff1..e9258970f 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/OAuth2Utils.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/OAuth2Utils.java @@ -62,6 +62,11 @@ public abstract class OAuth2Utils { */ public static final String USER_OAUTH_APPROVAL = "user_oauth_approval"; + /** + * Constant to use as a prefix for scope approval + */ + public static final String SCOPE_PREFIX = "scope."; + /** * Constant to use while parsing and formatting parameter maps for OAuth2 requests */ diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java index 2f9ad99bb..f95d015da 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java @@ -27,6 +27,7 @@ import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.security.core.Authentication; +import org.springframework.security.oauth2.common.util.OAuth2Utils; import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; import org.springframework.security.oauth2.provider.approval.Approval.ApprovalStatus; @@ -42,9 +43,7 @@ public class ApprovalStoreUserApprovalHandler implements UserApprovalHandler, In private static Log logger = LogFactory.getLog(ApprovalStoreUserApprovalHandler.class); - private static final String DEFAULT_SCOPE_PREFIX = "scope."; - - private String scopePrefix = DEFAULT_SCOPE_PREFIX; + private String scopePrefix = OAuth2Utils.SCOPE_PREFIX; private ApprovalStore approvalStore; @@ -53,7 +52,7 @@ public class ApprovalStoreUserApprovalHandler implements UserApprovalHandler, In /** * The prefix applied to incoming parameters that signal approval or denial of a scope. * - * @param scopePrefix the prefix (default "scope.") + * @param scopePrefix the prefix (default {@link OAuth2Utils#SCOPE_PREFIX}) */ public void setScopePrefix(String scopePrefix) { this.scopePrefix = scopePrefix; @@ -81,58 +80,8 @@ public void afterPropertiesSet() { Assert.state(requestFactory != null, "OAuth2RequestFactory must be provided"); } - /** - * Requires the authorization request to be explicitly approved, including all individual scopes, and the user to be - * authenticated. A scope that was requested in the authorization request can be approved by sending a request - * parameter scope.<scopename> equal to "true" or "approved" (otherwise it will be assumed to - * have been denied). The {@link ApprovalStore} will be updated to reflect the inputs. - * - * @param authorizationRequest The authorization request. - * @param userAuthentication the current user authentication - * - * @return Whether the specified request has been approved by the current user. - */ public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { - - boolean approved = authorizationRequest.isApproved(); - if (approved) { - return approved; - } - - // Store the scopes that have been approved / denied - Date expiry = computeExpiry(); - - // Get the approved scopes - Set approvedScopes = new HashSet(); - Set approvals = new HashSet(); - - Map approvalParameters = authorizationRequest.getApprovalParameters(); - for (String requestedScope : authorizationRequest.getScope()) { - String approvalParameter = scopePrefix + requestedScope; - String value = approvalParameters.get(approvalParameter); - value = value == null ? "" : value.toLowerCase(); - if ("true".equals(value) || value.startsWith("approve")) { - approvedScopes.add(requestedScope); - approvals.add(new Approval(userAuthentication.getName(), authorizationRequest.getClientId(), - requestedScope, expiry, ApprovalStatus.APPROVED)); - } - else { - approvals.add(new Approval(userAuthentication.getName(), authorizationRequest.getClientId(), - requestedScope, expiry, ApprovalStatus.DENIED)); - } - } - approvalStore.addApprovals(approvals); - - authorizationRequest.setScope(approvedScopes); - if (approvedScopes.isEmpty()) { - approved = false; - } - else { - approved = true; - } - authorizationRequest.setApproved(true); - return approved; - + return authorizationRequest.isApproved(); } public AuthorizationRequest checkForPreApproval( @@ -193,8 +142,53 @@ private Date computeExpiry() { return expiresAt.getTime(); } + /** + * Requires the authorization request to be explicitly approved, including all individual scopes, and the user to be + * authenticated. A scope that was requested in the authorization request can be approved by sending a request + * parameter scope.<scopename> equal to "true" or "approved" (otherwise it will be assumed to + * have been denied). The {@link ApprovalStore} will be updated to reflect the inputs. + * + * @param authorizationRequest The authorization request. + * @param userAuthentication the current user authentication + * + * @return An approved request if all scopes have been approved by the current user. + */ public AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { + // Get the approved scopes + Set requestedScopes = authorizationRequest.getScope(); + Set approvedScopes = new HashSet(); + Set approvals = new HashSet(); + + Date expiry = computeExpiry(); + + // Store the scopes that have been approved / denied + Map approvalParameters = authorizationRequest.getApprovalParameters(); + for (String requestedScope : requestedScopes) { + String approvalParameter = scopePrefix + requestedScope; + String value = approvalParameters.get(approvalParameter); + value = value == null ? "" : value.toLowerCase(); + if ("true".equals(value) || value.startsWith("approve")) { + approvedScopes.add(requestedScope); + approvals.add(new Approval(userAuthentication.getName(), authorizationRequest.getClientId(), + requestedScope, expiry, ApprovalStatus.APPROVED)); + } + else { + approvals.add(new Approval(userAuthentication.getName(), authorizationRequest.getClientId(), + requestedScope, expiry, ApprovalStatus.DENIED)); + } + } + approvalStore.addApprovals(approvals); + + boolean approved; + authorizationRequest.setScope(approvedScopes); + if (approvedScopes.isEmpty() && !requestedScopes.isEmpty()) { + approved = false; + } + else { + approved = true; + } + authorizationRequest.setApproved(approved); return authorizationRequest; } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/DefaultUserApprovalHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/DefaultUserApprovalHandler.java index 53d9d4cef..f32ae91ed 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/DefaultUserApprovalHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/DefaultUserApprovalHandler.java @@ -52,10 +52,7 @@ public boolean isApproved(AuthorizationRequest authorizationRequest, Authenticat if (authorizationRequest.isApproved()) { return true; } - Map approvalParameters = authorizationRequest.getApprovalParameters(); - String flag = approvalParameters.get(approvalParameter); - boolean approved = flag != null && flag.toLowerCase().equals("true"); - return userAuthentication.isAuthenticated() && approved; + return false; } public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { @@ -63,6 +60,10 @@ public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizati } public AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { + Map approvalParameters = authorizationRequest.getApprovalParameters(); + String flag = approvalParameters.get(approvalParameter); + boolean approved = flag != null && flag.toLowerCase().equals("true"); + authorizationRequest.setApproved(approved); return authorizationRequest; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandler.java index e9672a2b0..d3b5a605c 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandler.java @@ -80,15 +80,7 @@ public void afterPropertiesSet() { * @return Whether the specified request has been approved by the current user. */ public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { - - if (authorizationRequest.isApproved()) { - return true; - } - Map approvalParameters = authorizationRequest.getApprovalParameters(); - String flag = approvalParameters.get(approvalParameter); - boolean approved = flag != null && flag.toLowerCase().equals("true"); - return userAuthentication.isAuthenticated() && approved; - + return authorizationRequest.isApproved(); } public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { @@ -124,6 +116,10 @@ public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizati } public AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { + Map approvalParameters = authorizationRequest.getApprovalParameters(); + String flag = approvalParameters.get(approvalParameter); + boolean approved = flag != null && flag.toLowerCase().equals("true"); + authorizationRequest.setApproved(approved); return authorizationRequest; } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java index 2c5bc7fbd..1a9f324e8 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java @@ -166,6 +166,7 @@ public ModelAndView authorize(Map model, @RequestParam Map Date: Mon, 9 Sep 2013 08:11:53 -0700 Subject: [PATCH 084/831] Update sparklr approvals UI --- .../mvc/AccessConfirmationController.java | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AccessConfirmationController.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AccessConfirmationController.java index 0239b1994..d5ce94688 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AccessConfirmationController.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AccessConfirmationController.java @@ -35,15 +35,14 @@ public ModelAndView getAccessConfirmation(Map model, Principal p ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId()); model.put("auth_request", clientAuth); model.put("client", client); - Map scopes = new LinkedHashMap(); - for (Approval approval : approvalStore.getApprovals(principal.getName(), client.getClientId())) { - if (clientAuth.getScope().contains(approval.getScope())) { - scopes.put(OAuth2Utils.SCOPE_PREFIX + approval.getScope(), approval.getStatus()==ApprovalStatus.APPROVED ? "true" : "false"); - } - } + Map scopes = new LinkedHashMap(); for (String scope : clientAuth.getScope()) { - if (!scopes.containsKey(OAuth2Utils.SCOPE_PREFIX + scope)) { - scopes.put(OAuth2Utils.SCOPE_PREFIX + scope, "false"); + scopes.put(OAuth2Utils.SCOPE_PREFIX + scope, "false"); + } + for (Approval approval : approvalStore.getApprovals(principal.getName(), client.getClientId())) { + if (clientAuth.getScope().contains(approval.getScope())) { + scopes.put(OAuth2Utils.SCOPE_PREFIX + approval.getScope(), + approval.getStatus() == ApprovalStatus.APPROVED ? "true" : "false"); } } model.put("scopes", scopes); @@ -51,8 +50,8 @@ public ModelAndView getAccessConfirmation(Map model, Principal p } @RequestMapping("/oauth/error") - public String handleError(Map model) throws Exception { - // We can add more stuff to the model here for JSP rendering. If the client was a machine then + public String handleError(Map model) throws Exception { + // We can add more stuff to the model here for JSP rendering. If the client was a machine then // the JSON will already have been rendered. model.put("message", "There was a problem with the OAuth2 protocol"); return "oauth_error"; From 9daec97cb8cce92beee29b1511c25e1c090d7d6b Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 9 Sep 2013 08:12:18 -0700 Subject: [PATCH 085/831] Add autoapprove to client details --- .../oauth2/provider/BaseClientDetails.java | 18 ++++++++++++++++++ .../oauth2/provider/ClientDetails.java | 17 ++++++++++++++++- .../provider/JdbcClientDetailsService.java | 17 +++++++++++++---- .../provider/TestJdbcClientDetailsService.java | 13 +++++++------ .../src/test/resources/schema.sql | 6 ++++-- 5 files changed, 58 insertions(+), 13 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseClientDetails.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseClientDetails.java index 07cbcd4c3..5d5fde49b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseClientDetails.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseClientDetails.java @@ -63,6 +63,10 @@ public class BaseClientDetails implements ClientDetails { @JsonDeserialize(using = ArrayOrStringDeserializer.class) private Set registeredRedirectUris; + @JsonProperty("autoapprove") + @JsonDeserialize(using = ArrayOrStringDeserializer.class) + private Set autoApproveScopes; + private List authorities = Collections.emptyList(); @JsonProperty("access_token_validity") @@ -137,6 +141,20 @@ public String getClientId() { public void setClientId(String clientId) { this.clientId = clientId; } + + public void setAutoApproveScopes(Set autoApproveScopes) { + this.autoApproveScopes = autoApproveScopes; + } + + @Override + public Set getAutoApproveScopes() { + return autoApproveScopes; + } + + @Override + public boolean isAutoApprove(String scope) { + return autoApproveScopes.contains("true") || autoApproveScopes.contains(scope); + } @JsonIgnore public boolean isSecretRequired() { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientDetails.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientDetails.java index e9e6c7616..00e66b1ae 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientDetails.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientDetails.java @@ -95,9 +95,24 @@ public interface ClientDetails extends Serializable { * @return the refresh token validity period */ Integer getRefreshTokenValiditySeconds(); + + /** + * The set of scopes that will be autoapproved (if a user approval is required). + * + * @return the scopes that will be autoapproved (or empty if none) + */ + Set getAutoApproveScopes(); + + /** + * Test whether client needs user approval for a particular scope. + * + * @param scope the scope to consider + * @return true if this client does not need user approval + */ + boolean isAutoApprove(String scope); /** - * Additional information for this client, not neeed by the vanilla OAuth protocol but might be useful, for example, + * Additional information for this client, not needed by the vanilla OAuth protocol but might be useful, for example, * for storing descriptive information. * * @return a map of additional information diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/JdbcClientDetailsService.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/JdbcClientDetailsService.java index 7420acde0..b9238efb4 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/JdbcClientDetailsService.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/JdbcClientDetailsService.java @@ -51,7 +51,7 @@ public class JdbcClientDetailsService implements ClientDetailsService, ClientReg private static final String CLIENT_FIELDS_FOR_UPDATE = "resource_ids, scope, " + "authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, " - + "refresh_token_validity, additional_information"; + + "refresh_token_validity, additional_information, autoapprove"; private static final String CLIENT_FIELDS = "client_secret, " + CLIENT_FIELDS_FOR_UPDATE; @@ -63,7 +63,7 @@ public class JdbcClientDetailsService implements ClientDetailsService, ClientReg private static final String DEFAULT_SELECT_STATEMENT = BASE_FIND_STATEMENT + " where client_id = ?"; private static final String DEFAULT_INSERT_STATEMENT = "insert into oauth_client_details (" + CLIENT_FIELDS - + ", client_id) values (?,?,?,?,?,?,?,?,?,?)"; + + ", client_id) values (?,?,?,?,?,?,?,?,?,?,?)"; private static final String DEFAULT_UPDATE_STATEMENT = "update oauth_client_details " + "set " + CLIENT_FIELDS_FOR_UPDATE.replaceAll(", ", "=?, ") + "=? where client_id = ?"; @@ -179,8 +179,13 @@ private Object[] getFieldsForUpdate(ClientDetails clientDetails) { clientDetails.getRegisteredRedirectUri() != null ? StringUtils .collectionToCommaDelimitedString(clientDetails.getRegisteredRedirectUri()) : null, clientDetails.getAuthorities() != null ? StringUtils.collectionToCommaDelimitedString(clientDetails - .getAuthorities()) : null, clientDetails.getAccessTokenValiditySeconds(), - clientDetails.getRefreshTokenValiditySeconds(), json, clientDetails.getClientId() }; + .getAuthorities()) : null, + clientDetails.getAccessTokenValiditySeconds(), + clientDetails.getRefreshTokenValiditySeconds(), + json, + clientDetails.getAutoApproveScopes() != null ? StringUtils + .collectionToCommaDelimitedString(clientDetails.getAutoApproveScopes()) : null, + clientDetails.getClientId() }; } public void setSelectClientDetailsSql(String selectClientDetailsSql) { @@ -251,6 +256,10 @@ public ClientDetails mapRow(ResultSet rs, int rowNum) throws SQLException { logger.warn("Could not decode JSON for additional information: " + details, e); } } + String scopes = rs.getString(11); + if (scopes != null) { + details.setAutoApproveScopes(StringUtils.commaDelimitedListToSet(scopes)); + } return details; } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestJdbcClientDetailsService.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestJdbcClientDetailsService.java index 2ed49744f..642e45341 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestJdbcClientDetailsService.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestJdbcClientDetailsService.java @@ -29,7 +29,7 @@ public class TestJdbcClientDetailsService { private static final String SELECT_SQL = "select client_id, client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity from oauth_client_details where client_id=?"; - private static final String INSERT_SQL = "insert into oauth_client_details (client_id, client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity) values (?, ?, ?, ?, ?, ?, ?, ?, ?)"; + private static final String INSERT_SQL = "insert into oauth_client_details (client_id, client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, autoapprove) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; private static final String CUSTOM_INSERT_SQL = "insert into ClientDetails (appId, appSecret, resourceIds, scope, grantTypes, redirectUrl, authorities) values (?, ?, ?, ?, ?, ?, ?)"; @@ -53,7 +53,7 @@ public void testLoadingClientForNonExistingClientId() { @Test public void testLoadingClientIdWithNoDetails() { - jdbcTemplate.update(INSERT_SQL, "clientIdWithNoDetails", null, null, null, null, null, null, null, null); + jdbcTemplate.update(INSERT_SQL, "clientIdWithNoDetails", null, null, null, null, null, null, null, null, null); ClientDetails clientDetails = service.loadClientByClientId("clientIdWithNoDetails"); @@ -71,7 +71,7 @@ public void testLoadingClientIdWithNoDetails() { @Test public void testLoadingClientIdWithAdditionalInformation() { - jdbcTemplate.update(INSERT_SQL, "clientIdWithAddInfo", null, null, null, null, null, null, null, null); + jdbcTemplate.update(INSERT_SQL, "clientIdWithAddInfo", null, null, null, null, null, null, null, null, null); jdbcTemplate.update("update oauth_client_details set additional_information=? where client_id=?", "{\"foo\":\"bar\"}", "clientIdWithAddInfo"); ClientDetails clientDetails = service.loadClientByClientId("clientIdWithAddInfo"); @@ -83,7 +83,7 @@ public void testLoadingClientIdWithAdditionalInformation() { @Test public void testLoadingClientIdWithSingleDetails() { jdbcTemplate.update(INSERT_SQL, "clientIdWithSingleDetails", "mySecret", "myResource", "myScope", - "myAuthorizedGrantType", "myRedirectUri", "myAuthority", 100, 200); + "myAuthorizedGrantType", "myRedirectUri", "myAuthority", 100, 200, "true"); ClientDetails clientDetails = service.loadClientByClientId("clientIdWithSingleDetails"); @@ -112,7 +112,7 @@ public void testLoadingClientIdWithSingleDetailsInCustomTable() { JdbcClientDetailsService customService = new JdbcClientDetailsService(db); customService .setSelectClientDetailsSql("select appId, appSecret, resourceIds, scope, " - + "grantTypes, redirectUrl, authorities, access_token_validity, refresh_token_validity, additionalInformation from ClientDetails where appId = ?"); + + "grantTypes, redirectUrl, authorities, access_token_validity, refresh_token_validity, additionalInformation, autoApproveScopes from ClientDetails where appId = ?"); ClientDetails clientDetails = customService.loadClientByClientId("clientIdWithSingleDetails"); @@ -135,7 +135,7 @@ public void testLoadingClientIdWithSingleDetailsInCustomTable() { public void testLoadingClientIdWithMultipleDetails() { jdbcTemplate.update(INSERT_SQL, "clientIdWithMultipleDetails", "mySecret", "myResource1,myResource2", "myScope1,myScope2", "myAuthorizedGrantType1,myAuthorizedGrantType2", "myRedirectUri1,myRedirectUri2", - "myAuthority1,myAuthority2", 100, 200); + "myAuthority1,myAuthority2", 100, 200, "read,write"); ClientDetails clientDetails = service.loadClientByClientId("clientIdWithMultipleDetails"); @@ -165,6 +165,7 @@ public void testLoadingClientIdWithMultipleDetails() { assertEquals("myAuthority2", authorities.next().getAuthority()); assertEquals(new Integer(100), clientDetails.getAccessTokenValiditySeconds()); assertEquals(new Integer(200), clientDetails.getRefreshTokenValiditySeconds()); + assertEquals(2, clientDetails.getAutoApproveScopes().size()); } @Test diff --git a/spring-security-oauth2/src/test/resources/schema.sql b/spring-security-oauth2/src/test/resources/schema.sql index e6d1ecfca..03b3d4ac4 100644 --- a/spring-security-oauth2/src/test/resources/schema.sql +++ b/spring-security-oauth2/src/test/resources/schema.sql @@ -9,7 +9,8 @@ create table oauth_client_details ( authorities VARCHAR(256), access_token_validity INTEGER, refresh_token_validity INTEGER, - additional_information VARCHAR(4096) + additional_information VARCHAR(4096), + autoapprove VARCHAR(256) ); create table oauth_client_token ( @@ -61,5 +62,6 @@ create table ClientDetails ( authorities VARCHAR(256), access_token_validity INTEGER, refresh_token_validity INTEGER, - additionalInformation VARCHAR(4096) + additionalInformation VARCHAR(4096), + autoApproveScopes VARCHAR(256) ); From e171dad81640d775466a69ccab8ac8ed2a81fa6c Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 9 Sep 2013 08:41:58 -0700 Subject: [PATCH 086/831] Add autoapproval to approval handlers --- .../oauth2/provider/BaseClientDetails.java | 13 ++--- .../oauth2/provider/ClientDetails.java | 7 --- .../provider/JdbcClientDetailsService.java | 18 ++++++- .../ApprovalStoreUserApprovalHandler.java | 50 +++++++++++++++---- .../TokenStoreUserApprovalHandler.java | 44 ++++++++++++++-- .../provider/TestBaseClientDetails.java | 26 ++++++++++ .../TestJdbcClientDetailsService.java | 2 +- 7 files changed, 128 insertions(+), 32 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseClientDetails.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseClientDetails.java index 5d5fde49b..0772affbe 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseClientDetails.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseClientDetails.java @@ -141,19 +141,14 @@ public String getClientId() { public void setClientId(String clientId) { this.clientId = clientId; } - + public void setAutoApproveScopes(Set autoApproveScopes) { this.autoApproveScopes = autoApproveScopes; } - - @Override - public Set getAutoApproveScopes() { - return autoApproveScopes; - } - + @Override public boolean isAutoApprove(String scope) { - return autoApproveScopes.contains("true") || autoApproveScopes.contains(scope); + return autoApproveScopes != null && (autoApproveScopes.contains("true") || autoApproveScopes.contains(scope)); } @JsonIgnore @@ -294,7 +289,7 @@ public void addAdditionalInformation(String key, Object value) { public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + ((accessTokenValiditySeconds==null) ? 0 : accessTokenValiditySeconds); + result = prime * result + ((accessTokenValiditySeconds == null) ? 0 : accessTokenValiditySeconds); result = prime * result + ((refreshTokenValiditySeconds == null) ? 0 : refreshTokenValiditySeconds); result = prime * result + ((authorities == null) ? 0 : authorities.hashCode()); result = prime * result + ((authorizedGrantTypes == null) ? 0 : authorizedGrantTypes.hashCode()); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientDetails.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientDetails.java index 00e66b1ae..45bbd4d30 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientDetails.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientDetails.java @@ -96,13 +96,6 @@ public interface ClientDetails extends Serializable { */ Integer getRefreshTokenValiditySeconds(); - /** - * The set of scopes that will be autoapproved (if a user approval is required). - * - * @return the scopes that will be autoapproved (or empty if none) - */ - Set getAutoApproveScopes(); - /** * Test whether client needs user approval for a particular scope. * diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/JdbcClientDetailsService.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/JdbcClientDetailsService.java index b9238efb4..c7ff1ac7d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/JdbcClientDetailsService.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/JdbcClientDetailsService.java @@ -19,8 +19,10 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import javax.sql.DataSource; @@ -183,11 +185,23 @@ private Object[] getFieldsForUpdate(ClientDetails clientDetails) { clientDetails.getAccessTokenValiditySeconds(), clientDetails.getRefreshTokenValiditySeconds(), json, - clientDetails.getAutoApproveScopes() != null ? StringUtils - .collectionToCommaDelimitedString(clientDetails.getAutoApproveScopes()) : null, + getAutoApproveScopes(clientDetails), clientDetails.getClientId() }; } + private String getAutoApproveScopes(ClientDetails clientDetails) { + if (clientDetails.isAutoApprove("true")) { + return "true"; // all scopes autoapproved + } + Set scopes = new HashSet(); + for (String scope : clientDetails.getScope()) { + if (clientDetails.isAutoApprove(scope)) { + scopes.add(scope); + } + } + return StringUtils.collectionToCommaDelimitedString(scopes); + } + public void setSelectClientDetailsSql(String selectClientDetailsSql) { this.selectClientDetailsSql = selectClientDetailsSql; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java index f95d015da..fbce23b43 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java @@ -29,6 +29,9 @@ import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.common.util.OAuth2Utils; import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.ClientRegistrationException; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; import org.springframework.security.oauth2.provider.approval.Approval.ApprovalStatus; import org.springframework.util.Assert; @@ -49,6 +52,17 @@ public class ApprovalStoreUserApprovalHandler implements UserApprovalHandler, In private int approvalExpiryInMillis = -1; + private ClientDetailsService clientDetailsService; + + /** + * Service to load client details (optional) for auto approval checks. + * + * @param clientDetailsService a client details service + */ + public void setClientDetailsService(ClientDetailsService clientDetailsService) { + this.clientDetailsService = clientDetailsService; + } + /** * The prefix applied to incoming parameters that signal approval or denial of a scope. * @@ -84,26 +98,44 @@ public boolean isApproved(AuthorizationRequest authorizationRequest, Authenticat return authorizationRequest.isApproved(); } - public AuthorizationRequest checkForPreApproval( + public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest, + Authentication userAuthentication) { - AuthorizationRequest authorizationRequest, Authentication userAuthentication) { + String clientId = authorizationRequest.getClientId(); + Collection requestedScopes = authorizationRequest.getScope(); + Set approvedScopes = new HashSet(); + Set validUserApprovedScopes = new HashSet(); + + if (clientDetailsService != null) { + try { + ClientDetails client = clientDetailsService.loadClientByClientId(clientId); + for (String scope : requestedScopes) { + if (client.isAutoApprove(scope)) { + approvedScopes.add(scope); + } + } + if (approvedScopes.containsAll(requestedScopes)) { + authorizationRequest.setApproved(true); + return authorizationRequest; + } + } + catch (ClientRegistrationException e) { + logger.warn("Client registration problem prevent autoapproval check for client=" + clientId); + } + } if (logger.isDebugEnabled()) { StringBuilder builder = new StringBuilder("Looking up user approved authorizations for "); - builder.append("client_id=" + authorizationRequest.getClientId()); + builder.append("client_id=" + clientId); builder.append(" and username=" + userAuthentication.getName()); logger.debug(builder.toString()); } - Collection requestedScopes = authorizationRequest.getScope(); - // Find the stored approvals for that user and client Collection userApprovals = approvalStore.getApprovals(userAuthentication.getName(), - authorizationRequest.getClientId()); + clientId); // Look at the scopes and see if they have expired - Set validUserApprovedScopes = new HashSet(); - Set approvedScopes = new HashSet(); Date today = new Date(); for (Approval approval : userApprovals) { if (approval.getExpiresAt().after(today)) { @@ -161,7 +193,7 @@ public AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizati Set approvals = new HashSet(); Date expiry = computeExpiry(); - + // Store the scopes that have been approved / denied Map approvalParameters = authorizationRequest.getApprovalParameters(); for (String requestedScope : requestedScopes) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandler.java index d3b5a605c..e91c020af 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandler.java @@ -17,6 +17,7 @@ package org.springframework.security.oauth2.provider.approval; import java.util.Map; +import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -25,6 +26,9 @@ import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.util.OAuth2Utils; import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.ClientRegistrationException; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; @@ -43,6 +47,19 @@ public class TokenStoreUserApprovalHandler implements UserApprovalHandler, Initi private String approvalParameter = OAuth2Utils.USER_OAUTH_APPROVAL; + private TokenStore tokenStore; + + private ClientDetailsService clientDetailsService; + + /** + * Service to load client details (optional) for auto approval checks. + * + * @param clientDetailsService a client details service + */ + public void setClientDetailsService(ClientDetailsService clientDetailsService) { + this.clientDetailsService = clientDetailsService; + } + /** * @param approvalParameter the approvalParameter to set */ @@ -50,8 +67,6 @@ public void setApprovalParameter(String approvalParameter) { this.approvalParameter = approvalParameter; } - private TokenStore tokenStore; - /** * @param tokenStore the token store to set */ @@ -87,13 +102,34 @@ public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizati boolean approved = false; + String clientId = authorizationRequest.getClientId(); + Set scopes = authorizationRequest.getScope(); + if (clientDetailsService!=null) { + try { + ClientDetails client = clientDetailsService.loadClientByClientId(clientId); + approved = true; + for (String scope : scopes) { + if (!client.isAutoApprove(scope)) { + approved = false; + } + } + if (approved) { + authorizationRequest.setApproved(true); + return authorizationRequest; + } + } + catch (ClientRegistrationException e) { + logger.warn("Client registration problem prevent autoapproval check for client=" + clientId); + } + } + OAuth2Request storedOAuth2Request = requestFactory.createOAuth2Request(authorizationRequest); OAuth2Authentication authentication = new OAuth2Authentication(storedOAuth2Request, userAuthentication); if (logger.isDebugEnabled()) { StringBuilder builder = new StringBuilder("Looking up existing token for "); - builder.append("client_id=" + authorizationRequest.getClientId()); - builder.append(", scope=" + authorizationRequest.getScope()); + builder.append("client_id=" + clientId); + builder.append(", scope=" + scopes); builder.append(" and username=" + userAuthentication.getName()); logger.debug(builder.toString()); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestBaseClientDetails.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestBaseClientDetails.java index 6514adbad..bba845c72 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestBaseClientDetails.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestBaseClientDetails.java @@ -17,12 +17,14 @@ package org.springframework.security.oauth2.provider; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.util.Collections; import org.codehaus.jackson.map.ObjectMapper; import org.junit.Test; +import org.springframework.util.StringUtils; /** * @author Dave Syer @@ -54,6 +56,30 @@ public void testBaseClientDetailsConvenienceConstructor() { assertEquals("[ROLE_USER]", details.getAuthorities().toString()); } + /** + * test explicit autoapprove + */ + @Test + public void testBaseClientDetailsAutoApprove() { + BaseClientDetails details = new BaseClientDetails("foo", "", "foo,bar", "authorization_code", "ROLE_USER"); + details.setAutoApproveScopes(StringUtils.commaDelimitedListToSet("read,write")); + assertTrue(details.isAutoApprove("read")); + } + + @Test + public void testBaseClientDetailsImplicitAutoApprove() { + BaseClientDetails details = new BaseClientDetails("foo", "", "foo,bar", "authorization_code", "ROLE_USER"); + details.setAutoApproveScopes(StringUtils.commaDelimitedListToSet("true")); + assertTrue(details.isAutoApprove("read")); + } + + @Test + public void testBaseClientDetailsNoAutoApprove() { + BaseClientDetails details = new BaseClientDetails("foo", "", "foo,bar", "authorization_code", "ROLE_USER"); + details.setAutoApproveScopes(StringUtils.commaDelimitedListToSet("none")); + assertFalse(details.isAutoApprove("read")); + } + @Test public void testJsonSerialize() throws Exception { BaseClientDetails details = new BaseClientDetails("foo", "", "foo,bar", "authorization_code", "ROLE_USER"); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestJdbcClientDetailsService.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestJdbcClientDetailsService.java index 642e45341..55ec52d86 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestJdbcClientDetailsService.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestJdbcClientDetailsService.java @@ -165,7 +165,7 @@ public void testLoadingClientIdWithMultipleDetails() { assertEquals("myAuthority2", authorities.next().getAuthority()); assertEquals(new Integer(100), clientDetails.getAccessTokenValiditySeconds()); assertEquals(new Integer(200), clientDetails.getRefreshTokenValiditySeconds()); - assertEquals(2, clientDetails.getAutoApproveScopes().size()); + assertTrue(clientDetails.isAutoApprove("read")); } @Test From 35cc087fec8e865068cba6e14aad74cc767a9db6 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 9 Sep 2013 09:20:22 -0700 Subject: [PATCH 087/831] Add autoapprove to sparklr2 and XSD --- .../oauth/SparklrUserApprovalHandler.java | 40 +- .../main/webapp/WEB-INF/spring-servlet.xml | 8 +- ...entDetailsServiceBeanDefinitionParser.java | 1 + .../oauth2/spring-security-oauth2-1.0.xsd | 7 + .../oauth2/spring-security-oauth2-1.1.xsd | 728 ++++++++++++++++++ 5 files changed, 767 insertions(+), 17 deletions(-) create mode 100644 spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.1.xsd diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrUserApprovalHandler.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrUserApprovalHandler.java index 77059775b..9199ebe39 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrUserApprovalHandler.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrUserApprovalHandler.java @@ -17,10 +17,12 @@ package org.springframework.security.oauth.examples.sparklr.oauth; import java.util.Collection; -import java.util.HashSet; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.ClientRegistrationException; import org.springframework.security.oauth2.provider.approval.ApprovalStoreUserApprovalHandler; /** @@ -29,22 +31,25 @@ */ public class SparklrUserApprovalHandler extends ApprovalStoreUserApprovalHandler { - private Collection autoApproveClients = new HashSet(); - private boolean useApprovalStore = true; + private ClientDetailsService clientDetailsService; + /** - * @param useApprovalStore the useTokenServices to set + * Service to load client details (optional) for auto approval checks. + * + * @param clientDetailsService a client details service */ - public void setUseApprovalStore(boolean useApprovalStore) { - this.useApprovalStore = useApprovalStore; + public void setClientDetailsService(ClientDetailsService clientDetailsService) { + this.clientDetailsService = clientDetailsService; + super.setClientDetailsService(clientDetailsService); } /** - * @param autoApproveClients the auto approve clients to set + * @param useApprovalStore the useTokenServices to set */ - public void setAutoApproveClients(Collection autoApproveClients) { - this.autoApproveClients = autoApproveClients; + public void setUseApprovalStore(boolean useApprovalStore) { + this.useApprovalStore = useApprovalStore; } /** @@ -66,8 +71,21 @@ public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizati approved = authorizationRequest.isApproved(); } else { - approved = (authorizationRequest.getResponseTypes().contains("token") && autoApproveClients - .contains(authorizationRequest.getClientId())); + if (clientDetailsService != null) { + Collection requestedScopes = authorizationRequest.getScope(); + try { + ClientDetails client = clientDetailsService + .loadClientByClientId(authorizationRequest.getClientId()); + approved = true; + for (String scope : requestedScopes) { + if (!client.isAutoApprove(scope)) { + approved = false; + } + } + } + catch (ClientRegistrationException e) { + } + } } authorizationRequest.setApproved(approved); diff --git a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml index d863055b1..08df32a8e 100644 --- a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml +++ b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml @@ -132,12 +132,8 @@ - - - my-less-trusted-autoapprove-client - - + @@ -166,7 +162,7 @@ + authorities="ROLE_CLIENT" scope="read,write,trust" autoapprove="true"/> + + + + The set of scopes (or simply "true" for all) to autoapprove. + + + diff --git a/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.1.xsd b/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.1.xsd new file mode 100644 index 000000000..08865c92e --- /dev/null +++ b/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.1.xsd @@ -0,0 +1,728 @@ + + + + + + + + + Creates an OAuth2RestTemplate with all the pieces needed to connect to a remote resource from + a web + application. Injects request and session-scoped beans into the template, so can only be + used in the context of a web + request. + + + + + + + + + + + + + + + The OAuth2ProtectedResourceDetails governing the configuration of this client. Mandatory. + + + + + + + The reference to the bean that manages access token acquisition. Optional (defaults to a chain + including common grant types from the spec). + + + + + + + + + + + + Specifies that the oauth 2 authorization and token + endpoints should be created in the application + context. These are + implemented as regular Spring @Controller beans, so as long as the + default Spring MVC set up in + present in the application + the endpoints should work (at /oauth/authorization and /oauth/token by + default). + + + + + + + + + The configuration of the authorization code + mechanism. This + mechanism enables a way for clients to + obtain an + access token by obtaining an authorization code. + + + + + + + Whether to disable the authorization code + mechanism. + + + + + + + The reference to the bean that defines the + authorization code + services. Default value is an + instance of + "org.springframework.security.oauth2.provider.authorization_code.InMemoryAuthorizationCodeServices". + + + + + + + + + The configuration of the client credentials + grant type. + + + + + + + Whether to disable the implicit grant type + + + + + + + + + The configuration of the refresh token grant + type. + + + + + + + Whether to disable the refresh token grant + type + + + + + + + + + The configuration of the client credentials + grant type. + + + + + + + Whether to disable the refresh token grant + type + + + + + + + + + The configuration of the resource owner password + grant type. + + + + + + + Whether to disable the refresh token grant + type + + + + + + + A reference to an authentication manager that + can be used to + authenticate the resource owner + + + + + + + + + The configuration of your custom grant type. + + + + + + + Whether to disable this grant + type + + + + + + + A reference to your token granter + + + + + + + + + + The reference to the bean that defines the client + details service. + + + + + + + The URL at which a request for an access token + will be serviced. + Default value: "/oauth/token" + + + + + + + The URL at which a user is redirected for + authorization. Default + value: "/oauth/authorize" + + + + + + + + + The reference to the bean that defines the + granter of different oauth + token types. + + + + + + + + The reference to the bean that defines the + implicit grant service. + + + + + + + + The reference to the bean that defines the token + services. Default + value is an instance of + "org.springframework.security.oauth2.provider.token.DefaultTokenServices". + + + + + + + + The reference to the bean that defines the manager for + authorization requests from the input + parameters (e.g. request parameters). + Default + value is an + instance of + "org.springframework.security.oauth2.provider.token.DefaultAuthorizationRequestManager". + + + + + + + + Reference to a bean that handles user approval decisions. Using this strategy servers can + selectively skip the approval process depending on decisions in the past or on the type of client. + + + + + + + + The URL of the page that handles the user + approval form (if needed, depending on the grant type). + The default is "forward:/oauth/confirm_access" which is not handled + by the authorization endpoint, so normally you + will have to supply a handler + for this path. + + + + + + + + The URL of the page that handles errors (default forward:/oauth/error). + + + + + + + + The name of the form parameter that is used to + indicate user + approval of the client + authentication + request. + Default value: "user_oauth_approval". + + + + + + + + The reference to the bean that defines the + redirect resolver, used + during the user + authorization. + Default + value is an instance of + "org.springframework.security.oauth2.provider.authorization_code.DefaultRedirectResolver". + + + + + + + + + + + Specifies that there are oauth 2 protected resources in + the application context. This element + has an + id which is the bean id of the filter created. The filter + should be added to the Spring Security filter chain at + position before="PRE_AUTH_FILTER" + + + + + + + + + + The resource id that is protected by this filter + if any. If empty or + absent then all resource ids + are allowed, + otherwise + only tokens which are granted to a client that contains + this reosurce + id will be legal. + + + + + + + + The reference to the bean that defines the token + services. Default + value is an instance of + "org.springframework.security.oauth2.provider.token.DefaultTokenServices". + + + + + + + + The reference to the bean that defines the entry point for failed authentications. Defaults to + a vanilla + org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint. + + + + + + + + The reference to the bean that defines the AuthenticationDetailsSource. + + + + + + + + + + + + Default element that contains the definition of the + OAuth clients that are + allowed to access this + service. + + + + + + + + + + + Definition of a client that can act on behalf + of a user. + + + + + + + + The client id. + + + + + + + The client secret. If the secret is + undefined or empty (the + default) the client does + not + require a + secret. + + + + + + + The re-direct URI(s) established during + registration (optional, comma separated). + + + + + + + The resource ids to which this client can be + granted access + (comma-separated). If missing or + empty all + resources are + accessible (not recommended by the spec). + + + + + + + The scopes to which the client is limited + (comma-separated). If + scope is undefined or empty + (the + default) the client + is not limited by scope, but in that case + the authorization + service must explicitly + accept unlimited + access by not + specifying any scopes itself. + + + + + + + Grant types that are authorized for the + client to use + (comma-separated). Currently defined + grant types + include + "authorization_code", "password", "assertion", and + "refresh_token". Default value is + "authorization_code,refresh_token". + + + + + + + Authorities that are granted to the client + (comma-separated). Distinct + from the authorities + granted to + the user on behalf + of whom the client is acting. + + + + + + + The access token validity period in seconds (optional). If unspecified a global default will + be applied by the token services. + + + + + + + The refresh token validity period in seconds (optional). If unspecified a global default + will + be applied by the token services. + + + + + + + + + + + + + + + Element for declaring and configuring an expression + handler for oauth + security expressions. See + http://static.springsource.org/spring-security/site/docs/3.0.x/reference/el-access.html + + + + + + + + + + + + + Element for declaring and configuring an expression + handler for oauth + security expressions in http + intercept urls. See + http://static.springsource.org/spring-security/site/docs/3.0.x/reference/el-access.html + + + + + + + + + + + + + Creates the oauth 2 client filter be be added to the + application security policy. + + + + + + + + + The reference to the bean that defines the + redirect strategy, used when redirecting the user for + access authorization. Default value is an instance of + "org.springframework.security.web.DefaultRedirectStrategy". + + + + + + + + + + + + Definition of a remote resource that is protected via + OAuth2 to which this client application wants + access. + + + + + + + + + The grant type. Currently defined grant types + include + "authorization_code", "password", and + "assertion". + Default value + is "authorization_code". + + + + + + + The client id. This is the id by which the + resource server will + identify this application. + + + + + + + The uri to where the access token may be + obtained. + + + + + + + Comma-separted list of string specifying the + scope of the access to the + resource. By default, + no + scope will be + specified. + + + + + + + The secret asssociated with the resource. By + default, no secret + will be supplied for access to + the resource. + + + + + + + The scheme that is used to pass the client + secret. Suggested + values: "header" and "form". + Default: + "header". + See section 2.1 of the OAuth 2 spec. + + + + + + + The uri to which the user will be redirected if + the user is ever + needed to grant an authorization + code. + + + + + + + The method for bearing the token when accessing + the resource. + Default value is "header". See + AuthenticationScheme enum for possible values. + + + + + + + The name of the bearer token. The default is + "access_token", which + is according to the spec, + but + some providers + (e.g. Facebook) don't conform to the spec. + + + + + + + Some resource servers may require a + pre-established URI to which + they will redirect users after + users + authorize an access token. + + + + + + + Boolean flag indicating that the current URI should be used as a redirect (if available) rather + than the + registered redirect URI. Default is true. + + + + + + + The username for authentication, required only when type is "password". + + + + + + + The password for authentication, required only when type is "password". + + + + + + + + + From 1abadf9c0a89a995bb9c7399d6493b1d1a97474a Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 18 Sep 2013 15:33:17 +0100 Subject: [PATCH 088/831] Fix tests after approval reorg --- .../TestApprovalStoreUserApprovalHandler.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TestApprovalStoreUserApprovalHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TestApprovalStoreUserApprovalHandler.java index 63e4c0d88..97cdb4e35 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TestApprovalStoreUserApprovalHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TestApprovalStoreUserApprovalHandler.java @@ -46,27 +46,30 @@ public void init() { public void testExplicitlyApprovedScopes() { AuthorizationRequest authorizationRequest = new AuthorizationRequest("client", Arrays.asList("read")); authorizationRequest.setApprovalParameters(Collections.singletonMap("scope.read", "approved")); - assertTrue(handler.isApproved(authorizationRequest, userAuthentication)); + AuthorizationRequest result = handler.updateAfterApproval(authorizationRequest, userAuthentication); + assertTrue(handler.isApproved(result, userAuthentication)); assertEquals(1, store.getApprovals("user", "client").size()); - assertEquals(1, authorizationRequest.getScope().size()); - assertTrue(authorizationRequest.isApproved()); + assertEquals(1, result.getScope().size()); + assertTrue(result.isApproved()); } @Test public void testImplicitlyDeniedScope() { AuthorizationRequest authorizationRequest = new AuthorizationRequest("client", Arrays.asList("read", "write")); authorizationRequest.setApprovalParameters(Collections.singletonMap("scope.read", "approved")); - assertTrue(handler.isApproved(authorizationRequest, userAuthentication)); + AuthorizationRequest result = handler.updateAfterApproval(authorizationRequest, userAuthentication); + assertTrue(handler.isApproved(result, userAuthentication)); Collection approvals = store.getApprovals("user", "client"); assertEquals(2, approvals.size()); approvals.contains(new Approval("user", "client", "read", new Date(), Approval.ApprovalStatus.APPROVED)); approvals.contains(new Approval("user", "client", "write", new Date(), Approval.ApprovalStatus.DENIED)); - assertEquals(1, authorizationRequest.getScope().size()); + assertEquals(1, result.getScope().size()); } @Test public void testExplicitlyPreapprovedScopes() { - store.addApprovals(Arrays.asList(new Approval("user", "client", "read", new Date(System.currentTimeMillis() + 10000), Approval.ApprovalStatus.APPROVED))); + store.addApprovals(Arrays.asList(new Approval("user", "client", "read", new Date( + System.currentTimeMillis() + 10000), Approval.ApprovalStatus.APPROVED))); AuthorizationRequest authorizationRequest = new AuthorizationRequest("client", Arrays.asList("read")); AuthorizationRequest result = handler.checkForPreApproval(authorizationRequest, userAuthentication); assertTrue(result.isApproved()); @@ -74,7 +77,8 @@ public void testExplicitlyPreapprovedScopes() { @Test public void testExpiredPreapprovedScopes() { - store.addApprovals(Arrays.asList(new Approval("user", "client", "read", new Date(System.currentTimeMillis() - 10000), Approval.ApprovalStatus.APPROVED))); + store.addApprovals(Arrays.asList(new Approval("user", "client", "read", new Date( + System.currentTimeMillis() - 10000), Approval.ApprovalStatus.APPROVED))); AuthorizationRequest authorizationRequest = new AuthorizationRequest("client", Arrays.asList("read")); AuthorizationRequest result = handler.checkForPreApproval(authorizationRequest, userAuthentication); assertFalse(result.isApproved()); From 71e21dc77bb0d7d3c73157eb724076cc100b4d58 Mon Sep 17 00:00:00 2001 From: Radek Ostrowski Date: Thu, 1 Aug 2013 16:29:11 +0200 Subject: [PATCH 089/831] Extended the expression methods to allow testing for existing scope by specifying a regex expression --- .../expression/OAuth2ExpressionUtils.java | 18 ++++++++- .../OAuth2SecurityExpressionMethods.java | 40 +++++++++++++++++++ ...OAuth2MethodSecurityExpressionHandler.java | 36 ++++++++++++++++- 3 files changed, 91 insertions(+), 3 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionUtils.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionUtils.java index 86e114ee5..600847150 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionUtils.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionUtils.java @@ -23,7 +23,8 @@ /** * @author Dave Syer - * + * @author Radek Ostrowski + * */ public abstract class OAuth2ExpressionUtils { @@ -86,7 +87,22 @@ public static boolean hasAnyScope(Authentication authentication, String[] scopes } return false; + } + + public static boolean hasAnyScopeMatching(Authentication authentication, String[] scopesRegex) { + + if (authentication instanceof OAuth2Authentication) { + OAuth2Request clientAuthentication = ((OAuth2Authentication) authentication).getOAuth2Request(); + for (String scope : clientAuthentication.getScope()) { + for (String regex : scopesRegex) { + if (scope.matches(regex)) { + return true; + } + } + } + } + return false; } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethods.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethods.java index 7479e9b08..0307c5066 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethods.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethods.java @@ -28,6 +28,7 @@ * * @author Dave Syer * @author Rob Winch + * @author Radek Ostrowski * */ public class OAuth2SecurityExpressionMethods { @@ -110,6 +111,45 @@ public boolean hasAnyScope(String... scopes) { return result; } + /** + * Check if the current OAuth2 authentication has one of the scopes matching a specified regex expression. + * + *
+	 * access = "#oauth2.hasScopeMatching('.*_admin:manage_scopes')))"
+	 * 
+ * + * @param scopeRegex + * the scope regex to match + * @return true if the OAuth2 authentication has the required scope + */ + public boolean hasScopeMatching(String scopeRegex) { + return hasAnyScopeMatching(scopeRegex); + } + + /** + * Check if the current OAuth2 authentication has one of the scopes matching a specified regex expression. + * + *
+	 * access = "#oauth2.hasAnyScopeMatching('admin:manage_scopes','.*_admin:manage_scopes','.*_admin:read_scopes')))"
+	 * 
+ * + * @param roles + * the scopes regex to match + * @return true if the OAuth2 token has one of these scopes + * @throws AccessDeniedException + * if the scope is invalid and we the flag is set to throw the exception + */ + public boolean hasAnyScopeMatching(String... scopesRegex) { + + boolean result = OAuth2ExpressionUtils.hasAnyScopeMatching(authentication, scopesRegex); + if (!result && throwExceptionOnInvalidScope) { + missingScopes.addAll(Arrays.asList(scopesRegex)); + Throwable failure = new InsufficientScopeException("Insufficient scope for this resource", missingScopes); + throw new AccessDeniedException(failure.getMessage(), failure); + } + return result; + } + /** * Deny access to oauth requests, so used for example to only allow web UI users to access a resource. * diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2MethodSecurityExpressionHandler.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2MethodSecurityExpressionHandler.java index e2b4cfac7..582d3364b 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2MethodSecurityExpressionHandler.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2MethodSecurityExpressionHandler.java @@ -25,18 +25,20 @@ import org.junit.Test; import org.springframework.expression.EvaluationContext; import org.springframework.expression.Expression; +import org.springframework.security.access.AccessDeniedException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; +import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.AuthorizationRequest; -import org.springframework.security.oauth2.provider.RequestTokenFactory; import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.RequestTokenFactory; import org.springframework.security.util.SimpleMethodInvocation; import org.springframework.util.ReflectionUtils; /** * @author Dave Syer + * @author Radek Ostrowski * */ public class TestOAuth2MethodSecurityExpressionHandler { @@ -77,6 +79,36 @@ public void testScopes() throws Exception { assertTrue((Boolean) expression.getValue(context)); } + @Test + public void testScopesRegex() throws Exception { + + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("ns_admin:read"), null, null, null); + + Authentication userAuthentication = null; + OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); + MethodInvocation invocation = new SimpleMethodInvocation(this, ReflectionUtils.findMethod(getClass(), + "testOauthClient")); + EvaluationContext context = handler.createEvaluationContext(oAuth2Authentication, invocation); + Expression expression = handler.getExpressionParser().parseExpression("#oauth2.hasScopeMatching('.*_admin:read')"); + assertTrue((Boolean) expression.getValue(context)); + expression = handler.getExpressionParser().parseExpression("#oauth2.hasAnyScopeMatching('.*_admin:write','.*_admin:read')"); + assertTrue((Boolean) expression.getValue(context)); + } + + @Test(expected = AccessDeniedException.class) + public void testScopesRegexThrowsException() throws Exception { + + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("ns_admin:read"), null, null, null); + + Authentication userAuthentication = null; + OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); + MethodInvocation invocation = new SimpleMethodInvocation(this, ReflectionUtils.findMethod(getClass(), + "testOauthClient")); + EvaluationContext context = handler.createEvaluationContext(oAuth2Authentication, invocation); + Expression expression = handler.getExpressionParser().parseExpression("#oauth2.hasScopeMatching('.*_admin:write')"); + assertFalse((Boolean) expression.getValue(context)); + } + @Test public void testNonOauthClient() throws Exception { Authentication clientAuthentication = new UsernamePasswordAuthenticationToken("foo", "bar"); From ed338de3ff3e843322201ec8a736daa32756649a Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 18 Sep 2013 15:29:20 +0100 Subject: [PATCH 090/831] Fix tests affected by patch --- .../expression/TestOAuth2MethodSecurityExpressionHandler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2MethodSecurityExpressionHandler.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2MethodSecurityExpressionHandler.java index 582d3364b..9f019b122 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2MethodSecurityExpressionHandler.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2MethodSecurityExpressionHandler.java @@ -82,7 +82,7 @@ public void testScopes() throws Exception { @Test public void testScopesRegex() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("ns_admin:read"), null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("ns_admin:read"), null, null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); @@ -98,7 +98,7 @@ public void testScopesRegex() throws Exception { @Test(expected = AccessDeniedException.class) public void testScopesRegexThrowsException() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("ns_admin:read"), null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("ns_admin:read"), null, null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); From 6a0a58dbfe9aadd1dfa0ed493dc175c3d4f62df7 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 18 Sep 2013 15:58:33 +0100 Subject: [PATCH 091/831] Tweak auto approval --- .../oauth/SparklrUserApprovalHandler.java | 6 ++-- .../tonr/TestAuthorizationCodeGrant.java | 1 + .../oauth2/provider/BaseClientDetails.java | 10 +++++- .../ApprovalStoreUserApprovalHandler.java | 2 +- .../TestApprovalStoreUserApprovalHandler.java | 36 +++++++++++++++++++ 5 files changed, 50 insertions(+), 5 deletions(-) diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrUserApprovalHandler.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrUserApprovalHandler.java index 9199ebe39..3ea9b1160 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrUserApprovalHandler.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrUserApprovalHandler.java @@ -76,10 +76,10 @@ public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizati try { ClientDetails client = clientDetailsService .loadClientByClientId(authorizationRequest.getClientId()); - approved = true; for (String scope : requestedScopes) { - if (!client.isAutoApprove(scope)) { - approved = false; + if (client.isAutoApprove(scope) || client.isAutoApprove("all")) { + approved = true; + break; } } } diff --git a/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestAuthorizationCodeGrant.java b/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestAuthorizationCodeGrant.java index b27838f72..0d2147340 100755 --- a/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestAuthorizationCodeGrant.java +++ b/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestAuthorizationCodeGrant.java @@ -108,6 +108,7 @@ private String authenticateAndApprove(String location) { // Should be on user approval page now form = new LinkedMultiValueMap(); form.add("user_oauth_approval", "true"); + form.add("scope.read", "true"); response = serverRunning.postForHeaders("/sparklr2/oauth/authorize", form, headers); return response.getLocation().toString(); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseClientDetails.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseClientDetails.java index 0772affbe..4dcfeda2b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseClientDetails.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseClientDetails.java @@ -148,7 +148,15 @@ public void setAutoApproveScopes(Set autoApproveScopes) { @Override public boolean isAutoApprove(String scope) { - return autoApproveScopes != null && (autoApproveScopes.contains("true") || autoApproveScopes.contains(scope)); + if (autoApproveScopes == null) { + return false; + } + for (String auto : autoApproveScopes) { + if (auto.equals("true") || scope.matches(auto)) { + return true; + } + } + return false; } @JsonIgnore diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java index fbce23b43..d8d033c2d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java @@ -110,7 +110,7 @@ public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizati try { ClientDetails client = clientDetailsService.loadClientByClientId(clientId); for (String scope : requestedScopes) { - if (client.isAutoApprove(scope)) { + if (client.isAutoApprove(scope) || client.isAutoApprove("all")) { approvedScopes.add(scope); } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TestApprovalStoreUserApprovalHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TestApprovalStoreUserApprovalHandler.java index 97cdb4e35..6ce220d86 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TestApprovalStoreUserApprovalHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TestApprovalStoreUserApprovalHandler.java @@ -9,6 +9,7 @@ import java.util.Collections; import java.util.Date; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import org.junit.Before; @@ -27,6 +28,8 @@ public class TestApprovalStoreUserApprovalHandler { private ApprovalStoreUserApprovalHandler handler = new ApprovalStoreUserApprovalHandler(); private InMemoryApprovalStore store = new InMemoryApprovalStore(); + + private InMemoryClientDetailsService clientDetailsService = new InMemoryClientDetailsService(); private Authentication userAuthentication; @@ -75,6 +78,39 @@ public void testExplicitlyPreapprovedScopes() { assertTrue(result.isApproved()); } + @Test + public void testAutoapprovedScopes() { + handler.setClientDetailsService(clientDetailsService); + BaseClientDetails client = new BaseClientDetails("client", null, "read", "authorization_code", null); + client.setAutoApproveScopes(new HashSet(Arrays.asList("read"))); + clientDetailsService.setClientDetailsStore(Collections.singletonMap("client", client)); + AuthorizationRequest authorizationRequest = new AuthorizationRequest("client", Arrays.asList("read")); + AuthorizationRequest result = handler.checkForPreApproval(authorizationRequest, userAuthentication); + assertTrue(result.isApproved()); + } + + @Test + public void testAutoapprovedWildcardScopes() { + handler.setClientDetailsService(clientDetailsService); + BaseClientDetails client = new BaseClientDetails("client", null, "read", "authorization_code", null); + client.setAutoApproveScopes(new HashSet(Arrays.asList(".*"))); + clientDetailsService.setClientDetailsStore(Collections.singletonMap("client", client)); + AuthorizationRequest authorizationRequest = new AuthorizationRequest("client", Arrays.asList("read")); + AuthorizationRequest result = handler.checkForPreApproval(authorizationRequest, userAuthentication); + assertTrue(result.isApproved()); + } + + @Test + public void testAutoapprovedAllScopes() { + handler.setClientDetailsService(clientDetailsService); + BaseClientDetails client = new BaseClientDetails("client", null, "read", "authorization_code", null); + client.setAutoApproveScopes(new HashSet(Arrays.asList("true"))); + clientDetailsService.setClientDetailsStore(Collections.singletonMap("client", client)); + AuthorizationRequest authorizationRequest = new AuthorizationRequest("client", Arrays.asList("read")); + AuthorizationRequest result = handler.checkForPreApproval(authorizationRequest, userAuthentication); + assertTrue(result.isApproved()); + } + @Test public void testExpiredPreapprovedScopes() { store.addApprovals(Arrays.asList(new Approval("user", "client", "read", new Date( From d38adc59dfb9185c460be7cb972b2b8a4f182148 Mon Sep 17 00:00:00 2001 From: Costi Ciudatu Date: Sat, 31 Aug 2013 18:01:54 +0300 Subject: [PATCH 092/831] Bugfix for handling non-standard comma-separated scopes --- .../security/oauth2/provider/BaseRequest.java | 2 +- .../provider/TestAuthorizationRequest.java | 29 ++++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java index cd2cf3c63..11b71312b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java @@ -75,7 +75,7 @@ protected void setScope(Collection scope) { * This is really an error, but it can catch out unsuspecting users and it's easy to fix. It happens when an * AuthorizationRequest gets bound accidentally from request parameters using @ModelAttribute. */ - if (value.contains(" ") || scope.contains(",")) { + if (value.contains(" ") || value.contains(",")) { scope = OAuth2Utils.parseParameterList(value); } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationRequest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationRequest.java index 36db196fb..d608e9cb3 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationRequest.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationRequest.java @@ -83,13 +83,40 @@ public void testScopeNotSetInParameters() throws Exception { assertFalse(authorizationRequest.getRequestParameters().get(OAuth2Utils.SCOPE).contains("foo")); } + /** + * Ensure that setting a single value scope which contains spaces + * will result in exploding multiple scopes. + */ + @Test + public void testSpaceSeparatedScopesAreExploded() throws Exception { + testSingleValueScopeIsExploded(' '); + } + + /** + * Ensure that setting a single value scope which contains commas + * will result in exploding multiple scopes. + */ + @Test + public void testCommaSeparatedScopesAreExploded() throws Exception { + testSingleValueScopeIsExploded(','); + } + + private void testSingleValueScopeIsExploded(char separator) throws Exception { + AuthorizationRequest authorizationRequest = createFromParameters(parameters); + String multiScope = String.format("foo%cbar", separator); + authorizationRequest.setScope(Collections.singleton(multiScope)); + assertEquals(authorizationRequest.getScope().size(), 2); + assertTrue(authorizationRequest.getScope().containsAll(Arrays.asList("foo", "bar"))); + assertFalse(authorizationRequest.getScope().contains(multiScope)); + } + @Test public void testClientIdNotOverwitten() throws Exception { AuthorizationRequest authorizationRequest = new AuthorizationRequest("client", Arrays.asList("read")); parameters = new HashMap(); parameters.put("scope", "write"); authorizationRequest.setRequestParameters(parameters); - + assertEquals("client", authorizationRequest.getClientId()); assertEquals(1, authorizationRequest.getScope().size()); assertTrue(authorizationRequest.getScope().contains("read")); From 4fd855600e1ec9462cbae589e7c77c8a41cc3d97 Mon Sep 17 00:00:00 2001 From: Amanda Anganes Date: Tue, 3 Sep 2013 17:04:48 -0400 Subject: [PATCH 093/831] Added extra parameter to RedirectView constructor calls to set exposeModel to false --- .../provider/endpoint/AuthorizationEndpoint.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java index 1a9f324e8..da3800429 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java @@ -227,7 +227,7 @@ public View approveOrDeny(@RequestParam Map approvalParameters, if (!authorizationRequest.isApproved()) { return new RedirectView(getUnsuccessfulRedirect(authorizationRequest, new UserDeniedAuthorizationException( - "User denied access"), responseTypes.contains("token")), false); + "User denied access"), responseTypes.contains("token")), false, true, false); } if (responseTypes.contains("token")) { @@ -261,20 +261,20 @@ private ModelAndView getImplicitGrantResponse(AuthorizationRequest authorization if (accessToken == null) { throw new UnsupportedResponseTypeException("Unsupported response type: token"); } - return new ModelAndView(new RedirectView(appendAccessToken(authorizationRequest, accessToken), false)); + return new ModelAndView(new RedirectView(appendAccessToken(authorizationRequest, accessToken), false, true, false)); } catch (OAuth2Exception e) { - return new ModelAndView(new RedirectView(getUnsuccessfulRedirect(authorizationRequest, e, true), false)); + return new ModelAndView(new RedirectView(getUnsuccessfulRedirect(authorizationRequest, e, true), false, true, false)); } } private View getAuthorizationCodeResponse(AuthorizationRequest authorizationRequest, Authentication authUser) { try { return new RedirectView(getSuccessfulRedirect(authorizationRequest, - generateCode(authorizationRequest, authUser)), false); + generateCode(authorizationRequest, authUser)), false, true, false); } catch (OAuth2Exception e) { - return new RedirectView(getUnsuccessfulRedirect(authorizationRequest, e, false), false); + return new RedirectView(getUnsuccessfulRedirect(authorizationRequest, e, false), false, true, false); } } @@ -496,7 +496,7 @@ private ModelAndView handleException(Exception e, ServletWebRequest webRequest) authorizationRequest.setRedirectUri(requestedRedirect); String redirect = getUnsuccessfulRedirect(authorizationRequest, translate.getBody(), authorizationRequest .getResponseTypes().contains("token")); - return new ModelAndView(new RedirectView(redirect, false)); + return new ModelAndView(new RedirectView(redirect, false, true, false)); } catch (OAuth2Exception ex) { // If an AuthorizationRequest cannot be created from the incoming parameters it must be From ae967cbd7074285b47577d14b58887a11984951b Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 7 Oct 2013 12:42:15 -0400 Subject: [PATCH 094/831] SECOAUTH-423: Add Serializable to support session scoped attributes --- .../security/oauth2/provider/AuthorizationRequest.java | 3 ++- .../security/oauth2/provider/BaseRequest.java | 4 +++- .../oauth2/provider/TestAuthorizationRequest.java | 9 +++++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java index 14633f24a..3e9661daa 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java @@ -21,7 +21,8 @@ * @author Dave Syer * @author Amanda Anganes */ -public class AuthorizationRequest extends BaseRequest { +@SuppressWarnings("serial") +public class AuthorizationRequest extends BaseRequest implements Serializable { /** * Map to hold the original, unchanged parameter set submitted by a user to signal approval of the token grant diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java index 11b71312b..dfbc4c275 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java @@ -16,6 +16,7 @@ package org.springframework.security.oauth2.provider; +import java.io.Serializable; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -30,7 +31,8 @@ * @author Dave Syer * */ -abstract class BaseRequest { +@SuppressWarnings("serial") +abstract class BaseRequest implements Serializable { /** * Resolved client ID. This may be present in the original request parameters, or in some cases may be inferred by a diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationRequest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationRequest.java index d608e9cb3..0127b7cff 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationRequest.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationRequest.java @@ -32,6 +32,7 @@ import org.junit.Before; import org.junit.Test; import org.springframework.security.oauth2.common.util.OAuth2Utils; +import org.springframework.util.SerializationUtils; import org.springframework.util.StringUtils; /** @@ -169,4 +170,12 @@ public void testRedirectUriDefaultsToMap() { assertEquals("[one, two]", authorizationRequest.getScope().toString()); } + @Test + public void testSerialization() { + AuthorizationRequest authorizationRequest = createFromParameters(parameters); + AuthorizationRequest other = (AuthorizationRequest) SerializationUtils.deserialize(SerializationUtils + .serialize(authorizationRequest)); + assertEquals(authorizationRequest, other); + } + } From fc91516b2baa6f9bd1eef38075b839f658ea1141 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 7 Oct 2013 14:54:17 -0400 Subject: [PATCH 095/831] SECOAUTH-427: ensure redirect_uri is optional (if registered) --- .gitignore | 1 + pom.xml | 8 +- .../sparklr/oauth/SparklrConsumerDetails.java | 1 + .../oauth/examples/tonr/SparklrException.java | 1 + .../main/webapp/WEB-INF/spring-servlet.xml | 232 ++++++++++++------ .../oauth2/provider/ServerRunning.java | 6 +- .../oauth/examples/tonr/SparklrException.java | 1 + .../examples/tonr/mvc/SparklrController.java | 1 + .../tonr/mvc/SparklrRedirectController.java | 72 ++++++ .../src/main/webapp/WEB-INF/jsp/sparklr.jsp | 2 +- .../main/webapp/WEB-INF/spring-servlet.xml | 90 +++++-- .../oauth/examples/tonr/ServerRunning.java | 2 +- .../security/oauth/common/OAuthException.java | 1 + .../signature/InvalidSignatureException.java | 1 + .../oauth/common/signature/RSAKeySecret.java | 1 + .../signature/SharedConsumerSecretImpl.java | 1 + .../UnsupportedSignatureMethodException.java | 1 + .../AccessTokenRequiredException.java | 1 + .../consumer/InvalidOAuthRealmException.java | 1 + .../consumer/OAuthRequestFailedException.java | 1 + .../UnverifiedRequestTokenException.java | 1 + .../oauth/provider/BaseConsumerDetails.java | 9 +- .../provider/ConsumerAuthentication.java | 1 + .../oauth/provider/ConsumerCredentials.java | 1 + .../InvalidOAuthParametersException.java | 1 + .../provider/OAuthAuthenticationDetails.java | 1 + .../OAuthVersionUnsupportedException.java | 1 + .../attributes/ConsumerSecurityConfig.java | 1 + .../nonce/NonceAlreadyUsedException.java | 1 + .../token/ExpiredOAuthTokenException.java | 1 + .../token/InvalidOAuthTokenException.java | 1 + .../verifier/VerificationFailedException.java | 1 + .../oauth2/client/OAuth2RestTemplate.java | 2 +- .../http/AccessTokenRequiredException.java | 1 + .../resource/OAuth2AccessDeniedException.java | 1 + .../UserApprovalRequiredException.java | 1 + .../UserRedirectRequiredException.java | 1 + .../AuthorizationCodeAccessTokenProvider.java | 7 +- ...OAuth2AccessTokenJackson2Deserializer.java | 1 + .../BadClientCredentialsException.java | 1 + .../ClientAuthenticationException.java | 1 + .../InsufficientScopeException.java | 1 + .../exceptions/InvalidClientException.java | 1 + .../exceptions/InvalidGrantException.java | 1 + .../exceptions/InvalidRequestException.java | 1 + .../exceptions/InvalidScopeException.java | 1 + .../exceptions/InvalidTokenException.java | 1 + .../common/exceptions/OAuth2Exception.java | 1 + .../OAuth2ExceptionJackson2Deserializer.java | 1 + .../exceptions/RedirectMismatchException.java | 1 + .../exceptions/SerializationException.java | 1 + ...approvedClientAuthenticationException.java | 1 + .../UnauthorizedClientException.java | 1 + .../UnsupportedGrantTypeException.java | 1 + .../UnsupportedResponseTypeException.java | 1 + .../UserDeniedAuthorizationException.java | 1 + .../jaxb/AbstractJaxbMessageConverter.java | 1 - .../converter/jaxb/JaxbOAuth2AccessToken.java | 1 - .../converter/jaxb/JaxbOAuth2Exception.java | 1 - .../oauth2/provider/BaseClientDetails.java | 1 + .../ClientAlreadyExistsException.java | 1 + .../provider/ClientRegistrationException.java | 1 + .../provider/NoSuchClientException.java | 1 + .../oauth2/provider/TokenRequest.java | 1 + .../provider/endpoint/TokenEndpoint.java | 2 +- ...DefaultWebResponseExceptionTranslator.java | 3 + .../main/resources/META-INF/spring.schemas | 3 +- .../oauth2/spring-security-oauth2-1.0.xsd | 7 - .../oauth2/spring-security-oauth2-1.1.xsd | 7 + ...tAuthorizationCodeAccessTokenProvider.java | 3 +- ...estResourceServerBeanDefinitionParser.java | 6 +- .../jaxb/BaseJaxbMessageConverterTest.java | 1 - ...JaxbOAuth2AccessTokenMessageConverter.java | 1 - ...stJaxbOAuth2ExceptionMessageConverter.java | 1 - .../TestJdbcClientDetailsService.java | 126 ++++++---- .../approval/TestJdbcApprovalStore.java | 19 +- .../TestDefaultTokenServicesWithJdbc.java | 4 +- .../provider/token/TestJwtTokenServices.java | 1 + 78 files changed, 474 insertions(+), 194 deletions(-) create mode 100644 samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/mvc/SparklrRedirectController.java diff --git a/.gitignore b/.gitignore index 9bee68634..9bd45f719 100644 --- a/.gitignore +++ b/.gitignore @@ -14,5 +14,6 @@ target/ *.iws *.ipr .idea/ +code/ cargo-installs/ atlassian-ide-plugin.xml diff --git a/pom.xml b/pom.xml index 4d4b04d8f..0380bf17b 100644 --- a/pom.xml +++ b/pom.xml @@ -16,10 +16,10 @@ UTF-8 - 3.1.2.RELEASE - 3.1.3.RELEASE - [3.1.0,4.0.0) - [3.1.0,4.0.0) + 3.2.3.RELEASE + 3.1.4.RELEASE + [3.2.0,4.0.0) + [3.2.0,4.0.0) 1.6 diff --git a/samples/oauth/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrConsumerDetails.java b/samples/oauth/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrConsumerDetails.java index de896aa9b..6cc144fb1 100644 --- a/samples/oauth/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrConsumerDetails.java +++ b/samples/oauth/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrConsumerDetails.java @@ -5,6 +5,7 @@ /** * @author Ryan Heaton */ +@SuppressWarnings("serial") public class SparklrConsumerDetails extends BaseConsumerDetails { private String displayName; diff --git a/samples/oauth/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/SparklrException.java b/samples/oauth/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/SparklrException.java index def2bd830..c70ba399c 100644 --- a/samples/oauth/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/SparklrException.java +++ b/samples/oauth/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/SparklrException.java @@ -3,6 +3,7 @@ /** * @author Ryan Heaton */ +@SuppressWarnings("serial") public class SparklrException extends Exception { public SparklrException(String message) { diff --git a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml index 08df32a8e..83c180e06 100644 --- a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml +++ b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml @@ -1,29 +1,40 @@ - + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"> + + - - + + - - - + + - - + - + access="#oauth2.clientHasRole('ROLE_CLIENT') and #oauth2.isClient() and #oauth2.hasScope('read')" + method="GET" /> + - - + + @@ -53,43 +68,52 @@ - - + + - + - + - + - + - + - + - + @@ -99,11 +123,13 @@ - + - + @@ -112,36 +138,44 @@ - + - + - + - + - + - + - - - + + + - @@ -150,33 +184,49 @@ - + - - + - - - - - - + + + + + + - - + + @@ -185,83 +235,103 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ServerRunning.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ServerRunning.java index 6e7a86b93..6b26efd8f 100644 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ServerRunning.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ServerRunning.java @@ -245,7 +245,7 @@ private ResponseEntity postForStatus(RestOperations client, String path, H actualHeaders.putAll(headers); actualHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED); return client.exchange(getUrl(path), HttpMethod.POST, new HttpEntity>(formData, - actualHeaders), null); + actualHeaders), (Class)null); } public ResponseEntity postForRedirect(String path, HttpHeaders headers, MultiValueMap params) { @@ -262,7 +262,7 @@ public ResponseEntity postForRedirect(String path, HttpHeaders headers, Mu String location = exchange.getHeaders().getLocation().toString(); - return client.exchange(location, HttpMethod.GET, new HttpEntity(null, headers), null); + return client.exchange(location, HttpMethod.GET, new HttpEntity(null, headers), (Class)null); } public ResponseEntity getForString(String path) { @@ -280,7 +280,7 @@ public ResponseEntity getForString(String path, final HttpHeaders header public ResponseEntity getForResponse(String path, final HttpHeaders headers, Map uriVariables) { HttpEntity request = new HttpEntity(null, headers); - return client.exchange(getUrl(path), HttpMethod.GET, request, null, uriVariables); + return client.exchange(getUrl(path), HttpMethod.GET, request, (Class)null, uriVariables); } public ResponseEntity getForResponse(String path, HttpHeaders headers) { diff --git a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/SparklrException.java b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/SparklrException.java index def2bd830..c70ba399c 100644 --- a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/SparklrException.java +++ b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/SparklrException.java @@ -3,6 +3,7 @@ /** * @author Ryan Heaton */ +@SuppressWarnings("serial") public class SparklrException extends Exception { public SparklrException(String message) { diff --git a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/mvc/SparklrController.java b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/mvc/SparklrController.java index eac4a2147..48336863f 100644 --- a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/mvc/SparklrController.java +++ b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/mvc/SparklrController.java @@ -33,6 +33,7 @@ public class SparklrController { @RequestMapping("/sparklr/photos") public String photos(Model model) throws Exception { model.addAttribute("photoIds", sparklrService.getSparklrPhotoIds()); + model.addAttribute("path", "photos"); return "sparklr"; } diff --git a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/mvc/SparklrRedirectController.java b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/mvc/SparklrRedirectController.java new file mode 100644 index 000000000..d28249b58 --- /dev/null +++ b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/mvc/SparklrRedirectController.java @@ -0,0 +1,72 @@ +package org.springframework.security.oauth.examples.tonr.mvc; + +import java.awt.image.BufferedImage; +import java.io.InputStream; +import java.util.Iterator; + +import javax.imageio.ImageIO; +import javax.imageio.ImageReadParam; +import javax.imageio.ImageReader; +import javax.imageio.stream.MemoryCacheImageInputStream; +import javax.servlet.UnavailableException; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.security.oauth.examples.tonr.SparklrService; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; + +/** + * @author Ryan Heaton + * @author Dave Syer + */ +@Controller +public class SparklrRedirectController { + + private SparklrService sparklrService; + + @RequestMapping("/sparklr/redirect") + public String photos(Model model) throws Exception { + model.addAttribute("photoIds", sparklrService.getSparklrPhotoIds()); + model.addAttribute("path", "redirect"); + return "sparklr"; + } + + @RequestMapping("/sparklr/trigger") + public String trigger(Model model) throws Exception { + return photos(model); + } + + @RequestMapping("/sparklr/redirect/{id}") + public ResponseEntity photo(@PathVariable String id) throws Exception { + InputStream photo = sparklrService.loadSparklrPhoto(id); + if (photo == null) { + throw new UnavailableException("The requested photo does not exist"); + } + BufferedImage body; + MediaType contentType = MediaType.IMAGE_JPEG; + Iterator imageReaders = ImageIO.getImageReadersByMIMEType(contentType.toString()); + if (imageReaders.hasNext()) { + ImageReader imageReader = imageReaders.next(); + ImageReadParam irp = imageReader.getDefaultReadParam(); + imageReader.setInput(new MemoryCacheImageInputStream(photo), true); + body = imageReader.read(0, irp); + } else { + throw new HttpMessageNotReadableException("Could not find javax.imageio.ImageReader for Content-Type [" + + contentType + "]"); + } + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.IMAGE_JPEG); + return new ResponseEntity(body, headers, HttpStatus.OK); + } + + public void setSparklrService(SparklrService sparklrService) { + this.sparklrService = sparklrService; + } + +} diff --git a/samples/oauth2/tonr/src/main/webapp/WEB-INF/jsp/sparklr.jsp b/samples/oauth2/tonr/src/main/webapp/WEB-INF/jsp/sparklr.jsp index 6cf77d0f2..3537257ae 100644 --- a/samples/oauth2/tonr/src/main/webapp/WEB-INF/jsp/sparklr.jsp +++ b/samples/oauth2/tonr/src/main/webapp/WEB-INF/jsp/sparklr.jsp @@ -23,7 +23,7 @@
    -
  • "/>
  • +
  • "/>
diff --git a/samples/oauth2/tonr/src/main/webapp/WEB-INF/spring-servlet.xml b/samples/oauth2/tonr/src/main/webapp/WEB-INF/spring-servlet.xml index d58842d12..9e184ba28 100644 --- a/samples/oauth2/tonr/src/main/webapp/WEB-INF/spring-servlet.xml +++ b/samples/oauth2/tonr/src/main/webapp/WEB-INF/spring-servlet.xml @@ -1,7 +1,8 @@ - - + - + - + @@ -35,25 +39,37 @@ - + - - + + - - + + + + - + - + @@ -62,37 +78,49 @@ - + - + - + - + - + - + + + + + - + @@ -113,7 +141,8 @@ - + @@ -125,4 +154,13 @@ + + + + + + + + diff --git a/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/ServerRunning.java b/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/ServerRunning.java index a33bcd64e..da70f9039 100755 --- a/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/ServerRunning.java +++ b/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/ServerRunning.java @@ -205,7 +205,7 @@ public ResponseEntity postForStatus(String path, HttpHeaders headers, Mult actualHeaders.putAll(headers); actualHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED); return client.exchange(getUrl(path), HttpMethod.POST, new HttpEntity>(formData, - actualHeaders), null); + actualHeaders), (Class)null); } public HttpHeaders postForHeaders(String path, MultiValueMap formData) { diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/OAuthException.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/OAuthException.java index 7658b1f29..7fc06de64 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/OAuthException.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/OAuthException.java @@ -23,6 +23,7 @@ * * @author Ryan Heaton */ +@SuppressWarnings("serial") public class OAuthException extends AuthenticationException { public OAuthException(String message) { diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/InvalidSignatureException.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/InvalidSignatureException.java index fba700661..de5196961 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/InvalidSignatureException.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/InvalidSignatureException.java @@ -23,6 +23,7 @@ * * @author Ryan Heaton */ +@SuppressWarnings("serial") public class InvalidSignatureException extends OAuthException { public InvalidSignatureException(String msg) { diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/RSAKeySecret.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/RSAKeySecret.java index cad84ec10..0f0da404f 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/RSAKeySecret.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/RSAKeySecret.java @@ -34,6 +34,7 @@ * * @author Ryan Heaton */ +@SuppressWarnings("serial") public class RSAKeySecret implements SignatureSecret { private final PrivateKey privateKey; diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/SharedConsumerSecretImpl.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/SharedConsumerSecretImpl.java index cd84d7d30..dbde015ee 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/SharedConsumerSecretImpl.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/SharedConsumerSecretImpl.java @@ -21,6 +21,7 @@ * * @author Ryan Heaton */ +@SuppressWarnings("serial") public class SharedConsumerSecretImpl implements SharedConsumerSecret { private final String consumerSecret; diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/UnsupportedSignatureMethodException.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/UnsupportedSignatureMethodException.java index e1d233ba2..422955590 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/UnsupportedSignatureMethodException.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/UnsupportedSignatureMethodException.java @@ -19,6 +19,7 @@ /** * @author Ryan Heaton */ +@SuppressWarnings("serial") public class UnsupportedSignatureMethodException extends RuntimeException { public UnsupportedSignatureMethodException(String msg) { diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/AccessTokenRequiredException.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/AccessTokenRequiredException.java index 8ef810f14..c93385391 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/AccessTokenRequiredException.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/AccessTokenRequiredException.java @@ -5,6 +5,7 @@ /** * @author Ryan Heaton */ +@SuppressWarnings("serial") public class AccessTokenRequiredException extends InsufficientAuthenticationException { private final ProtectedResourceDetails resource; diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/InvalidOAuthRealmException.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/InvalidOAuthRealmException.java index d80e4c700..ffc5536c7 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/InvalidOAuthRealmException.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/InvalidOAuthRealmException.java @@ -21,6 +21,7 @@ * * @author Ryan Heaton */ +@SuppressWarnings("serial") public class InvalidOAuthRealmException extends OAuthRequestFailedException { private final String requiredRealm; diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/OAuthRequestFailedException.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/OAuthRequestFailedException.java index 7314a556c..ed92ba098 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/OAuthRequestFailedException.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/OAuthRequestFailedException.java @@ -23,6 +23,7 @@ * * @author Ryan Heaton */ +@SuppressWarnings("serial") public class OAuthRequestFailedException extends AccessDeniedException { public OAuthRequestFailedException(String msg) { diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/UnverifiedRequestTokenException.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/UnverifiedRequestTokenException.java index 383dced02..cf0a54262 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/UnverifiedRequestTokenException.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/UnverifiedRequestTokenException.java @@ -21,6 +21,7 @@ * * @author Ryan Heaton */ +@SuppressWarnings("serial") public class UnverifiedRequestTokenException extends OAuthRequestFailedException { public UnverifiedRequestTokenException(String msg) { diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/BaseConsumerDetails.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/BaseConsumerDetails.java index 86abc37b4..250172ff9 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/BaseConsumerDetails.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/BaseConsumerDetails.java @@ -16,11 +16,11 @@ package org.springframework.security.oauth.provider; -import org.springframework.security.oauth.common.signature.SignatureSecret; -import org.springframework.security.core.GrantedAuthority; - -import java.util.List; import java.util.ArrayList; +import java.util.List; + +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.oauth.common.signature.SignatureSecret; /** * Base implementation for consumer details. @@ -28,6 +28,7 @@ * @author Ryan Heaton * @author Andrew McCall */ +@SuppressWarnings("serial") public class BaseConsumerDetails implements ResourceSpecificConsumerDetails, ExtraTrustConsumerDetails { private String consumerKey; diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ConsumerAuthentication.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ConsumerAuthentication.java index 263b8b3b3..6d5e37fce 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ConsumerAuthentication.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ConsumerAuthentication.java @@ -25,6 +25,7 @@ * * @author Ryan Heaton */ +@SuppressWarnings("serial") public class ConsumerAuthentication extends AbstractAuthenticationToken { private final ConsumerDetails consumerDetails; diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ConsumerCredentials.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ConsumerCredentials.java index 236afd962..5afe5324d 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ConsumerCredentials.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ConsumerCredentials.java @@ -23,6 +23,7 @@ * * @author Ryan Heaton */ +@SuppressWarnings("serial") public class ConsumerCredentials implements Serializable { private final String consumerKey; diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/InvalidOAuthParametersException.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/InvalidOAuthParametersException.java index e2e9f950f..8c8a93f05 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/InvalidOAuthParametersException.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/InvalidOAuthParametersException.java @@ -21,6 +21,7 @@ /** * @author Ryan Heaton */ +@SuppressWarnings("serial") public class InvalidOAuthParametersException extends OAuthException { public InvalidOAuthParametersException(String msg) { diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/OAuthAuthenticationDetails.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/OAuthAuthenticationDetails.java index d527146a0..66843bcaa 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/OAuthAuthenticationDetails.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/OAuthAuthenticationDetails.java @@ -25,6 +25,7 @@ * * @author Ryan Heaton */ +@SuppressWarnings("serial") public class OAuthAuthenticationDetails extends WebAuthenticationDetails { private final ConsumerDetails consumerDetails; diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/OAuthVersionUnsupportedException.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/OAuthVersionUnsupportedException.java index 7fbabb0e2..d715ac562 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/OAuthVersionUnsupportedException.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/OAuthVersionUnsupportedException.java @@ -19,6 +19,7 @@ /** * @author Ryan Heaton */ +@SuppressWarnings("serial") public class OAuthVersionUnsupportedException extends InvalidOAuthParametersException { public OAuthVersionUnsupportedException(String msg) { diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/attributes/ConsumerSecurityConfig.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/attributes/ConsumerSecurityConfig.java index 3caa13a6a..0fcd5869a 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/attributes/ConsumerSecurityConfig.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/attributes/ConsumerSecurityConfig.java @@ -23,6 +23,7 @@ * * @author Ryan Heaton */ +@SuppressWarnings("serial") public class ConsumerSecurityConfig extends SecurityConfig { public static final ConsumerSecurityConfig DENY_ALL_ATTRIBUTE = new ConsumerSecurityConfig(DenyAllConsumers.class.getName(), null); diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/nonce/NonceAlreadyUsedException.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/nonce/NonceAlreadyUsedException.java index dd9008027..a3d180bf3 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/nonce/NonceAlreadyUsedException.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/nonce/NonceAlreadyUsedException.java @@ -21,6 +21,7 @@ /** * @author Ryan Heaton */ +@SuppressWarnings("serial") public class NonceAlreadyUsedException extends OAuthException { public NonceAlreadyUsedException(String msg) { super(msg); diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/ExpiredOAuthTokenException.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/ExpiredOAuthTokenException.java index 4e290813b..37222ba5c 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/ExpiredOAuthTokenException.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/ExpiredOAuthTokenException.java @@ -21,6 +21,7 @@ /** * @author Ryan Heaton */ +@SuppressWarnings("serial") public class ExpiredOAuthTokenException extends OAuthException { public ExpiredOAuthTokenException(String msg) { diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/InvalidOAuthTokenException.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/InvalidOAuthTokenException.java index 7de28f1ab..113ea14f3 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/InvalidOAuthTokenException.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/InvalidOAuthTokenException.java @@ -21,6 +21,7 @@ /** * @author Ryan Heaton */ +@SuppressWarnings("serial") public class InvalidOAuthTokenException extends OAuthException { public InvalidOAuthTokenException(String msg) { diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/verifier/VerificationFailedException.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/verifier/VerificationFailedException.java index aa240beb3..90d78788e 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/verifier/VerificationFailedException.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/verifier/VerificationFailedException.java @@ -21,6 +21,7 @@ /** * @author Ryan Heaton */ +@SuppressWarnings("serial") public class VerificationFailedException extends OAuthException { public VerificationFailedException(String msg) { super(msg); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/OAuth2RestTemplate.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/OAuth2RestTemplate.java index dbeb25532..0073251eb 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/OAuth2RestTemplate.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/OAuth2RestTemplate.java @@ -174,7 +174,7 @@ public OAuth2AccessToken getAccessToken() throws UserRedirectRequiredException { if (stateKey != null) { Object stateToPreserve = e.getStateToPreserve(); if (stateToPreserve == null) { - stateToPreserve = "state"; + stateToPreserve = "NONE"; } context.setPreservedState(stateKey, stateToPreserve); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/http/AccessTokenRequiredException.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/http/AccessTokenRequiredException.java index e60df7b02..fc4d42f72 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/http/AccessTokenRequiredException.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/http/AccessTokenRequiredException.java @@ -6,6 +6,7 @@ /** * @author Ryan Heaton */ +@SuppressWarnings("serial") public class AccessTokenRequiredException extends InsufficientAuthenticationException { private final OAuth2ProtectedResourceDetails resource; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/resource/OAuth2AccessDeniedException.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/resource/OAuth2AccessDeniedException.java index 203790433..46a489895 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/resource/OAuth2AccessDeniedException.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/resource/OAuth2AccessDeniedException.java @@ -9,6 +9,7 @@ * @author Ryan Heaton * @author Dave Syer */ +@SuppressWarnings("serial") public class OAuth2AccessDeniedException extends OAuth2Exception { private OAuth2ProtectedResourceDetails resource; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/resource/UserApprovalRequiredException.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/resource/UserApprovalRequiredException.java index e18cf49fa..144f9f399 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/resource/UserApprovalRequiredException.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/resource/UserApprovalRequiredException.java @@ -24,6 +24,7 @@ * @author Dave Syer * */ +@SuppressWarnings("serial") public class UserApprovalRequiredException extends RuntimeException { private final String approvalUri; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/resource/UserRedirectRequiredException.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/resource/UserRedirectRequiredException.java index be51be57e..3146d9199 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/resource/UserRedirectRequiredException.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/resource/UserRedirectRequiredException.java @@ -7,6 +7,7 @@ * * @author Ryan Heaton */ +@SuppressWarnings("serial") public class UserRedirectRequiredException extends RuntimeException { private final String redirectUri; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProvider.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProvider.java index 1dc5748d2..c2deddf7d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProvider.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProvider.java @@ -229,7 +229,7 @@ private MultiValueMap getParametersForTokenRequest(Authorization redirectUri = resource.getRedirectUri(request); } - if (redirectUri != null) { + if (redirectUri != null && !"NONE".equals(redirectUri)) { form.set("redirect_uri", redirectUri); } @@ -292,10 +292,9 @@ private UserRedirectRequiredException getRedirectForAuthorization(AuthorizationC // Client secret is not required in the initial authorization request String redirectUri = resource.getRedirectUri(request); - if (redirectUri == null) { - throw new IllegalStateException("No redirect URI has been established for the current request."); + if (redirectUri != null) { + requestParameters.put("redirect_uri", redirectUri); } - requestParameters.put("redirect_uri", redirectUri); if (resource.isScoped()) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2Deserializer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2Deserializer.java index 1a9ef66d5..1c5552678 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2Deserializer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2Deserializer.java @@ -41,6 +41,7 @@ * @author Brian Clozel * @see org.springframework.security.oauth2.common.OAuth2AccessTokenJackson2Serializer */ +@SuppressWarnings("serial") public final class OAuth2AccessTokenJackson2Deserializer extends StdDeserializer { public OAuth2AccessTokenJackson2Deserializer() { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/BadClientCredentialsException.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/BadClientCredentialsException.java index 4f523f046..e928185f5 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/BadClientCredentialsException.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/BadClientCredentialsException.java @@ -6,6 +6,7 @@ * @author Ryan Heaton * @author Dave Syer */ +@SuppressWarnings("serial") public class BadClientCredentialsException extends ClientAuthenticationException { public BadClientCredentialsException() { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/ClientAuthenticationException.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/ClientAuthenticationException.java index 213e7115a..5c0eb31d6 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/ClientAuthenticationException.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/ClientAuthenticationException.java @@ -6,6 +6,7 @@ * @author Ryan Heaton * @author Dave Syer */ +@SuppressWarnings("serial") public abstract class ClientAuthenticationException extends OAuth2Exception { public ClientAuthenticationException(String msg, Throwable t) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/InsufficientScopeException.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/InsufficientScopeException.java index 1ffebee44..c512f60aa 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/InsufficientScopeException.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/InsufficientScopeException.java @@ -11,6 +11,7 @@ * * @author Dave Syer */ +@SuppressWarnings("serial") public class InsufficientScopeException extends OAuth2Exception { public InsufficientScopeException(String msg, Set validScope) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/InvalidClientException.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/InvalidClientException.java index f279ecbcc..fd10e7b26 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/InvalidClientException.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/InvalidClientException.java @@ -6,6 +6,7 @@ * @author Ryan Heaton * @author Dave Syer */ +@SuppressWarnings("serial") public class InvalidClientException extends ClientAuthenticationException { public InvalidClientException(String msg) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/InvalidGrantException.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/InvalidGrantException.java index df17701dc..b492d9452 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/InvalidGrantException.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/InvalidGrantException.java @@ -4,6 +4,7 @@ * @author Ryan Heaton * @author Dave Syer */ +@SuppressWarnings("serial") public class InvalidGrantException extends ClientAuthenticationException { public InvalidGrantException(String msg, Throwable t) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/InvalidRequestException.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/InvalidRequestException.java index f02cce337..32b14681e 100755 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/InvalidRequestException.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/InvalidRequestException.java @@ -3,6 +3,7 @@ /** * @author Dave Syer */ +@SuppressWarnings("serial") public class InvalidRequestException extends ClientAuthenticationException { public InvalidRequestException(String msg, Throwable t) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/InvalidScopeException.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/InvalidScopeException.java index 54daa9d7e..f5989edd1 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/InvalidScopeException.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/InvalidScopeException.java @@ -12,6 +12,7 @@ * @author Ryan Heaton * @author Dave Syer */ +@SuppressWarnings("serial") public class InvalidScopeException extends OAuth2Exception { public InvalidScopeException(String msg, Set validScope) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/InvalidTokenException.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/InvalidTokenException.java index cab3fd00b..527fdced8 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/InvalidTokenException.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/InvalidTokenException.java @@ -19,6 +19,7 @@ * @author Ryan Heaton * @author Dave Syer */ +@SuppressWarnings("serial") public class InvalidTokenException extends ClientAuthenticationException { public InvalidTokenException(String msg, Throwable t) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2Exception.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2Exception.java index 047056bdc..00963d39a 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2Exception.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2Exception.java @@ -11,6 +11,7 @@ * @author Rob Winch * @author Dave Syer */ +@SuppressWarnings("serial") @org.codehaus.jackson.map.annotate.JsonSerialize(using = OAuth2ExceptionJackson1Serializer.class) @org.codehaus.jackson.map.annotate.JsonDeserialize(using = OAuth2ExceptionJackson1Deserializer.class) @com.fasterxml.jackson.databind.annotation.JsonSerialize(using = OAuth2ExceptionJackson2Serializer.class) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson2Deserializer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson2Deserializer.java index 8e42b1d93..92c23d4c4 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson2Deserializer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson2Deserializer.java @@ -29,6 +29,7 @@ * @author Brian Clozel * */ +@SuppressWarnings("serial") public class OAuth2ExceptionJackson2Deserializer extends StdDeserializer { public OAuth2ExceptionJackson2Deserializer() { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/RedirectMismatchException.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/RedirectMismatchException.java index eff5bb97b..eac238ed3 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/RedirectMismatchException.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/RedirectMismatchException.java @@ -3,6 +3,7 @@ /** * @author Ryan Heaton */ +@SuppressWarnings("serial") public class RedirectMismatchException extends ClientAuthenticationException { public RedirectMismatchException(String msg, Throwable t) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/SerializationException.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/SerializationException.java index 177f0e252..2b46c26eb 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/SerializationException.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/SerializationException.java @@ -5,6 +5,7 @@ * * @author Ryan Heaton */ +@SuppressWarnings("serial") public class SerializationException extends RuntimeException { public SerializationException() { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/UnapprovedClientAuthenticationException.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/UnapprovedClientAuthenticationException.java index b04f556e4..f288bc679 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/UnapprovedClientAuthenticationException.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/UnapprovedClientAuthenticationException.java @@ -5,6 +5,7 @@ /** * @author Ryan Heaton */ +@SuppressWarnings("serial") public class UnapprovedClientAuthenticationException extends InsufficientAuthenticationException { public UnapprovedClientAuthenticationException(String msg) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/UnauthorizedClientException.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/UnauthorizedClientException.java index cf8b0d13f..cb25b01d5 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/UnauthorizedClientException.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/UnauthorizedClientException.java @@ -5,6 +5,7 @@ * * @author Ryan Heaton */ +@SuppressWarnings("serial") public class UnauthorizedClientException extends ClientAuthenticationException { public UnauthorizedClientException(String msg, Throwable t) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/UnsupportedGrantTypeException.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/UnsupportedGrantTypeException.java index a2573989d..113c7fefb 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/UnsupportedGrantTypeException.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/UnsupportedGrantTypeException.java @@ -3,6 +3,7 @@ /** * @author Ryan Heaton */ +@SuppressWarnings("serial") public class UnsupportedGrantTypeException extends OAuth2Exception { public UnsupportedGrantTypeException(String msg, Throwable t) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/UnsupportedResponseTypeException.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/UnsupportedResponseTypeException.java index d09e444fa..8129964ac 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/UnsupportedResponseTypeException.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/UnsupportedResponseTypeException.java @@ -3,6 +3,7 @@ /** * @author Ryan Heaton */ +@SuppressWarnings("serial") public class UnsupportedResponseTypeException extends OAuth2Exception { public UnsupportedResponseTypeException(String msg, Throwable t) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/UserDeniedAuthorizationException.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/UserDeniedAuthorizationException.java index 2718f99ef..0ec3cc75c 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/UserDeniedAuthorizationException.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/UserDeniedAuthorizationException.java @@ -3,6 +3,7 @@ /** * @author Ryan Heaton */ +@SuppressWarnings("serial") public class UserDeniedAuthorizationException extends OAuth2Exception { public UserDeniedAuthorizationException(String msg, Throwable t) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/jaxb/AbstractJaxbMessageConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/jaxb/AbstractJaxbMessageConverter.java index 95887f438..fb2666dac 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/jaxb/AbstractJaxbMessageConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/jaxb/AbstractJaxbMessageConverter.java @@ -44,7 +44,6 @@ * @param The internal representation of the object that can be safely marshalled/unmarshalled using JAXB. * @param The external representation of the object that is exposed externally but cannot be marshalled/unmarshalled using JAXB. */ -@SuppressWarnings("restriction") abstract class AbstractJaxbMessageConverter extends AbstractXmlHttpMessageConverter { private final Class internalClass; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2AccessToken.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2AccessToken.java index 649fac68a..1cbabd251 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2AccessToken.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2AccessToken.java @@ -18,7 +18,6 @@ import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlTransient; -@SuppressWarnings("restriction") @XmlRootElement(name = "oauth") class JaxbOAuth2AccessToken { private String accessToken; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2Exception.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2Exception.java index f0ecf9747..ca4f3fdd2 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2Exception.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2Exception.java @@ -17,7 +17,6 @@ import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; -@SuppressWarnings("restriction") @XmlRootElement(name = "oauth") @XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL) class JaxbOAuth2Exception { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseClientDetails.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseClientDetails.java index 4dcfeda2b..68e05d2f2 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseClientDetails.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseClientDetails.java @@ -38,6 +38,7 @@ * @author Ryan Heaton * @author Dave Syer */ +@SuppressWarnings("serial") @JsonSerialize(include = Inclusion.NON_DEFAULT) @JsonIgnoreProperties(ignoreUnknown = true) public class BaseClientDetails implements ClientDetails { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientAlreadyExistsException.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientAlreadyExistsException.java index 5a7ba4a40..eae256046 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientAlreadyExistsException.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientAlreadyExistsException.java @@ -21,6 +21,7 @@ * @author Dave Syer * */ +@SuppressWarnings("serial") public class ClientAlreadyExistsException extends ClientRegistrationException { public ClientAlreadyExistsException(String msg) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientRegistrationException.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientRegistrationException.java index 05c108b47..aa32bf437 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientRegistrationException.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientRegistrationException.java @@ -19,6 +19,7 @@ * @author Dave Syer * */ +@SuppressWarnings("serial") public class ClientRegistrationException extends RuntimeException { public ClientRegistrationException(String msg) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/NoSuchClientException.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/NoSuchClientException.java index 5089ab29a..ba68dee61 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/NoSuchClientException.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/NoSuchClientException.java @@ -19,6 +19,7 @@ * @author Dave Syer * */ +@SuppressWarnings("serial") public class NoSuchClientException extends ClientRegistrationException { public NoSuchClientException(String msg) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java index 99c8d9a35..40775ad44 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java @@ -19,6 +19,7 @@ * @author Amanda Anganes * */ +@SuppressWarnings("serial") public class TokenRequest extends BaseRequest { private String grantType; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java index ff899af93..e6cdd802d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java @@ -76,12 +76,12 @@ public ResponseEntity getAccessToken(Principal principal, } String clientId = getClientId(principal); + ClientDetails client = getClientDetailsService().loadClientByClientId(clientId); HashMap map = new HashMap(parameters); if (clientId != null) { map.put(OAuth2Utils.CLIENT_ID, clientId); // Only validate the client details if a client authenticated during this // request. - ClientDetails client = getClientDetailsService().loadClientByClientId(clientId); if (client != null) { oAuth2RequestValidator.validateScope(map, client.getScope()); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/DefaultWebResponseExceptionTranslator.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/DefaultWebResponseExceptionTranslator.java index 8015ad1f5..a242e564a 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/DefaultWebResponseExceptionTranslator.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/DefaultWebResponseExceptionTranslator.java @@ -84,6 +84,7 @@ public void setThrowableAnalyzer(ThrowableAnalyzer throwableAnalyzer) { this.throwableAnalyzer = throwableAnalyzer; } + @SuppressWarnings("serial") private static class ForbiddenException extends OAuth2Exception { public ForbiddenException(String msg, Throwable t) { @@ -100,6 +101,7 @@ public int getHttpErrorCode() { } + @SuppressWarnings("serial") private static class ServerErrorException extends OAuth2Exception { public ServerErrorException(String msg, Throwable t) { @@ -115,6 +117,7 @@ public int getHttpErrorCode() { } } + @SuppressWarnings("serial") private static class UnauthorizedException extends OAuth2Exception { public UnauthorizedException(String msg, Throwable t) { diff --git a/spring-security-oauth2/src/main/resources/META-INF/spring.schemas b/spring-security-oauth2/src/main/resources/META-INF/spring.schemas index f9d874654..206973acf 100644 --- a/spring-security-oauth2/src/main/resources/META-INF/spring.schemas +++ b/spring-security-oauth2/src/main/resources/META-INF/spring.schemas @@ -1,2 +1,3 @@ http\://www.springframework.org/schema/security/spring-security-oauth2-1.0.xsd=org/springframework/security/oauth2/spring-security-oauth2-1.0.xsd -http\://www.springframework.org/schema/security/spring-security-oauth2.xsd=org/springframework/security/oauth2/spring-security-oauth2-1.0.xsd \ No newline at end of file +http\://www.springframework.org/schema/security/spring-security-oauth2-1.1.xsd=org/springframework/security/oauth2/spring-security-oauth2-1.1.xsd +http\://www.springframework.org/schema/security/spring-security-oauth2.xsd=org/springframework/security/oauth2/spring-security-oauth2-1.1.xsd \ No newline at end of file diff --git a/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.0.xsd b/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.0.xsd index abe3c2dc5..08865c92e 100644 --- a/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.0.xsd +++ b/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.0.xsd @@ -514,13 +514,6 @@ - - - - The set of scopes (or simply "true" for all) to autoapprove. - - - diff --git a/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.1.xsd b/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.1.xsd index 08865c92e..6f421dfc4 100644 --- a/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.1.xsd +++ b/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.1.xsd @@ -497,6 +497,13 @@ + + + + Scopes or scope patterns that are autoapproved (comma-separated), or just "true" to autoapprove all. + + + diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/TestAuthorizationCodeAccessTokenProvider.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/TestAuthorizationCodeAccessTokenProvider.java index 7190b98fd..83a8a35da 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/TestAuthorizationCodeAccessTokenProvider.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/TestAuthorizationCodeAccessTokenProvider.java @@ -73,7 +73,8 @@ public void testRedirectToAuthorizationEndpoint() throws Exception { } } - @Test(expected = IllegalStateException.class) + // A missing redirect just means the server has to deal with it + @Test(expected = UserRedirectRequiredException.class) public void testRedirectNotSpecified() throws Exception { AccessTokenRequest request = new DefaultAccessTokenRequest(); resource.setUserAuthorizationUri("http://localhost/oauth/authorize"); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/TestResourceServerBeanDefinitionParser.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/TestResourceServerBeanDefinitionParser.java index 330766b2c..de94932ca 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/TestResourceServerBeanDefinitionParser.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/TestResourceServerBeanDefinitionParser.java @@ -19,16 +19,18 @@ /** * @author Dave Syer - * + * */ public class TestResourceServerBeanDefinitionParser { @Test public void testDefaults() { - GenericXmlApplicationContext context = new GenericXmlApplicationContext(getClass(), getClass().getSimpleName()+"-context.xml"); + GenericXmlApplicationContext context = new GenericXmlApplicationContext( + getClass(), getClass().getSimpleName() + "-context.xml"); // System.err.println(Arrays.asList(context.getBeanDefinitionNames())); assertTrue(context.containsBeanDefinition("oauth2ProviderFilter")); assertTrue(context.containsBeanDefinition("anotherProviderFilter")); assertTrue(context.containsBeanDefinition("thirdProviderFilter")); + context.close(); } } \ No newline at end of file diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/BaseJaxbMessageConverterTest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/BaseJaxbMessageConverterTest.java index bd07b869b..cf52a5bae 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/BaseJaxbMessageConverterTest.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/BaseJaxbMessageConverterTest.java @@ -40,7 +40,6 @@ * @author Rob Winch * */ -@SuppressWarnings("restriction") @RunWith(PowerMockRunner.class) @PrepareForTest(System.class) abstract class BaseJaxbMessageConverterTest { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/TestJaxbOAuth2AccessTokenMessageConverter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/TestJaxbOAuth2AccessTokenMessageConverter.java index d6caa896e..99da1a4ba 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/TestJaxbOAuth2AccessTokenMessageConverter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/TestJaxbOAuth2AccessTokenMessageConverter.java @@ -34,7 +34,6 @@ * @author Rob Winch * */ -@SuppressWarnings("restriction") @PrepareForTest(JaxbOAuth2AccessToken.class) public class TestJaxbOAuth2AccessTokenMessageConverter extends BaseJaxbMessageConverterTest { private JaxbOAuth2AccessTokenMessageConverter converter; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/TestJaxbOAuth2ExceptionMessageConverter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/TestJaxbOAuth2ExceptionMessageConverter.java index fce14a58a..cb8930de7 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/TestJaxbOAuth2ExceptionMessageConverter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/TestJaxbOAuth2ExceptionMessageConverter.java @@ -40,7 +40,6 @@ * @author Rob Winch * */ -@SuppressWarnings("restriction") @RunWith(PowerMockRunner.class) @PrepareForTest({ System.class, JaxbOAuth2AccessToken.class }) public class TestJaxbOAuth2ExceptionMessageConverter extends BaseJaxbMessageConverterTest { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestJdbcClientDetailsService.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestJdbcClientDetailsService.java index 55ec52d86..12387945c 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestJdbcClientDetailsService.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestJdbcClientDetailsService.java @@ -35,7 +35,8 @@ public class TestJdbcClientDetailsService { @Before public void setUp() throws Exception { - // creates a HSQL in-memory db populated from default scripts classpath:schema.sql and classpath:data.sql + // creates a HSQL in-memory db populated from default scripts + // classpath:schema.sql and classpath:data.sql db = new EmbeddedDatabaseBuilder().addDefaultScripts().build(); jdbcTemplate = new JdbcTemplate(db); service = new JdbcClientDetailsService(db); @@ -53,9 +54,11 @@ public void testLoadingClientForNonExistingClientId() { @Test public void testLoadingClientIdWithNoDetails() { - jdbcTemplate.update(INSERT_SQL, "clientIdWithNoDetails", null, null, null, null, null, null, null, null, null); + jdbcTemplate.update(INSERT_SQL, "clientIdWithNoDetails", null, null, + null, null, null, null, null, null, null); - ClientDetails clientDetails = service.loadClientByClientId("clientIdWithNoDetails"); + ClientDetails clientDetails = service + .loadClientByClientId("clientIdWithNoDetails"); assertEquals("clientIdWithNoDetails", clientDetails.getClientId()); assertFalse(clientDetails.isSecretRequired()); @@ -71,21 +74,28 @@ public void testLoadingClientIdWithNoDetails() { @Test public void testLoadingClientIdWithAdditionalInformation() { - jdbcTemplate.update(INSERT_SQL, "clientIdWithAddInfo", null, null, null, null, null, null, null, null, null); - jdbcTemplate.update("update oauth_client_details set additional_information=? where client_id=?", "{\"foo\":\"bar\"}", "clientIdWithAddInfo"); + jdbcTemplate.update(INSERT_SQL, "clientIdWithAddInfo", null, null, + null, null, null, null, null, null, null); + jdbcTemplate + .update("update oauth_client_details set additional_information=? where client_id=?", + "{\"foo\":\"bar\"}", "clientIdWithAddInfo"); - ClientDetails clientDetails = service.loadClientByClientId("clientIdWithAddInfo"); + ClientDetails clientDetails = service + .loadClientByClientId("clientIdWithAddInfo"); assertEquals("clientIdWithAddInfo", clientDetails.getClientId()); - assertEquals(Collections.singletonMap("foo", "bar"), clientDetails.getAdditionalInformation()); + assertEquals(Collections.singletonMap("foo", "bar"), + clientDetails.getAdditionalInformation()); } @Test public void testLoadingClientIdWithSingleDetails() { - jdbcTemplate.update(INSERT_SQL, "clientIdWithSingleDetails", "mySecret", "myResource", "myScope", - "myAuthorizedGrantType", "myRedirectUri", "myAuthority", 100, 200, "true"); + jdbcTemplate.update(INSERT_SQL, "clientIdWithSingleDetails", + "mySecret", "myResource", "myScope", "myAuthorizedGrantType", + "myRedirectUri", "myAuthority", 100, 200, "true"); - ClientDetails clientDetails = service.loadClientByClientId("clientIdWithSingleDetails"); + ClientDetails clientDetails = service + .loadClientByClientId("clientIdWithSingleDetails"); assertEquals("clientIdWithSingleDetails", clientDetails.getClientId()); assertTrue(clientDetails.isSecretRequired()); @@ -94,27 +104,36 @@ public void testLoadingClientIdWithSingleDetails() { assertEquals(1, clientDetails.getScope().size()); assertEquals("myScope", clientDetails.getScope().iterator().next()); assertEquals(1, clientDetails.getResourceIds().size()); - assertEquals("myResource", clientDetails.getResourceIds().iterator().next()); + assertEquals("myResource", clientDetails.getResourceIds().iterator() + .next()); assertEquals(1, clientDetails.getAuthorizedGrantTypes().size()); - assertEquals("myAuthorizedGrantType", clientDetails.getAuthorizedGrantTypes().iterator().next()); - assertEquals("myRedirectUri", clientDetails.getRegisteredRedirectUri().iterator().next()); + assertEquals("myAuthorizedGrantType", clientDetails + .getAuthorizedGrantTypes().iterator().next()); + assertEquals("myRedirectUri", clientDetails.getRegisteredRedirectUri() + .iterator().next()); assertEquals(1, clientDetails.getAuthorities().size()); - assertEquals("myAuthority", clientDetails.getAuthorities().iterator().next().getAuthority()); - assertEquals(new Integer(100), clientDetails.getAccessTokenValiditySeconds()); - assertEquals(new Integer(200), clientDetails.getRefreshTokenValiditySeconds()); + assertEquals("myAuthority", clientDetails.getAuthorities().iterator() + .next().getAuthority()); + assertEquals(new Integer(100), + clientDetails.getAccessTokenValiditySeconds()); + assertEquals(new Integer(200), + clientDetails.getRefreshTokenValiditySeconds()); } @Test public void testLoadingClientIdWithSingleDetailsInCustomTable() { - jdbcTemplate.update(CUSTOM_INSERT_SQL, "clientIdWithSingleDetails", "mySecret", "myResource", "myScope", - "myAuthorizedGrantType", "myRedirectUri", "myAuthority"); + jdbcTemplate.update(CUSTOM_INSERT_SQL, "clientIdWithSingleDetails", + "mySecret", "myResource", "myScope", "myAuthorizedGrantType", + "myRedirectUri", "myAuthority"); - JdbcClientDetailsService customService = new JdbcClientDetailsService(db); + JdbcClientDetailsService customService = new JdbcClientDetailsService( + db); customService .setSelectClientDetailsSql("select appId, appSecret, resourceIds, scope, " + "grantTypes, redirectUrl, authorities, access_token_validity, refresh_token_validity, additionalInformation, autoApproveScopes from ClientDetails where appId = ?"); - ClientDetails clientDetails = customService.loadClientByClientId("clientIdWithSingleDetails"); + ClientDetails clientDetails = customService + .loadClientByClientId("clientIdWithSingleDetails"); assertEquals("clientIdWithSingleDetails", clientDetails.getClientId()); assertTrue(clientDetails.isSecretRequired()); @@ -123,28 +142,36 @@ public void testLoadingClientIdWithSingleDetailsInCustomTable() { assertEquals(1, clientDetails.getScope().size()); assertEquals("myScope", clientDetails.getScope().iterator().next()); assertEquals(1, clientDetails.getResourceIds().size()); - assertEquals("myResource", clientDetails.getResourceIds().iterator().next()); + assertEquals("myResource", clientDetails.getResourceIds().iterator() + .next()); assertEquals(1, clientDetails.getAuthorizedGrantTypes().size()); - assertEquals("myAuthorizedGrantType", clientDetails.getAuthorizedGrantTypes().iterator().next()); - assertEquals("myRedirectUri", clientDetails.getRegisteredRedirectUri().iterator().next()); + assertEquals("myAuthorizedGrantType", clientDetails + .getAuthorizedGrantTypes().iterator().next()); + assertEquals("myRedirectUri", clientDetails.getRegisteredRedirectUri() + .iterator().next()); assertEquals(1, clientDetails.getAuthorities().size()); - assertEquals("myAuthority", clientDetails.getAuthorities().iterator().next().getAuthority()); + assertEquals("myAuthority", clientDetails.getAuthorities().iterator() + .next().getAuthority()); } @Test public void testLoadingClientIdWithMultipleDetails() { - jdbcTemplate.update(INSERT_SQL, "clientIdWithMultipleDetails", "mySecret", "myResource1,myResource2", - "myScope1,myScope2", "myAuthorizedGrantType1,myAuthorizedGrantType2", "myRedirectUri1,myRedirectUri2", - "myAuthority1,myAuthority2", 100, 200, "read,write"); + jdbcTemplate.update(INSERT_SQL, "clientIdWithMultipleDetails", + "mySecret", "myResource1,myResource2", "myScope1,myScope2", + "myAuthorizedGrantType1,myAuthorizedGrantType2", + "myRedirectUri1,myRedirectUri2", "myAuthority1,myAuthority2", + 100, 200, "read,write"); - ClientDetails clientDetails = service.loadClientByClientId("clientIdWithMultipleDetails"); + ClientDetails clientDetails = service + .loadClientByClientId("clientIdWithMultipleDetails"); assertEquals("clientIdWithMultipleDetails", clientDetails.getClientId()); assertTrue(clientDetails.isSecretRequired()); assertEquals("mySecret", clientDetails.getClientSecret()); assertTrue(clientDetails.isScoped()); assertEquals(2, clientDetails.getResourceIds().size()); - Iterator resourceIds = clientDetails.getResourceIds().iterator(); + Iterator resourceIds = clientDetails.getResourceIds() + .iterator(); assertEquals("myResource1", resourceIds.next()); assertEquals("myResource2", resourceIds.next()); assertEquals(2, clientDetails.getScope().size()); @@ -152,19 +179,24 @@ public void testLoadingClientIdWithMultipleDetails() { assertEquals("myScope1", scope.next()); assertEquals("myScope2", scope.next()); assertEquals(2, clientDetails.getAuthorizedGrantTypes().size()); - Iterator grantTypes = clientDetails.getAuthorizedGrantTypes().iterator(); + Iterator grantTypes = clientDetails.getAuthorizedGrantTypes() + .iterator(); assertEquals("myAuthorizedGrantType1", grantTypes.next()); assertEquals("myAuthorizedGrantType2", grantTypes.next()); assertEquals(2, clientDetails.getRegisteredRedirectUri().size()); - Iterator redirectUris = clientDetails.getRegisteredRedirectUri().iterator(); + Iterator redirectUris = clientDetails + .getRegisteredRedirectUri().iterator(); assertEquals("myRedirectUri1", redirectUris.next()); assertEquals("myRedirectUri2", redirectUris.next()); assertEquals(2, clientDetails.getAuthorities().size()); - Iterator authorities = clientDetails.getAuthorities().iterator(); + Iterator authorities = clientDetails.getAuthorities() + .iterator(); assertEquals("myAuthority1", authorities.next().getAuthority()); assertEquals("myAuthority2", authorities.next().getAuthority()); - assertEquals(new Integer(100), clientDetails.getAccessTokenValiditySeconds()); - assertEquals(new Integer(200), clientDetails.getRefreshTokenValiditySeconds()); + assertEquals(new Integer(100), + clientDetails.getAccessTokenValiditySeconds()); + assertEquals(new Integer(200), + clientDetails.getRefreshTokenValiditySeconds()); assertTrue(clientDetails.isAutoApprove("read")); } @@ -176,7 +208,8 @@ public void testAddClientWithNoDetails() { service.addClientDetails(clientDetails); - Map map = jdbcTemplate.queryForMap(SELECT_SQL, "addedClientIdWithNoDetails"); + Map map = jdbcTemplate.queryForMap(SELECT_SQL, + "addedClientIdWithNoDetails"); assertEquals("addedClientIdWithNoDetails", map.get("client_id")); assertTrue(map.containsKey("client_secret")); @@ -201,7 +234,8 @@ public void testUpdateClientSecret() { service.setPasswordEncoder(new PasswordEncoder() { - public boolean matches(CharSequence rawPassword, String encodedPassword) { + public boolean matches(CharSequence rawPassword, + String encodedPassword) { return true; } @@ -212,7 +246,8 @@ public String encode(CharSequence rawPassword) { service.addClientDetails(clientDetails); service.updateClientSecret(clientDetails.getClientId(), "foo"); - Map map = jdbcTemplate.queryForMap(SELECT_SQL, "newClientIdWithNoDetails"); + Map map = jdbcTemplate.queryForMap(SELECT_SQL, + "newClientIdWithNoDetails"); assertEquals("newClientIdWithNoDetails", map.get("client_id")); assertTrue(map.containsKey("client_secret")); @@ -227,16 +262,20 @@ public void testUpdateClientRedirectURI() { service.addClientDetails(clientDetails); - String[] redirectURI = { "http://localhost:8080/", "http://localhost:9090/" }; - clientDetails.setRegisteredRedirectUri(new HashSet(Arrays.asList(redirectURI))); + String[] redirectURI = { "http://localhost:8080/", + "http://localhost:9090/" }; + clientDetails.setRegisteredRedirectUri(new HashSet(Arrays + .asList(redirectURI))); service.updateClientDetails(clientDetails); - Map map = jdbcTemplate.queryForMap(SELECT_SQL, "newClientIdWithNoDetails"); + Map map = jdbcTemplate.queryForMap(SELECT_SQL, + "newClientIdWithNoDetails"); assertEquals("newClientIdWithNoDetails", map.get("client_id")); assertTrue(map.containsKey("web_server_redirect_uri")); - assertEquals("http://localhost:8080,http://localhost:9090", map.get("web_server_redirect_uri")); + assertEquals("http://localhost:8080,http://localhost:9090", + map.get("web_server_redirect_uri")); } @Test(expected = NoSuchClientException.class) @@ -257,8 +296,9 @@ public void testRemoveClient() { service.addClientDetails(clientDetails); service.removeClientDetails(clientDetails.getClientId()); - int count = jdbcTemplate.queryForInt("select count(*) from oauth_client_details where client_id=?", - "deletedClientIdWithNoDetails"); + int count = jdbcTemplate.queryForObject( + "select count(*) from oauth_client_details where client_id=?", + Integer.class, "deletedClientIdWithNoDetails"); assertEquals(0, count); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestJdbcApprovalStore.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestJdbcApprovalStore.java index 12bd0cce7..a14576802 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestJdbcApprovalStore.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestJdbcApprovalStore.java @@ -54,13 +54,20 @@ protected ApprovalStore getApprovalStore() { @Test public void testRevokeByExpiry() { store.setHandleRevocationsAsExpiry(true); - Approval approval1 = new Approval("user", "client", "read", 10000, ApprovalStatus.APPROVED); - Approval approval2 = new Approval("user", "client", "write", 10000, ApprovalStatus.APPROVED); - assertTrue(store.addApprovals(Arrays. asList(approval1, approval2))); + Approval approval1 = new Approval("user", "client", "read", 10000, + ApprovalStatus.APPROVED); + Approval approval2 = new Approval("user", "client", "write", 10000, + ApprovalStatus.APPROVED); + assertTrue(store.addApprovals(Arrays. asList(approval1, + approval2))); store.revokeApprovals(Arrays.asList(approval1)); assertEquals(2, store.getApprovals("user", "client").size()); - assertEquals(1, new JdbcTemplate(db).queryForInt( - "SELECT COUNT(*) from oauth_approvals where userId='user' AND expiresAt < ?", - new Date(System.currentTimeMillis() + 1000))); + assertEquals( + new Integer(1), + new JdbcTemplate(db) + .queryForObject( + "SELECT COUNT(*) from oauth_approvals where userId='user' AND expiresAt < ?", + Integer.class, + new Date(System.currentTimeMillis() + 1000))); } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestDefaultTokenServicesWithJdbc.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestDefaultTokenServicesWithJdbc.java index c55363da0..b5215951f 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestDefaultTokenServicesWithJdbc.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestDefaultTokenServicesWithJdbc.java @@ -25,11 +25,11 @@ public void tearDown() throws Exception { protected int getAccessTokenCount() { - return new JdbcTemplate(db).queryForInt("SELECT COUNT(*) FROM OAUTH_ACCESS_TOKEN"); + return new JdbcTemplate(db).queryForObject("SELECT COUNT(*) FROM OAUTH_ACCESS_TOKEN", Integer.class); } protected int getRefreshTokenCount() { - return new JdbcTemplate(db).queryForInt("SELECT COUNT(*) FROM OAUTH_REFRESH_TOKEN"); + return new JdbcTemplate(db).queryForObject("SELECT COUNT(*) FROM OAUTH_REFRESH_TOKEN", Integer.class); } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJwtTokenServices.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJwtTokenServices.java index e1c4d404e..b0968d932 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJwtTokenServices.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJwtTokenServices.java @@ -232,6 +232,7 @@ private OAuth2Request createOAuth2Request(String clientId, Set scope) { null, null); } + @SuppressWarnings("serial") protected static class TestAuthentication extends AbstractAuthenticationToken { private String principal; From 1fbd8f8dcc02ba27a1d386a4186a66baadfe5ba9 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 7 Oct 2013 15:08:27 -0400 Subject: [PATCH 096/831] Add test for fixed registered redirect The spec says that a redirect can be computed by the auth server if one is registered for the client. Tonr has 2 registrations and only one has a redirect. In addition to testing that the redirect can be ommitted we test that the URL that triggers the token acquisition can be different than the registered URI (/trigger and /redirect). --- samples/oauth2/sparklr/pom.xml | 2 +- .../main/webapp/WEB-INF/spring-servlet.xml | 2 +- .../tonr/TestAuthorizationCodeGrant.java | 67 ++++++++++++++----- 3 files changed, 53 insertions(+), 18 deletions(-) diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index a08bb0f15..bbc6a7f25 100644 --- a/samples/oauth2/sparklr/pom.xml +++ b/samples/oauth2/sparklr/pom.xml @@ -178,7 +178,7 @@ org.apache.httpcomponents httpclient - 4.1.2 + 4.2.2 test diff --git a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml index 83c180e06..c01cddab3 100644 --- a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml +++ b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml @@ -203,7 +203,7 @@ - diff --git a/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestAuthorizationCodeGrant.java b/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestAuthorizationCodeGrant.java index 0d2147340..09ef83659 100755 --- a/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestAuthorizationCodeGrant.java +++ b/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestAuthorizationCodeGrant.java @@ -33,11 +33,13 @@ public class TestAuthorizationCodeGrant { private AuthorizationCodeResourceDetails resource = new AuthorizationCodeResourceDetails(); { - resource.setAccessTokenUri(serverRunning.getUrl("/sparklr2/oauth/token")); + resource.setAccessTokenUri(serverRunning + .getUrl("/sparklr2/oauth/token")); resource.setClientId("my-client-with-registered-redirect"); resource.setId("sparklr"); resource.setScope(Arrays.asList("trust")); - resource.setUserAuthorizationUri(serverRunning.getUrl("/sparklr2/oauth/authorize")); + resource.setUserAuthorizationUri(serverRunning + .getUrl("/sparklr2/oauth/authorize")); } @Test @@ -46,12 +48,13 @@ public void testCannotConnectWithoutToken() throws Exception { OAuth2RestTemplate template = new OAuth2RestTemplate(resource); resource.setPreEstablishedRedirectUri("http://anywhere.com/"); try { - template.getForObject(serverRunning.getUrl("/tonr2/photos"), String.class); + template.getForObject(serverRunning.getUrl("/tonr2/photos"), + String.class); fail("Expected UserRedirectRequiredException"); - } - catch (UserRedirectRequiredException e) { + } catch (UserRedirectRequiredException e) { String message = e.getMessage(); - assertTrue("Wrong message: " + message, + assertTrue( + "Wrong message: " + message, message.contains("A redirect is required to get the users approval")); } } @@ -60,13 +63,14 @@ public void testCannotConnectWithoutToken() throws Exception { public void testAttemptedTokenAcquisitionWithNoRedirect() throws Exception { AuthorizationCodeAccessTokenProvider provider = new AuthorizationCodeAccessTokenProvider(); try { - OAuth2AccessToken token = provider.obtainAccessToken(resource, new DefaultAccessTokenRequest()); + OAuth2AccessToken token = provider.obtainAccessToken(resource, + new DefaultAccessTokenRequest()); fail("Expected UserRedirectRequiredException"); assertNotNull(token); - } - catch (IllegalStateException e) { + } catch (UserRedirectRequiredException e) { String message = e.getMessage(); - assertTrue("Wrong message: " + message, message.contains("No redirect URI has been established")); + assertTrue("Wrong message: " + message, + message.contains("A redirect is required")); } } @@ -76,18 +80,47 @@ public void testTokenAcquisitionWithCorrectContext() throws Exception { MultiValueMap form = new LinkedMultiValueMap(); form.add("j_username", "marissa"); form.add("j_password", "wombat"); - HttpHeaders response = serverRunning.postForHeaders("/tonr2/login.do", form); + HttpHeaders response = serverRunning.postForHeaders("/tonr2/login.do", + form); String cookie = response.getFirst("Set-Cookie"); HttpHeaders headers = new HttpHeaders(); headers.set("Cookie", cookie); // headers.setAccept(Collections.singletonList(MediaType.ALL)); - headers.setAccept(MediaType.parseMediaTypes("image/png,image/*;q=0.8,*/*;q=0.5")); + headers.setAccept(MediaType + .parseMediaTypes("image/png,image/*;q=0.8,*/*;q=0.5")); + + String location = serverRunning.getForRedirect( + "/tonr2/sparklr/photos/1", headers); + location = authenticateAndApprove(location); + + assertTrue("Redirect location should be to the original photo URL: " + + location, location.contains("photos/1")); + HttpStatus status = serverRunning.getStatusCode(location, headers); + assertEquals(HttpStatus.OK, status); + } + + @Test + public void testTokenAcquisitionWithRegisteredRedirect() throws Exception { + + MultiValueMap form = new LinkedMultiValueMap(); + form.add("j_username", "marissa"); + form.add("j_password", "wombat"); + HttpHeaders response = serverRunning.postForHeaders("/tonr2/login.do", + form); + String cookie = response.getFirst("Set-Cookie"); + + HttpHeaders headers = new HttpHeaders(); + headers.set("Cookie", cookie); - String location = serverRunning.getForRedirect("/tonr2/sparklr/photos/1", headers); + // The registered redirect is /redirect, but /trigger is used as a test + // because it is different (i.e. not the current request URI). + String location = serverRunning.getForRedirect( + "/tonr2/sparklr/trigger", headers); location = authenticateAndApprove(location); - assertTrue("Redirect location should be to the original photo URL: " + location, location.contains("photos/1")); + assertTrue("Redirect location should be to the original photo URL: " + + location, location.contains("sparklr/redirect")); HttpStatus status = serverRunning.getStatusCode(location, headers); assertEquals(HttpStatus.OK, status); } @@ -98,7 +131,8 @@ private String authenticateAndApprove(String location) { MultiValueMap form = new LinkedMultiValueMap(); form.add("j_username", "marissa"); form.add("j_password", "koala"); - HttpHeaders response = serverRunning.postForHeaders("/sparklr2/login.do", form); + HttpHeaders response = serverRunning.postForHeaders( + "/sparklr2/login.do", form); String cookie = response.getFirst("Set-Cookie"); HttpHeaders headers = new HttpHeaders(); @@ -109,7 +143,8 @@ private String authenticateAndApprove(String location) { form = new LinkedMultiValueMap(); form.add("user_oauth_approval", "true"); form.add("scope.read", "true"); - response = serverRunning.postForHeaders("/sparklr2/oauth/authorize", form, headers); + response = serverRunning.postForHeaders("/sparklr2/oauth/authorize", + form, headers); return response.getLocation().toString(); } From f5122ec0ddacaf5b7862a0c1f5b8829f45ba4491 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 7 Oct 2013 15:23:29 -0400 Subject: [PATCH 097/831] SECOAUTH-404: remove @Autowired --- .../filter/OAuthConsumerContextFilter.java | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/filter/OAuthConsumerContextFilter.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/filter/OAuthConsumerContextFilter.java index f79895ccc..c8fd4566a 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/filter/OAuthConsumerContextFilter.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/filter/OAuthConsumerContextFilter.java @@ -16,10 +16,26 @@ package org.springframework.security.oauth.consumer.filter; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.TreeMap; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; @@ -46,17 +62,6 @@ import org.springframework.security.web.util.ThrowableCauseExtractor; import org.springframework.util.Assert; -import javax.servlet.*; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import java.util.TreeMap; - /** * OAuth filter that establishes an OAuth security context. * @@ -398,7 +403,6 @@ public OAuthConsumerSupport getConsumerSupport() { * * @param consumerSupport The OAuth consumer support. */ - @Autowired public void setConsumerSupport(OAuthConsumerSupport consumerSupport) { this.consumerSupport = consumerSupport; } @@ -435,7 +439,6 @@ public PortResolver getPortResolver() { * * @param portResolver The port resolver. */ - @Autowired ( required = false ) public void setPortResolver(PortResolver portResolver) { this.portResolver = portResolver; } From 6b305bafa1ff3cd7fb569b1dc13250000c6f4ee2 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Wed, 9 Oct 2013 12:38:27 -0400 Subject: [PATCH 098/831] Removed readObject and writeObject from OAuth2Request (which no longer needs them) --- .../oauth2/provider/AuthorizationRequest.java | 131 ++++++++++++------ .../security/oauth2/provider/BaseRequest.java | 35 +---- .../oauth2/provider/OAuth2Request.java | 75 +++------- .../oauth2/provider/TokenRequest.java | 44 ++++-- 4 files changed, 147 insertions(+), 138 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java index 3e9661daa..9538fc8d0 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java @@ -5,17 +5,32 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.oauth2.common.util.OAuth2Utils; +import org.springframework.web.bind.annotation.SessionAttributes; /** - * Base class representing an OAuth2 Authorization Request. HTTP request parameters are stored in the parameters map, - * and any processing the server makes throughout the lifecycle of a request are stored on individual properties. The - * original request parameters will remain available through the parameters map. For convenience, constants are defined - * in order to get at those original values. However, the parameters map is unmodifiable so that processing cannot drop - * the original values. + * A request for authorization by an OAuth 2 Client, normally received and + * processed by the AuthorizationEndpoint. This class is meant to be manipulated + * throughout the authorization process, and is therefore treated as ephemeral + * and not to be stored long term. For long term storage, use the read-only + * {@link OAuth2Request} class. + * + * HTTP request parameters are stored in the parameters map, and any processing + * the server makes throughout the lifecycle of a request are stored on + * individual properties. The original request parameters will remain available + * through the parameters map. For convenience, constants are defined in order + * to get at those original values. However, the parameters map is unmodifiable + * so that processing cannot drop the original values. + * + * This class is {@link Serializable} in order to support storage of the + * authorization request as a {@link SessionAttributes} member while the end + * user through the authorization process (which may span several page + * requests). * * @author Ryan Heaton * @author Dave Syer @@ -25,20 +40,22 @@ public class AuthorizationRequest extends BaseRequest implements Serializable { /** - * Map to hold the original, unchanged parameter set submitted by a user to signal approval of the token grant - * approval. Once set this should not be modified. + * Map to hold the original, unchanged parameter set submitted by a user to + * signal approval of the token grant approval. Once set this should not be + * modified. */ private Map approvalParameters = Collections.unmodifiableMap(new HashMap()); /** - * The value of the "state" parameter sent by the client in the request, if sent by the client. As this must be - * echoed back to the client unchanged, it should not be modified by any processing classes. + * The value of the "state" parameter sent by the client in the request, if + * sent by the client. As this must be echoed back to the client unchanged, + * it should not be modified by any processing classes. */ private String state; /** - * Resolved requested response types initialized (by the OAuth2RequestFactory) with the response types originally - * requested. + * Resolved requested response types initialized (by the + * OAuth2RequestFactory) with the response types originally requested. */ private Set responseTypes = new HashSet(); @@ -48,26 +65,30 @@ public class AuthorizationRequest extends BaseRequest implements Serializable { private Set resourceIds = new HashSet(); /** - * Resolved granted authorities for this request. May change during request processing. + * Resolved granted authorities for this request. May change during request + * processing. */ private Collection authorities = new HashSet(); /** - * Whether the request has been approved by the end user (or other process). This will be altered by the User - * Approval Endpoint and/or the UserApprovalHandler as appropriate. + * Whether the request has been approved by the end user (or other process). + * This will be altered by the User Approval Endpoint and/or the + * UserApprovalHandler as appropriate. */ private boolean approved = false; /** - * The resolved redirect URI of this request. A URI may be present in the original request, in the - * authorizationParameters, or it may not be provided, in which case it will be defaulted (by processing classes) to + * The resolved redirect URI of this request. A URI may be present in the + * original request, in the authorizationParameters, or it may not be + * provided, in which case it will be defaulted (by processing classes) to * the Client's default registered value. */ private String redirectUri; /** - * Extension point for custom processing classes which may wish to store additional information about the OAuth2 - * request. Since this class will create a serializable OAuth2Request, all members of this extension map + * Extension point for custom processing classes which may wish to store + * additional information about the OAuth2 request. Since this class will + * create a serializable OAuth2Request, all members of this extension map * must be serializable. */ private Map extensions = new HashMap(); @@ -81,13 +102,12 @@ public AuthorizationRequest() { /** * Full constructor. */ - public AuthorizationRequest(Map authorizationParameters, Map approvalParameters, - String clientId, Set scope, Set resourceIds, - Collection authorities, boolean approved, String state, String redirectUri, - Set responseTypes) { - super.setClientId(clientId); - super.setRequestParameters(authorizationParameters); - super.setScope(scope); + public AuthorizationRequest(Map authorizationParameters, Map approvalParameters, String clientId, Set scope, Set resourceIds, Collection authorities, boolean approved, String state, String redirectUri, + Set responseTypes) { + this.clientId = clientId; + setRequestParameters(authorizationParameters); // in case we need to + // wrap the collection + setScope(scope); // in case we need to parse if (resourceIds != null) { this.resourceIds = new HashSet(resourceIds); } @@ -108,18 +128,20 @@ public OAuth2Request createOAuth2Request() { } /** - * Convenience constructor for unit tests, where client ID and scope are often the only needed fields. + * Convenience constructor for unit tests, where client ID and scope are + * often the only needed fields. * * @param clientId * @param scopes */ public AuthorizationRequest(String clientId, Collection scopes) { - super.setClientId(clientId); - super.setScope(new HashSet(scopes)); + this.clientId = clientId; + setScope(scope); // in case we need to parse } /** - * Convenience method to set resourceIds and authorities on this request by inheriting from a ClientDetails object. + * Convenience method to set resourceIds and authorities on this request by + * inheriting from a ClientDetails object. * * @param clientDetails */ @@ -161,7 +183,7 @@ public void setApproved(boolean approved) { } public void setAuthorities(Collection authorities) { - if (authorities!= null) { + if (authorities != null) { this.authorities = new HashSet(authorities); } } @@ -181,20 +203,44 @@ public void setResourceIds(Set resourceIds) { this.resourceIds = resourceIds; } - // expose the superclass's utility method - @Override public void setClientId(String clientId) { - super.setClientId(clientId); + this.clientId = clientId; } - // expose the superclass's utility method - @Override + /** + * Set the scope value. If the collection contains only a single scope + * value, this method will parse that value into a collection using + * {@link OAuth2Utils.parseParameterList}. + * + * @see TokenRequest.setScope + * + * @param scope + */ public void setScope(Collection scope) { - super.setScope(scope); + if (scope != null && scope.size() == 1) { + String value = scope.iterator().next(); + /* + * This is really an error, but it can catch out unsuspecting users + * and it's easy to fix. It happens when an AuthorizationRequest + * gets bound accidentally from request parameters using + * @ModelAttribute. + */ + if (value.contains(" ") || value.contains(",")) { + scope = OAuth2Utils.parseParameterList(value); + } + } + this.scope = Collections.unmodifiableSet(scope == null ? new LinkedHashSet() : new LinkedHashSet(scope)); } - // expose the superclass's utiltiy method - @Override + /** + * Set the Request Parameters on this authorization request, which represent + * the original request parameters and should never be changed during + * processing. The map passed in is wrapped in an unmodifiable map instance. + * + * @see TokenRequest.setRequestParameters + * + * @param requestParameters + */ public void setRequestParameters(Map requestParameters) { if (requestParameters != null) { this.requestParameters = Collections.unmodifiableMap(requestParameters); @@ -251,20 +297,17 @@ public boolean equals(Object obj) { if (approvalParameters == null) { if (other.approvalParameters != null) return false; - } - else if (!approvalParameters.equals(other.approvalParameters)) + } else if (!approvalParameters.equals(other.approvalParameters)) return false; if (responseTypes == null) { if (other.responseTypes != null) return false; - } - else if (!responseTypes.equals(other.responseTypes)) + } else if (!responseTypes.equals(other.responseTypes)) return false; if (state == null) { if (other.state != null) return false; - } - else if (!state.equals(other.state)) + } else if (!state.equals(other.state)) return false; return true; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java index dfbc4c275..6c2174ccf 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java @@ -17,17 +17,19 @@ package org.springframework.security.oauth2.provider; import java.io.Serializable; -import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; -import org.springframework.security.oauth2.common.util.OAuth2Utils; - /** + * + * A base class for the three "*Request" classes used in processing OAuth 2 + * authorizations. This class should never be used directly, + * and it should never be used as the type for a local or other + * variable. + * * @author Dave Syer * */ @@ -62,29 +64,10 @@ public String getClientId() { return clientId; } - protected void setClientId(String clientId) { - this.clientId = clientId; - } - public Set getScope() { return scope; } - protected void setScope(Collection scope) { - if (scope != null && scope.size() == 1) { - String value = scope.iterator().next(); - /* - * This is really an error, but it can catch out unsuspecting users and it's easy to fix. It happens when an - * AuthorizationRequest gets bound accidentally from request parameters using @ModelAttribute. - */ - if (value.contains(" ") || value.contains(",")) { - scope = OAuth2Utils.parseParameterList(value); - } - } - this.scope = Collections.unmodifiableSet(scope == null ? new LinkedHashSet() - : new LinkedHashSet(scope)); - } - /** * Warning: most clients should use the individual properties of this class, such as {{@link #getScope()} or { * {@link #getClientId()}, rather than retrieving values from this map. @@ -95,12 +78,6 @@ public Map getRequestParameters() { return requestParameters; } - protected void setRequestParameters(Map requestParameters) { - if (requestParameters != null) { - this.requestParameters = Collections.unmodifiableMap(requestParameters); - } - } - @Override public int hashCode() { final int prime = 31; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java index 7c06205ab..f76233f00 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java @@ -1,16 +1,16 @@ package org.springframework.security.oauth2.provider; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.oauth2.common.util.OAuth2Utils; /** * Represents a stored authorization or token request. Used as part of the OAuth2Authentication object to store a @@ -63,9 +63,21 @@ public class OAuth2Request extends BaseRequest implements Serializable { public OAuth2Request(Map requestParameters, String clientId, Collection authorities, boolean approved, Set scope, Set resourceIds, String redirectUri, Set responseTypes, Map extensionProperties) { - super.setClientId(clientId); - super.setRequestParameters(requestParameters); - super.setScope(scope); + this.clientId = clientId; + if (requestParameters != null) { + this.requestParameters = Collections.unmodifiableMap(requestParameters); + } + if (scope != null && scope.size() == 1) { + String value = scope.iterator().next(); + /* + * This is really an error, but it can catch out unsuspecting users and it's easy to fix. It happens when an + * AuthorizationRequest gets bound accidentally from request parameters using @ModelAttribute. + */ + if (value.contains(" ") || value.contains(",")) { + scope = OAuth2Utils.parseParameterList(value); + } + } + this.scope = Collections.unmodifiableSet(scope == null ? new LinkedHashSet() : new LinkedHashSet(scope)); if (resourceIds != null) { this.resourceIds = new HashSet(resourceIds); } @@ -89,7 +101,7 @@ protected OAuth2Request(OAuth2Request other) { } protected OAuth2Request(String clientId) { - super.setClientId(clientId); + this.clientId = clientId; } protected OAuth2Request() { @@ -120,36 +132,6 @@ public Map getExtensions() { return extensions; } - - - // - // These three methods override the protected utility methods in the parent class to ensure that the setters never get called. - // - - /* (non-Javadoc) - * @see org.springframework.security.oauth2.provider.BaseRequest#setClientId(java.lang.String) - */ - @Override - protected void setClientId(String clientId) { - throw new IllegalStateException("Can't set clientId on OAuth2Request"); - } - - /* (non-Javadoc) - * @see org.springframework.security.oauth2.provider.BaseRequest#setScope(java.util.Collection) - */ - @Override - protected void setScope(Collection scope) { - throw new IllegalStateException("Can't set scope on OAuth2Request"); - } - - /* (non-Javadoc) - * @see org.springframework.security.oauth2.provider.BaseRequest#setRequestParameters(java.util.Map) - */ - @Override - protected void setRequestParameters(Map requestParameters) { - throw new IllegalStateException("Can't set request parameters on OAuth2Request"); - } - /** * Update the request parameters and return a new object with the same properties except the parameters. * @param parameters new parameters replacing the existing ones @@ -160,25 +142,6 @@ public OAuth2Request createOAuth2Request(Map parameters) { redirectUri, responseTypes, extensions); } - // - // Handle serialization and deserialization to capture fields from parent class - // - - private void writeObject(ObjectOutputStream out) throws IOException { - out.defaultWriteObject(); - out.writeObject(clientId); - out.writeObject(new HashMap(requestParameters)); - out.writeObject(new HashSet(scope)); - } - - @SuppressWarnings("unchecked") - private void readObject(ObjectInputStream in) throws ClassNotFoundException, IOException { - in.defaultReadObject(); - clientId = (String) in.readObject(); - requestParameters = (HashMap) in.readObject(); - scope = (HashSet) in.readObject(); - } - @Override public int hashCode() { final int prime = 31; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java index 40775ad44..4f3542b5e 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java @@ -3,8 +3,10 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.Map; +import org.springframework.security.oauth2.common.util.OAuth2Utils; import org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint; import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint; @@ -39,7 +41,7 @@ protected TokenRequest() { * @param grantType */ public TokenRequest(Map requestParameters, String clientId, Collection scope, String grantType) { - super.setClientId(clientId); + this.clientId = clientId; setRequestParameters(requestParameters); setScope(scope); this.grantType = grantType; @@ -53,20 +55,44 @@ public void setGrantType(String grantType) { this.grantType = grantType; } - // expose the superclass's utility method - @Override public void setClientId(String clientId) { - super.setClientId(clientId); + this.clientId = clientId; } - // expose the superclass's utility method - @Override + + /** + * Set the scope value. If the collection contains only a single scope + * value, this method will parse that value into a collection using + * {@link OAuth2Utils.parseParameterList}. + * + * @see AuthorizationRequest.setScope + * + * @param scope + */ public void setScope(Collection scope) { - super.setScope(scope); + if (scope != null && scope.size() == 1) { + String value = scope.iterator().next(); + /* + * This is really an error, but it can catch out unsuspecting users and it's easy to fix. It happens when an + * AuthorizationRequest gets bound accidentally from request parameters using @ModelAttribute. + */ + if (value.contains(" ") || value.contains(",")) { + scope = OAuth2Utils.parseParameterList(value); + } + } + this.scope = Collections.unmodifiableSet(scope == null ? new LinkedHashSet() + : new LinkedHashSet(scope)); } - // expose the superclass's utility method - @Override + /** + * Set the Request Parameters on this authorization request, which represent + * the original request parameters and should never be changed during + * processing. The map passed in is wrapped in an unmodifiable map instance. + * + * @see AuthorizationRequest.setRequestParameters + * + * @param requestParameters + */ public void setRequestParameters(Map requestParameters) { if (requestParameters != null) { this.requestParameters = Collections.unmodifiableMap(requestParameters); From 081be23099a34fee890b188a49055f5609a4632f Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 9 Oct 2013 17:13:04 -0400 Subject: [PATCH 099/831] Make shared fields private with protected setter --- .../oauth2/provider/AuthorizationRequest.java | 27 ++---- .../security/oauth2/provider/BaseRequest.java | 90 ++++++++++++++----- .../oauth2/provider/OAuth2Request.java | 23 +---- .../oauth2/provider/TokenRequest.java | 66 ++++++-------- 4 files changed, 105 insertions(+), 101 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java index 9538fc8d0..0c58aa4ee 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java @@ -5,7 +5,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; @@ -104,7 +103,7 @@ public AuthorizationRequest() { */ public AuthorizationRequest(Map authorizationParameters, Map approvalParameters, String clientId, Set scope, Set resourceIds, Collection authorities, boolean approved, String state, String redirectUri, Set responseTypes) { - this.clientId = clientId; + setClientId(clientId); setRequestParameters(authorizationParameters); // in case we need to // wrap the collection setScope(scope); // in case we need to parse @@ -135,8 +134,8 @@ public OAuth2Request createOAuth2Request() { * @param scopes */ public AuthorizationRequest(String clientId, Collection scopes) { - this.clientId = clientId; - setScope(scope); // in case we need to parse + setClientId(clientId); + setScope(scopes); // in case we need to parse } /** @@ -204,7 +203,7 @@ public void setResourceIds(Set resourceIds) { } public void setClientId(String clientId) { - this.clientId = clientId; + super.setClientId(clientId); } /** @@ -217,19 +216,7 @@ public void setClientId(String clientId) { * @param scope */ public void setScope(Collection scope) { - if (scope != null && scope.size() == 1) { - String value = scope.iterator().next(); - /* - * This is really an error, but it can catch out unsuspecting users - * and it's easy to fix. It happens when an AuthorizationRequest - * gets bound accidentally from request parameters using - * @ModelAttribute. - */ - if (value.contains(" ") || value.contains(",")) { - scope = OAuth2Utils.parseParameterList(value); - } - } - this.scope = Collections.unmodifiableSet(scope == null ? new LinkedHashSet() : new LinkedHashSet(scope)); + super.setScope(scope); } /** @@ -242,9 +229,7 @@ public void setScope(Collection scope) { * @param requestParameters */ public void setRequestParameters(Map requestParameters) { - if (requestParameters != null) { - this.requestParameters = Collections.unmodifiableMap(requestParameters); - } + super.setRequestParameters(requestParameters); } /** diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java index 6c2174ccf..1dcb5a8ca 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java @@ -17,12 +17,16 @@ package org.springframework.security.oauth2.provider; import java.io.Serializable; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; +import org.springframework.security.oauth2.common.util.OAuth2Utils; + /** * * A base class for the three "*Request" classes used in processing OAuth 2 @@ -37,29 +41,35 @@ abstract class BaseRequest implements Serializable { /** - * Resolved client ID. This may be present in the original request parameters, or in some cases may be inferred by a - * processing class and inserted here. + * Resolved client ID. This may be present in the original request + * parameters, or in some cases may be inferred by a processing class and + * inserted here. */ - protected String clientId; + private String clientId; /** - * Resolved scope set, initialized (by the OAuth2RequestFactory) with the scopes originally requested. Further - * processing and user interaction may alter the set of scopes that is finally granted and stored when the request - * processing is complete. + * Resolved scope set, initialized (by the OAuth2RequestFactory) with the + * scopes originally requested. Further processing and user interaction may + * alter the set of scopes that is finally granted and stored when the + * request processing is complete. */ - protected Set scope = new HashSet(); + private Set scope = new HashSet(); /** - * Map of parameters passed in to the Authorization Endpoint or Token Endpoint, preserved unchanged from the - * original request. This map should not be modified after initialization. In general, classes should not retrieve - * values from this map directly, and should instead use the individual members on this class. + * Map of parameters passed in to the Authorization Endpoint or Token + * Endpoint, preserved unchanged from the original request. This map should + * not be modified after initialization. In general, classes should not + * retrieve values from this map directly, and should instead use the + * individual members on this class. * - * The OAuth2RequestFactory is responsible for initializing all members of this class, usually by parsing the values - * inside the requestParmaeters map. + * The OAuth2RequestFactory is responsible for initializing all members of + * this class, usually by parsing the values inside the requestParmaeters + * map. * */ - protected Map requestParameters = Collections.unmodifiableMap(new HashMap()); - + private Map requestParameters = Collections + .unmodifiableMap(new HashMap()); + public String getClientId() { return clientId; } @@ -69,8 +79,9 @@ public Set getScope() { } /** - * Warning: most clients should use the individual properties of this class, such as {{@link #getScope()} or { - * {@link #getClientId()}, rather than retrieving values from this map. + * Warning: most clients should use the individual properties of this class, + * such as {{@link #getScope()} or { {@link #getClientId()}, rather than + * retrieving values from this map. * * @return the original, unchanged set of request parameters */ @@ -82,8 +93,12 @@ public Map getRequestParameters() { public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + ((clientId == null) ? 0 : clientId.hashCode()); - result = prime * result + ((requestParameters == null) ? 0 : requestParameters.hashCode()); + result = prime * result + + ((clientId == null) ? 0 : clientId.hashCode()); + result = prime + * result + + ((requestParameters == null) ? 0 : requestParameters + .hashCode()); result = prime * result + ((scope == null) ? 0 : scope.hashCode()); return result; } @@ -100,22 +115,49 @@ public boolean equals(Object obj) { if (clientId == null) { if (other.clientId != null) return false; - } - else if (!clientId.equals(other.clientId)) + } else if (!clientId.equals(other.clientId)) return false; if (requestParameters == null) { if (other.requestParameters != null) return false; - } - else if (!requestParameters.equals(other.requestParameters)) + } else if (!requestParameters.equals(other.requestParameters)) return false; if (scope == null) { if (other.scope != null) return false; - } - else if (!scope.equals(other.scope)) + } else if (!scope.equals(other.scope)) return false; return true; } + protected void setScope(Collection scope) { + if (scope != null && scope.size() == 1) { + String value = scope.iterator().next(); + /* + * This is really an error, but it can catch out unsuspecting users + * and it's easy to fix. It happens when an AuthorizationRequest + * gets bound accidentally from request parameters using + * + * @ModelAttribute. + */ + if (value.contains(" ") || value.contains(",")) { + scope = OAuth2Utils.parseParameterList(value); + } + } + this.scope = Collections + .unmodifiableSet(scope == null ? new LinkedHashSet() + : new LinkedHashSet(scope)); + } + + protected void setRequestParameters(Map requestParameters) { + if (requestParameters != null) { + this.requestParameters = Collections + .unmodifiableMap(requestParameters); + } + } + + protected void setClientId(String clientId) { + this.clientId = clientId; + } + } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java index f76233f00..0fd054d25 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java @@ -2,15 +2,12 @@ import java.io.Serializable; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.oauth2.common.util.OAuth2Utils; /** * Represents a stored authorization or token request. Used as part of the OAuth2Authentication object to store a @@ -63,21 +60,9 @@ public class OAuth2Request extends BaseRequest implements Serializable { public OAuth2Request(Map requestParameters, String clientId, Collection authorities, boolean approved, Set scope, Set resourceIds, String redirectUri, Set responseTypes, Map extensionProperties) { - this.clientId = clientId; - if (requestParameters != null) { - this.requestParameters = Collections.unmodifiableMap(requestParameters); - } - if (scope != null && scope.size() == 1) { - String value = scope.iterator().next(); - /* - * This is really an error, but it can catch out unsuspecting users and it's easy to fix. It happens when an - * AuthorizationRequest gets bound accidentally from request parameters using @ModelAttribute. - */ - if (value.contains(" ") || value.contains(",")) { - scope = OAuth2Utils.parseParameterList(value); - } - } - this.scope = Collections.unmodifiableSet(scope == null ? new LinkedHashSet() : new LinkedHashSet(scope)); + setClientId(clientId); + setRequestParameters(requestParameters); + setScope(scope); if (resourceIds != null) { this.resourceIds = new HashSet(resourceIds); } @@ -101,7 +86,7 @@ protected OAuth2Request(OAuth2Request other) { } protected OAuth2Request(String clientId) { - this.clientId = clientId; + setClientId(clientId); } protected OAuth2Request() { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java index 4f3542b5e..f2a9e96ba 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java @@ -1,9 +1,7 @@ package org.springframework.security.oauth2.provider; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; -import java.util.LinkedHashSet; import java.util.Map; import org.springframework.security.oauth2.common.util.OAuth2Utils; @@ -11,37 +9,42 @@ import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint; /** - * Represents an OAuth2 token request, made at the {@link TokenEndpoint}. The requestParameters map should - * contain the original, unmodified parameters from the original OAuth2 request. + * Represents an OAuth2 token request, made at the {@link TokenEndpoint}. The + * requestParameters map should contain the original, unmodified parameters from + * the original OAuth2 request. * - * In the implicit flow, a token is requested through the {@link AuthorizationEndpoint} directly, and in - * that case the {@link AuthorizationRequest} is converted into a {@link TokenRequest} for processing - * through the token granting chain. + * In the implicit flow, a token is requested through the + * {@link AuthorizationEndpoint} directly, and in that case the + * {@link AuthorizationRequest} is converted into a {@link TokenRequest} for + * processing through the token granting chain. * * @author Amanda Anganes - * + * @author Dave Syer + * */ @SuppressWarnings("serial") public class TokenRequest extends BaseRequest { - + private String grantType; - + /** * Default constructor */ protected TokenRequest() { } - + /** - * Full constructor. Sets this TokenRequest's requestParameters map to an unmodifiable version of the one provided. + * Full constructor. Sets this TokenRequest's requestParameters map to an + * unmodifiable version of the one provided. * * @param requestParameters * @param clientId * @param scope * @param grantType */ - public TokenRequest(Map requestParameters, String clientId, Collection scope, String grantType) { - this.clientId = clientId; + public TokenRequest(Map requestParameters, String clientId, + Collection scope, String grantType) { + setClientId(clientId); setRequestParameters(requestParameters); setScope(scope); this.grantType = grantType; @@ -56,10 +59,9 @@ public void setGrantType(String grantType) { } public void setClientId(String clientId) { - this.clientId = clientId; + super.setClientId(clientId); } - /** * Set the scope value. If the collection contains only a single scope * value, this method will parse that value into a collection using @@ -70,41 +72,31 @@ public void setClientId(String clientId) { * @param scope */ public void setScope(Collection scope) { - if (scope != null && scope.size() == 1) { - String value = scope.iterator().next(); - /* - * This is really an error, but it can catch out unsuspecting users and it's easy to fix. It happens when an - * AuthorizationRequest gets bound accidentally from request parameters using @ModelAttribute. - */ - if (value.contains(" ") || value.contains(",")) { - scope = OAuth2Utils.parseParameterList(value); - } - } - this.scope = Collections.unmodifiableSet(scope == null ? new LinkedHashSet() - : new LinkedHashSet(scope)); + super.setScope(scope); } /** * Set the Request Parameters on this authorization request, which represent * the original request parameters and should never be changed during * processing. The map passed in is wrapped in an unmodifiable map instance. - * + * * @see AuthorizationRequest.setRequestParameters * * @param requestParameters */ public void setRequestParameters(Map requestParameters) { - if (requestParameters != null) { - this.requestParameters = Collections.unmodifiableMap(requestParameters); - } + super.setRequestParameters(requestParameters); } public OAuth2Request createOAuth2Request(ClientDetails client) { - // Remove password if present to prevent leaks - Map requestParameters = getRequestParameters(); - HashMap modifiable = new HashMap(requestParameters); + // Remove password if present to prevent leaks + Map requestParameters = getRequestParameters(); + HashMap modifiable = new HashMap( + requestParameters); modifiable.remove("password"); - return new OAuth2Request(modifiable, client.getClientId(), client.getAuthorities(), true, this.getScope(), null, null, null, null); + return new OAuth2Request(modifiable, client.getClientId(), + client.getAuthorities(), true, this.getScope(), null, null, + null, null); } - + } From fd18647d17efa8b0ace4fcc87a2fc87d9ea07eba Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 29 Oct 2013 08:00:13 -0400 Subject: [PATCH 100/831] Add boolean flag to allow client authentication in request params --- .../ClientCredentialsTokenEndpointFilter.java | 73 +++++++++++++------ 1 file changed, 50 insertions(+), 23 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenEndpointFilter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenEndpointFilter.java index b11be687b..e928e3405 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenEndpointFilter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenEndpointFilter.java @@ -30,20 +30,25 @@ import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; +import org.springframework.web.HttpRequestMethodNotSupportedException; /** - * A filter and authentication endpoint for the OAuth2 Token Endpoint. Allows clients to authenticate using request - * parameters if included as a security filter, as permitted by the specification (but not recommended). It is - * recommended by the specification that you permit HTTP basic authentication for clients, and not use this filter at - * all. + * A filter and authentication endpoint for the OAuth2 Token Endpoint. Allows + * clients to authenticate using request parameters if included as a security + * filter, as permitted by the specification (but not recommended). It is + * recommended by the specification that you permit HTTP basic authentication + * for clients, and not use this filter at all. * * @author Dave Syer * */ -public class ClientCredentialsTokenEndpointFilter extends AbstractAuthenticationProcessingFilter { +public class ClientCredentialsTokenEndpointFilter extends + AbstractAuthenticationProcessingFilter { private AuthenticationEntryPoint authenticationEntryPoint = new OAuth2AuthenticationEntryPoint(); + private boolean allowOnlyPost = false; + public ClientCredentialsTokenEndpointFilter() { this("/oauth/token"); } @@ -51,13 +56,20 @@ public ClientCredentialsTokenEndpointFilter() { public ClientCredentialsTokenEndpointFilter(String path) { super(path); // If authentication fails the type is "Form" - ((OAuth2AuthenticationEntryPoint)authenticationEntryPoint).setTypeName("Form"); + ((OAuth2AuthenticationEntryPoint) authenticationEntryPoint) + .setTypeName("Form"); + } + + public void setAllowOnlyPost(boolean allowOnlyPost) { + this.allowOnlyPost = allowOnlyPost; } /** - * @param authenticationEntryPoint the authentication entry point to set + * @param authenticationEntryPoint + * the authentication entry point to set */ - public void setAuthenticationEntryPoint(AuthenticationEntryPoint authenticationEntryPoint) { + public void setAuthenticationEntryPoint( + AuthenticationEntryPoint authenticationEntryPoint) { this.authenticationEntryPoint = authenticationEntryPoint; } @@ -65,35 +77,48 @@ public void setAuthenticationEntryPoint(AuthenticationEntryPoint authenticationE public void afterPropertiesSet() { super.afterPropertiesSet(); setAuthenticationFailureHandler(new AuthenticationFailureHandler() { - public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, - AuthenticationException exception) throws IOException, ServletException { + public void onAuthenticationFailure(HttpServletRequest request, + HttpServletResponse response, + AuthenticationException exception) throws IOException, + ServletException { if (exception instanceof BadCredentialsException) { - exception = new BadCredentialsException(exception.getMessage(), new BadClientCredentialsException()); + exception = new BadCredentialsException( + exception.getMessage(), + new BadClientCredentialsException()); } authenticationEntryPoint.commence(request, response, exception); } }); setAuthenticationSuccessHandler(new AuthenticationSuccessHandler() { - public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, - Authentication authentication) throws IOException, ServletException { + public void onAuthenticationSuccess(HttpServletRequest request, + HttpServletResponse response, Authentication authentication) + throws IOException, ServletException { // no-op - just allow filter chain to continue to token endpoint } }); } @Override - public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) - throws AuthenticationException, IOException, ServletException { + public Authentication attemptAuthentication(HttpServletRequest request, + HttpServletResponse response) throws AuthenticationException, + IOException, ServletException { + + if (allowOnlyPost && !"POST".equalsIgnoreCase(request.getMethod())) { + throw new HttpRequestMethodNotSupportedException( + request.getMethod(), new String[] { "POST" }); + } String clientId = request.getParameter("client_id"); String clientSecret = request.getParameter("client_secret"); - // If the request is already authenticated we can assume that this filter is not needed - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + // If the request is already authenticated we can assume that this + // filter is not needed + Authentication authentication = SecurityContextHolder.getContext() + .getAuthentication(); if (authentication != null && authentication.isAuthenticated()) { return authentication; } - + if (clientId == null) { throw new BadCredentialsException("No client credentials presented"); } @@ -103,22 +128,24 @@ public Authentication attemptAuthentication(HttpServletRequest request, HttpServ } clientId = clientId.trim(); - UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(clientId, - clientSecret); + UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken( + clientId, clientSecret); return this.getAuthenticationManager().authenticate(authRequest); } @Override - protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, - FilterChain chain, Authentication authResult) throws IOException, ServletException { + protected void successfulAuthentication(HttpServletRequest request, + HttpServletResponse response, FilterChain chain, + Authentication authResult) throws IOException, ServletException { super.successfulAuthentication(request, response, chain, authResult); chain.doFilter(request, response); } @Override - protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) { + protected boolean requiresAuthentication(HttpServletRequest request, + HttpServletResponse response) { String uri = request.getRequestURI(); int pathParamIndex = uri.indexOf(';'); From 09c63f39418d252bf2ac188392ee007aef96929d Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 31 Oct 2013 16:23:40 +0000 Subject: [PATCH 101/831] Small changes to support Spring 4 --- pom.xml | 6 ++ samples/oauth2/sparklr/pom.xml | 25 +++++++- .../oauth2/provider/ServerRunning.java | 58 ++++++++++--------- samples/oauth2/tonr/pom.xml | 16 ++++- spring-security-oauth/pom.xml | 2 +- 5 files changed, 73 insertions(+), 34 deletions(-) diff --git a/pom.xml b/pom.xml index 0380bf17b..ea52eebc6 100644 --- a/pom.xml +++ b/pom.xml @@ -65,6 +65,12 @@ + + spring4 + + 4.0.0.BUILD-SNAPSHOT + + staging diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index bbc6a7f25..9210ae0d3 100644 --- a/samples/oauth2/sparklr/pom.xml +++ b/samples/oauth2/sparklr/pom.xml @@ -112,6 +112,24 @@ ${spring.version} + + org.springframework + spring-core + ${spring.version} + + + + org.springframework + spring-beans + ${spring.version} + + + + org.springframework + spring-context + ${spring.version} + + org.springframework spring-jdbc @@ -157,8 +175,9 @@ javax.servlet - servlet-api - 2.3 + javax.servlet-api + + 3.0.1 provided @@ -178,7 +197,7 @@ org.apache.httpcomponents httpclient - 4.2.2 + 4.3.1 test diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ServerRunning.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ServerRunning.java index 6b26efd8f..78e7eaf96 100644 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ServerRunning.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ServerRunning.java @@ -11,9 +11,10 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.http.client.HttpClient; -import org.apache.http.client.params.ClientPNames; -import org.apache.http.client.params.CookiePolicy; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.config.RequestConfig.Builder; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.client.methods.HttpUriRequest; import org.junit.Assume; import org.junit.internal.AssumptionViolatedException; import org.junit.rules.MethodRule; @@ -80,7 +81,7 @@ public class ServerRunning implements MethodRule, RestTemplateHolder { private String hostName = DEFAULT_HOST; private RestOperations client; - + /** * @return a new rule that assumes an existing running broker */ @@ -126,8 +127,7 @@ public Statement apply(final Statement base, FrameworkMethod method, Object targ // Check at the beginning, so this can be used as a static field if (assumeOnline) { Assume.assumeTrue(serverOnline.get(port)); - } - else { + } else { Assume.assumeTrue(serverOffline.get(port)); } @@ -139,16 +139,14 @@ public Statement apply(final Statement base, FrameworkMethod method, Object targ client.getForEntity(new UriTemplate(getUrl("/sparklr2/login.jsp")).toString(), String.class); online = true; logger.info("Basic connectivity test passed"); - } - catch (RestClientException e) { + } catch (RestClientException e) { logger.warn(String.format( "Not executing tests because basic connectivity test failed for hostName=%s, port=%d", hostName, port), e); if (assumeOnline) { Assume.assumeNoException(e); } - } - finally { + } finally { HttpURLConnection.setFollowRedirects(followRedirects); if (online) { serverOffline.put(port, false); @@ -156,15 +154,13 @@ public Statement apply(final Statement base, FrameworkMethod method, Object targ Assume.assumeTrue(serverOffline.get(port)); } - } - else { + } else { serverOnline.put(port, false); } } final RestOperations savedClient = getRestTemplate(); - postForStatus(savedClient, "/sparklr2/oauth/uncache_approvals", - new LinkedMultiValueMap()); + postForStatus(savedClient, "/sparklr2/oauth/uncache_approvals", new LinkedMultiValueMap()); return new Statement() { @@ -172,8 +168,7 @@ public Statement apply(final Statement base, FrameworkMethod method, Object targ public void evaluate() throws Throwable { try { base.evaluate(); - } - finally { + } finally { postForStatus(savedClient, "/sparklr2/oauth/cache_approvals", new LinkedMultiValueMap()); } @@ -182,7 +177,7 @@ public void evaluate() throws Throwable { }; } - + public String getBaseUrl() { return "http://" + hostName + ":" + port; } @@ -245,7 +240,7 @@ private ResponseEntity postForStatus(RestOperations client, String path, H actualHeaders.putAll(headers); actualHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED); return client.exchange(getUrl(path), HttpMethod.POST, new HttpEntity>(formData, - actualHeaders), (Class)null); + actualHeaders), (Class) null); } public ResponseEntity postForRedirect(String path, HttpHeaders headers, MultiValueMap params) { @@ -262,7 +257,7 @@ public ResponseEntity postForRedirect(String path, HttpHeaders headers, Mu String location = exchange.getHeaders().getLocation().toString(); - return client.exchange(location, HttpMethod.GET, new HttpEntity(null, headers), (Class)null); + return client.exchange(location, HttpMethod.GET, new HttpEntity(null, headers), (Class) null); } public ResponseEntity getForString(String path) { @@ -280,7 +275,7 @@ public ResponseEntity getForString(String path, final HttpHeaders header public ResponseEntity getForResponse(String path, final HttpHeaders headers, Map uriVariables) { HttpEntity request = new HttpEntity(null, headers); - return client.exchange(getUrl(path), HttpMethod.GET, request, (Class)null, uriVariables); + return client.exchange(getUrl(path), HttpMethod.GET, request, (Class) null, uriVariables); } public ResponseEntity getForResponse(String path, HttpHeaders headers) { @@ -303,16 +298,24 @@ public void setRestTemplate(RestOperations restTemplate) { public RestOperations getRestTemplate() { return client; } - + public RestOperations createRestTemplate() { RestTemplate client = new RestTemplate(); client.setRequestFactory(new HttpComponentsClientHttpRequestFactory() { @Override - public HttpClient getHttpClient() { - HttpClient client = super.getHttpClient(); - client.getParams().setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, false); - client.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.IGNORE_COOKIES); - return client; + protected HttpUriRequest createHttpUriRequest(HttpMethod httpMethod, URI uri) { + HttpUriRequest request = super.createHttpUriRequest(httpMethod, uri); + if (request instanceof HttpRequestBase) { + HttpRequestBase base = (HttpRequestBase) request; + Builder builder = RequestConfig.custom(); + if (base.getConfig()!=null) { + builder = RequestConfig.copy(base.getConfig()); + } + RequestConfig config = builder.setRedirectsEnabled(false) + .setCookieSpec("ignoreCookies").build(); + base.setConfig(config); + } + return request; } }); client.setErrorHandler(new ResponseErrorHandler() { @@ -360,8 +363,7 @@ public String pattern() { for (String key : params.keySet()) { if (!first) { builder.append("&"); - } - else { + } else { first = false; } String value = params.get(key); diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 466cdc8e1..d12687aac 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -141,6 +141,18 @@ ${spring.version} + + org.springframework + spring-beans + ${spring.version} + + + + org.springframework + spring-core + ${spring.version} + + org.springframework spring-aop @@ -167,8 +179,8 @@ javax.servlet - servlet-api - 2.3 + javax.servlet-api + 3.0.1 provided diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index 36cc0a83a..edbd3c2a3 100644 --- a/spring-security-oauth/pom.xml +++ b/spring-security-oauth/pom.xml @@ -55,7 +55,7 @@ javax.servlet servlet-api - 2.3 + 2.5 provided From 1ce7aeff0b5740df1ec699fdaab4bbf85f00518c Mon Sep 17 00:00:00 2001 From: Amanda Anganes Date: Tue, 3 Sep 2013 13:12:15 -0400 Subject: [PATCH 102/831] Made OAuth2RequestValidator pluggable through the xml authorization-server configuration. --- .../AuthorizationServerBeanDefinitionParser.java | 12 ++++++++++++ .../security/oauth2/spring-security-oauth2-1.0.xsd | 13 ++++++++++++- .../oauth2/config/authorization-server-extras.xml | 6 ++++-- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/AuthorizationServerBeanDefinitionParser.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/AuthorizationServerBeanDefinitionParser.java index a60589853..cfaf63f4a 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/AuthorizationServerBeanDefinitionParser.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/AuthorizationServerBeanDefinitionParser.java @@ -26,6 +26,7 @@ import org.springframework.security.config.BeanIds; import org.springframework.security.oauth2.provider.CompositeTokenGranter; import org.springframework.security.oauth2.provider.DefaultOAuth2RequestFactory; +import org.springframework.security.oauth2.provider.DefaultOAuth2RequestValidator; import org.springframework.security.oauth2.provider.approval.DefaultUserApprovalHandler; import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenGranter; import org.springframework.security.oauth2.provider.code.AuthorizationCodeTokenGranter; @@ -68,6 +69,7 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P String redirectResolverRef = element.getAttribute("redirect-resolver-ref"); String implicitGrantServiceRef = element.getAttribute("implicit-grant-service-ref"); + String oAuth2RequestValidatorRef = element.getAttribute("request-validator-ref"); // Create a bean definition speculatively for the auth endpoint BeanDefinitionBuilder authorizationEndpointBean = BeanDefinitionBuilder @@ -81,6 +83,15 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P implicitGrantService.getBeanDefinition()); } + if (!StringUtils.hasText(oAuth2RequestValidatorRef)) { + oAuth2RequestValidatorRef = "defaultOAuth2RequestValidator"; + BeanDefinitionBuilder oAuth2RequestValidator = BeanDefinitionBuilder + .rootBeanDefinition(DefaultOAuth2RequestValidator.class); + parserContext.getRegistry().registerBeanDefinition(oAuth2RequestValidatorRef, + oAuth2RequestValidator.getBeanDefinition()); + } + authorizationEndpointBean.addPropertyReference("oAuth2RequestValidator", oAuth2RequestValidatorRef); + if (!StringUtils.hasText(oAuth2RequestFactoryRef)) { oAuth2RequestFactoryRef = "oAuth2AuthorizationRequestManager"; BeanDefinitionBuilder oAuth2RequestManager = BeanDefinitionBuilder @@ -247,6 +258,7 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P BeanDefinitionBuilder tokenEndpointBean = BeanDefinitionBuilder.rootBeanDefinition(TokenEndpoint.class); tokenEndpointBean.addPropertyReference("clientDetailsService", clientDetailsRef); tokenEndpointBean.addPropertyReference("tokenGranter", tokenGranterRef); + authorizationEndpointBean.addPropertyReference("oAuth2RequestValidator", oAuth2RequestValidatorRef); parserContext.getRegistry() .registerBeanDefinition("oauth2TokenEndpoint", tokenEndpointBean.getBeanDefinition()); if (StringUtils.hasText(oAuth2RequestFactoryRef)) { diff --git a/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.0.xsd b/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.0.xsd index 08865c92e..ff7eda3c2 100644 --- a/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.0.xsd +++ b/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.0.xsd @@ -243,7 +243,18 @@ - + + + + + The reference to the bean that defines the + OAuth2RequestValidator implementation. Default + value is an instance of + "org.springframework.security.oauth2.provider.DefaultOAuth2RequestValidator". + + + + diff --git a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/authorization-server-extras.xml b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/authorization-server-extras.xml index 93e057508..920afa44f 100644 --- a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/authorization-server-extras.xml +++ b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/authorization-server-extras.xml @@ -8,7 +8,7 @@ @@ -21,7 +21,7 @@ -
+
@@ -32,6 +32,8 @@ + + From aa00c3a0d93cb5c5d1031fbb8730ef54c209f2aa Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 5 Nov 2013 09:53:24 +0000 Subject: [PATCH 103/831] Move new features to 1.1 xsd --- .../security/oauth2/spring-security-oauth2-1.0.xsd | 11 ----------- .../security/oauth2/spring-security-oauth2-1.1.xsd | 11 +++++++++++ .../oauth2/config/authorization-server-extras.xml | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.0.xsd b/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.0.xsd index ff7eda3c2..71007dd0b 100644 --- a/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.0.xsd +++ b/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.0.xsd @@ -244,17 +244,6 @@ - - - - The reference to the bean that defines the - OAuth2RequestValidator implementation. Default - value is an instance of - "org.springframework.security.oauth2.provider.DefaultOAuth2RequestValidator". - - - - diff --git a/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.1.xsd b/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.1.xsd index 6f421dfc4..631192880 100644 --- a/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.1.xsd +++ b/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.1.xsd @@ -244,6 +244,17 @@ + + + + The reference to the bean that defines the + OAuth2RequestValidator implementation. Default + value is an instance of + "org.springframework.security.oauth2.provider.DefaultOAuth2RequestValidator". + + + + diff --git a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/authorization-server-extras.xml b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/authorization-server-extras.xml index 920afa44f..f73f259dd 100644 --- a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/authorization-server-extras.xml +++ b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/authorization-server-extras.xml @@ -2,7 +2,7 @@ Date: Thu, 19 Sep 2013 14:53:53 -0500 Subject: [PATCH 104/831] Fix for client_id in req parm and auth header --- .../token/grant/client/ClientCredentialsAccessTokenProvider.java | 1 - 1 file changed, 1 deletion(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/client/ClientCredentialsAccessTokenProvider.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/client/ClientCredentialsAccessTokenProvider.java index d97cfdde5..51d3faea5 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/client/ClientCredentialsAccessTokenProvider.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/client/ClientCredentialsAccessTokenProvider.java @@ -49,7 +49,6 @@ private MultiValueMap getParametersForTokenRequest(ClientCredent MultiValueMap form = new LinkedMultiValueMap(); form.set("grant_type", "client_credentials"); - form.set("client_id", resource.getClientId()); if (resource.isScoped()) { From 0d142e5465ec2248f6dd71930cba38d383fb4e31 Mon Sep 17 00:00:00 2001 From: Casey Lucas Date: Wed, 21 Aug 2013 17:40:23 -0500 Subject: [PATCH 105/831] Handle non-oauth2 errors similar to RestTemplate Update OAuth2ErrorHander to handle non-oauth2 errors in a similar same way that RestTemplate does. Now, OAuth2ErrorHandler only looks at 4XX status codes and if it is not able to determine a reasonable oauth2 error, it delegates to a different/default ErrorHandler. --- .../client/http/OAuth2ErrorHandler.java | 106 ++++++++++++++---- .../client/http/TestOAuth2ErrorHandler.java | 36 ++++-- 2 files changed, 110 insertions(+), 32 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandler.java index 33a9e746b..5454d3728 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandler.java @@ -15,16 +15,21 @@ */ package org.springframework.security.oauth2.client.http; +import java.io.ByteArrayInputStream; +import java.io.InputStream; import java.io.IOException; import java.util.List; import java.util.Map; import org.springframework.http.client.ClientHttpResponse; import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; +import org.springframework.util.FileCopyUtils; import org.springframework.web.client.DefaultResponseErrorHandler; import org.springframework.web.client.HttpMessageConverterExtractor; import org.springframework.web.client.ResponseErrorHandler; @@ -71,33 +76,86 @@ public boolean hasError(ClientHttpResponse response) throws IOException { return this.errorHandler.hasError(response); } - public void handleError(ClientHttpResponse response) throws IOException { - - HttpMessageConverterExtractor extractor = new HttpMessageConverterExtractor( - OAuth2Exception.class, messageConverters); - try { - OAuth2Exception body = extractor.extractData(response); - if (body != null) { - // If we can get an OAuth2Exception already from the body, it is likely to have more information than - // the header does, so just re-throw it here. - throw body; + public void handleError(final ClientHttpResponse response) throws IOException { + if (response.getStatusCode().series() != HttpStatus.Series.CLIENT_ERROR) { + // We should only care about 400 level errors. Ex: A 500 server error shouldn't + // be an oauth related error. + errorHandler.handleError(response); + } else { + // Need to use buffered response because input stream may need to be consumed multiple times. + ClientHttpResponse bufferedResponse = new ClientHttpResponse() { + private byte[] lazyBody; + + public HttpStatus getStatusCode() throws IOException { + return response.getStatusCode(); + } + + public synchronized InputStream getBody() throws IOException { + if (lazyBody == null) { + InputStream bodyStream = response.getBody(); + if (bodyStream != null) { + lazyBody = FileCopyUtils.copyToByteArray(bodyStream); + } + } + return new ByteArrayInputStream(lazyBody); + } + + public HttpHeaders getHeaders() { + return response.getHeaders(); + } + + public String getStatusText() throws IOException { + return response.getStatusText(); + } + + public void close() { + response.close(); + } + + public int getRawStatusCode() throws IOException { + return response.getRawStatusCode(); + } + }; + + try { + HttpMessageConverterExtractor extractor = new HttpMessageConverterExtractor( + OAuth2Exception.class, messageConverters); + try { + OAuth2Exception body = extractor.extractData(response); + if (body != null) { + // If we can get an OAuth2Exception already from the body, it is likely to have more information than + // the header does, so just re-throw it here. + throw body; + } + } + catch (RestClientException e) { + // ignore + } + + // first try: www-authenticate error + List authenticateHeaders = response.getHeaders().get("WWW-Authenticate"); + if (authenticateHeaders != null) { + for (String authenticateHeader : authenticateHeaders) { + maybeThrowExceptionFromHeader(authenticateHeader, OAuth2AccessToken.BEARER_TYPE); + maybeThrowExceptionFromHeader(authenticateHeader, OAuth2AccessToken.OAUTH2_TYPE); + } + } + + // then delegate to the custom handler + errorHandler.handleError(response); } - } - catch (RestClientException e) { - // ignore - } - - // first try: www-authenticate error - List authenticateHeaders = response.getHeaders().get("WWW-Authenticate"); - if (authenticateHeaders != null) { - for (String authenticateHeader : authenticateHeaders) { - maybeThrowExceptionFromHeader(authenticateHeader, OAuth2AccessToken.BEARER_TYPE); - maybeThrowExceptionFromHeader(authenticateHeader, OAuth2AccessToken.OAUTH2_TYPE); + catch (OAuth2Exception ex) { + if (bufferedResponse.getRawStatusCode() == 401 || ! ex.getClass().equals(OAuth2Exception.class)) { + // Status code 401 should always mean that we need a legitimate token. + // Caught a specific, derived class so this is not just some generic error + throw ex; + } else { + // This is not an exception that is really understood, so allow our delegate + // to handle it in a non-oauth way + errorHandler.handleError(bufferedResponse); + } } } - - // then delegate to the custom handler - errorHandler.handleError(response); } private void maybeThrowExceptionFromHeader(String authenticateHeader, String headerType) { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/http/TestOAuth2ErrorHandler.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/http/TestOAuth2ErrorHandler.java index 2c9329692..de98e20ec 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/http/TestOAuth2ErrorHandler.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/http/TestOAuth2ErrorHandler.java @@ -33,6 +33,7 @@ import org.springframework.http.client.ClientHttpResponse; import org.springframework.security.oauth2.client.resource.BaseOAuth2ProtectedResourceDetails; import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.ResponseErrorHandler; /** @@ -54,10 +55,11 @@ public class TestOAuth2ErrorHandler { private final class TestClientHttpResponse implements ClientHttpResponse { private final HttpHeaders headers; + private final HttpStatus status; - public TestClientHttpResponse(HttpHeaders headers) { + public TestClientHttpResponse(HttpHeaders headers, int status) { this.headers = headers; - + this.status = HttpStatus.valueOf(status); } public InputStream getBody() throws IOException { @@ -69,15 +71,15 @@ public HttpHeaders getHeaders() { } public HttpStatus getStatusCode() throws IOException { - return null; + return status; } public String getStatusText() throws IOException { - return null; + return status.getReasonPhrase(); } public int getRawStatusCode() throws IOException { - return 0; + return status.value(); } public void close() { @@ -94,7 +96,7 @@ public void testHandleErrorClientHttpResponse() throws Exception { HttpHeaders headers = new HttpHeaders(); headers.set("www-authenticate", "Bearer error=foo"); - ClientHttpResponse response = new TestClientHttpResponse(headers); + ClientHttpResponse response = new TestClientHttpResponse(headers,401); expected.expectMessage("foo"); handler.handleError(response); @@ -106,7 +108,7 @@ public void testHandleErrorWithInvalidToken() throws Exception { HttpHeaders headers = new HttpHeaders(); headers.set("www-authenticate", "Bearer error=\"invalid_token\", description=\"foo\""); - ClientHttpResponse response = new TestClientHttpResponse(headers); + ClientHttpResponse response = new TestClientHttpResponse(headers,401); expected.expect(AccessTokenRequiredException.class); expected.expectMessage("OAuth2 access denied"); @@ -129,13 +131,31 @@ public void handleError(ClientHttpResponse response) throws IOException { }, resource); HttpHeaders headers = new HttpHeaders(); - ClientHttpResponse response = new TestClientHttpResponse(headers); + ClientHttpResponse response = new TestClientHttpResponse(headers,401); expected.expectMessage("planned"); handler.handleError(response); } + @Test + public void testHandle500Error() throws Exception { + HttpHeaders headers = new HttpHeaders(); + ClientHttpResponse response = new TestClientHttpResponse(headers,500); + + expected.expect(HttpServerErrorException.class); + handler.handleError(response); + } + + @Test + public void testHandle400Error() throws Exception { + HttpHeaders headers = new HttpHeaders(); + ClientHttpResponse response = new TestClientHttpResponse(headers,400); + + expected.expect(HttpClientErrorException.class); + handler.handleError(response); + } + @Test public void testHandleErrorWithMissingHeader() throws IOException { From b3d55e44f85e672930831f02e3b4e888b9a9c511 Mon Sep 17 00:00:00 2001 From: Casey Lucas Date: Wed, 21 Aug 2013 19:13:33 -0500 Subject: [PATCH 106/831] Fix code that wasn't using buffered response. - Some code wasn't using the correct buffered response. - Added test case to verify that custom ErrorHandlers can consume the response body if needed. --- .../client/http/OAuth2ErrorHandler.java | 11 ++--- .../client/http/TestOAuth2ErrorHandler.java | 40 ++++++++++++++++++- 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandler.java index 5454d3728..f1aa8352e 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandler.java @@ -73,11 +73,12 @@ public OAuth2ErrorHandler(ResponseErrorHandler errorHandler, OAuth2ProtectedReso } public boolean hasError(ClientHttpResponse response) throws IOException { - return this.errorHandler.hasError(response); + return HttpStatus.Series.CLIENT_ERROR.equals(response.getStatusCode().series()) || + this.errorHandler.hasError(response); } public void handleError(final ClientHttpResponse response) throws IOException { - if (response.getStatusCode().series() != HttpStatus.Series.CLIENT_ERROR) { + if (! HttpStatus.Series.CLIENT_ERROR.equals(response.getStatusCode().series())) { // We should only care about 400 level errors. Ex: A 500 server error shouldn't // be an oauth related error. errorHandler.handleError(response); @@ -121,7 +122,7 @@ public int getRawStatusCode() throws IOException { HttpMessageConverterExtractor extractor = new HttpMessageConverterExtractor( OAuth2Exception.class, messageConverters); try { - OAuth2Exception body = extractor.extractData(response); + OAuth2Exception body = extractor.extractData(bufferedResponse); if (body != null) { // If we can get an OAuth2Exception already from the body, it is likely to have more information than // the header does, so just re-throw it here. @@ -133,7 +134,7 @@ public int getRawStatusCode() throws IOException { } // first try: www-authenticate error - List authenticateHeaders = response.getHeaders().get("WWW-Authenticate"); + List authenticateHeaders = bufferedResponse.getHeaders().get("WWW-Authenticate"); if (authenticateHeaders != null) { for (String authenticateHeader : authenticateHeaders) { maybeThrowExceptionFromHeader(authenticateHeader, OAuth2AccessToken.BEARER_TYPE); @@ -142,7 +143,7 @@ public int getRawStatusCode() throws IOException { } // then delegate to the custom handler - errorHandler.handleError(response); + errorHandler.handleError(bufferedResponse); } catch (OAuth2Exception ex) { if (bufferedResponse.getRawStatusCode() == 401 || ! ex.getClass().equals(OAuth2Exception.class)) { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/http/TestOAuth2ErrorHandler.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/http/TestOAuth2ErrorHandler.java index de98e20ec..b716914ee 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/http/TestOAuth2ErrorHandler.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/http/TestOAuth2ErrorHandler.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.io.InputStream; +import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -56,14 +57,20 @@ private final class TestClientHttpResponse implements ClientHttpResponse { private final HttpHeaders headers; private final HttpStatus status; + private final InputStream body; public TestClientHttpResponse(HttpHeaders headers, int status) { + this(headers,status,new ByteArrayInputStream(new byte[0])); + } + + public TestClientHttpResponse(HttpHeaders headers, int status, InputStream bodyStream) { this.headers = headers; this.status = HttpStatus.valueOf(status); + this.body = bodyStream; } public InputStream getBody() throws IOException { - return null; + return body; } public HttpHeaders getHeaders() { @@ -148,7 +155,7 @@ public void testHandle500Error() throws Exception { } @Test - public void testHandle400Error() throws Exception { + public void testHandleGeneric400Error() throws Exception { HttpHeaders headers = new HttpHeaders(); ClientHttpResponse response = new TestClientHttpResponse(headers,400); @@ -156,6 +163,35 @@ public void testHandle400Error() throws Exception { handler.handleError(response); } + @Test + public void testBodyCanBeUsedByCustomHandler() throws Exception { + final String appSpecificBodyContent = "{\"some_status\":\"app error\"}"; + OAuth2ErrorHandler handler = new OAuth2ErrorHandler(new ResponseErrorHandler() { + public boolean hasError(ClientHttpResponse response) throws IOException { + return true; + } + + public void handleError(ClientHttpResponse response) throws IOException { + InputStream body = response.getBody(); + byte[] buf = new byte[appSpecificBodyContent.length()]; + int readResponse = body.read(buf); + Assert.assertEquals(buf.length, readResponse); + Assert.assertEquals(appSpecificBodyContent,new String(buf, "UTF-8")); + throw new RuntimeException("planned"); + } + }, resource); + HttpHeaders headers = new HttpHeaders(); + headers.set("Content-Length",""+appSpecificBodyContent.length()); + headers.set("Content-Type","application/json"); + InputStream appSpecificErrorBody = + new ByteArrayInputStream(appSpecificBodyContent.getBytes("UTF-8")); + ClientHttpResponse response = + new TestClientHttpResponse(headers,400,appSpecificErrorBody); + + expected.expectMessage("planned"); + handler.handleError(response); + } + @Test public void testHandleErrorWithMissingHeader() throws IOException { From e76aa5d17db2ff9c530f52d364839f892317ec9a Mon Sep 17 00:00:00 2001 From: Casey Lucas Date: Fri, 20 Sep 2013 20:44:34 -0500 Subject: [PATCH 107/831] change test cases to match updated error handling --- .../oauth2/provider/TestAdminEndpoints.java | 42 +++++++++++++++---- .../TestAuthorizationCodeProvider.java | 13 +++--- 2 files changed, 41 insertions(+), 14 deletions(-) diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestAdminEndpoints.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestAdminEndpoints.java index 8f22dd1ee..407fe3737 100644 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestAdminEndpoints.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestAdminEndpoints.java @@ -2,6 +2,9 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; import java.util.Arrays; @@ -18,6 +21,8 @@ import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails; import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordResourceDetails; import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.common.exceptions.InsufficientScopeException; +import org.springframework.security.oauth2.common.exceptions.UserDeniedAuthorizationException; /** * @author Dave Syer @@ -44,6 +49,7 @@ public void testListTokensByUser() throws Exception { public void testRevokeTokenByUser() throws Exception { OAuth2AccessToken token = context.getAccessToken(); + String tokenValueBeforeDeletion = token.getValue(); HttpHeaders headers = new HttpHeaders(); headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); @@ -55,11 +61,20 @@ public void testRevokeTokenByUser() throws Exception { .getRestTemplate() .exchange(serverRunning.getUrl("/sparklr2/oauth/users/{user}/tokens/{token}"), HttpMethod.DELETE, request, Void.class, "marissa", token.getValue()).getStatusCode()); - - ResponseEntity result = serverRunning.getForString("/sparklr2/oauth/users/marissa/tokens", headers); - assertEquals(HttpStatus.UNAUTHORIZED, result.getStatusCode()); - assertTrue(result.getBody().contains("invalid_token")); - + try { + // The request above will delete the oauth token so that the next request will initially fail. However, + // the failure will be detected and a new access token will be obtained. The new access token + // only has "write" scope and the requested resource needs "read" scope. So, an insufficient_scope + // exception should be thrown. + ResponseEntity result = serverRunning.getForString("/sparklr2/oauth/users/marissa/tokens", headers); + fail("Should have thrown an exception"); + } catch (InsufficientScopeException ex) { + assertEquals(HttpStatus.FORBIDDEN.value(), ex.getHttpErrorCode()); + assertEquals("insufficient_scope", ex.getOAuth2ErrorCode()); + String secondTokenWithWriteOnlyScope = context.getOAuth2ClientContext().getAccessToken().getValue(); + assertNotNull(secondTokenWithWriteOnlyScope); + assertFalse(secondTokenWithWriteOnlyScope.equals(tokenValueBeforeDeletion)); + } } @Test @@ -75,7 +90,13 @@ public void testClientListsTokensOfUser() throws Exception { @Test @OAuth2ContextConfiguration(ResourceOwnerReadOnly.class) public void testCannotListTokensOfAnotherUser() throws Exception { - assertEquals(HttpStatus.FORBIDDEN, serverRunning.getStatusCode("/sparklr2/oauth/users/foo/tokens")); + try { + serverRunning.getStatusCode("/sparklr2/oauth/users/foo/tokens"); + fail("Should have thrown an exception"); + } catch (UserDeniedAuthorizationException ex) { + // assertEquals(HttpStatus.FORBIDDEN.value(), ex.getHttpErrorCode()); + assertEquals("access_denied", ex.getOAuth2ErrorCode()); + } } @Test @@ -90,8 +111,13 @@ public void testListTokensByClient() throws Exception { @Test @OAuth2ContextConfiguration(ResourceOwnerReadOnly.class) public void testUserCannotListTokensOfClient() throws Exception { - assertEquals(HttpStatus.FORBIDDEN, - serverRunning.getStatusCode("/sparklr2/oauth/clients/my-client-with-registered-redirect/tokens")); + try { + serverRunning.getStatusCode("/sparklr2/oauth/clients/my-client-with-registered-redirect/tokens"); + fail("Should have thrown an exception"); + } catch (UserDeniedAuthorizationException ex) { + // assertEquals(HttpStatus.FORBIDDEN.value(), ex.getHttpErrorCode()); + assertEquals("access_denied", ex.getOAuth2ErrorCode()); + } } static class ResourceOwnerReadOnly extends ResourceOwnerPasswordResourceDetails { diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationCodeProvider.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationCodeProvider.java index b48408993..95c23ca3b 100755 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationCodeProvider.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationCodeProvider.java @@ -38,6 +38,7 @@ import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider; import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails; import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.common.exceptions.InsufficientScopeException; import org.springframework.security.oauth2.common.exceptions.RedirectMismatchException; import org.springframework.security.oauth2.common.util.OAuth2Utils; import org.springframework.security.oauth2.provider.ServerRunning.UriBuilder; @@ -309,12 +310,12 @@ public void testInsufficientScopeInResourceRequest() throws Exception { resource.setScope(Arrays.asList("trust")); approveAccessTokenGrant("http://anywhere/?key=value", true); assertNotNull(context.getAccessToken()); - ResponseEntity response = serverRunning.getForString("/sparklr2/photos?format=json"); - assertEquals(HttpStatus.FORBIDDEN, response.getStatusCode()); - String authenticate = response.getHeaders().getFirst("WWW-Authenticate"); - assertNotNull(authenticate); - assertTrue(authenticate.startsWith("Bearer")); - assertTrue("Wrong header: " + authenticate, authenticate.contains("scope=\"")); + try { + serverRunning.getForString("/sparklr2/photos?format=json"); + fail("Should have thrown exception"); + } catch (InsufficientScopeException ex) { + // ignore / all good + } } @Test From 102050681c16a36a50858336ac5060f58ab1db3f Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 5 Nov 2013 17:16:19 +0000 Subject: [PATCH 108/831] Revert Spring 4 change to RestTemplate The API changed slightly in the underlying library which is a nightmare. I think the current code now works with Spring 4 snapshots. --- .../oauth2/provider/ServerRunning.java | 58 +++++++++---------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ServerRunning.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ServerRunning.java index 78e7eaf96..6b26efd8f 100644 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ServerRunning.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ServerRunning.java @@ -11,10 +11,9 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.config.RequestConfig.Builder; -import org.apache.http.client.methods.HttpRequestBase; -import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.client.HttpClient; +import org.apache.http.client.params.ClientPNames; +import org.apache.http.client.params.CookiePolicy; import org.junit.Assume; import org.junit.internal.AssumptionViolatedException; import org.junit.rules.MethodRule; @@ -81,7 +80,7 @@ public class ServerRunning implements MethodRule, RestTemplateHolder { private String hostName = DEFAULT_HOST; private RestOperations client; - + /** * @return a new rule that assumes an existing running broker */ @@ -127,7 +126,8 @@ public Statement apply(final Statement base, FrameworkMethod method, Object targ // Check at the beginning, so this can be used as a static field if (assumeOnline) { Assume.assumeTrue(serverOnline.get(port)); - } else { + } + else { Assume.assumeTrue(serverOffline.get(port)); } @@ -139,14 +139,16 @@ public Statement apply(final Statement base, FrameworkMethod method, Object targ client.getForEntity(new UriTemplate(getUrl("/sparklr2/login.jsp")).toString(), String.class); online = true; logger.info("Basic connectivity test passed"); - } catch (RestClientException e) { + } + catch (RestClientException e) { logger.warn(String.format( "Not executing tests because basic connectivity test failed for hostName=%s, port=%d", hostName, port), e); if (assumeOnline) { Assume.assumeNoException(e); } - } finally { + } + finally { HttpURLConnection.setFollowRedirects(followRedirects); if (online) { serverOffline.put(port, false); @@ -154,13 +156,15 @@ public Statement apply(final Statement base, FrameworkMethod method, Object targ Assume.assumeTrue(serverOffline.get(port)); } - } else { + } + else { serverOnline.put(port, false); } } final RestOperations savedClient = getRestTemplate(); - postForStatus(savedClient, "/sparklr2/oauth/uncache_approvals", new LinkedMultiValueMap()); + postForStatus(savedClient, "/sparklr2/oauth/uncache_approvals", + new LinkedMultiValueMap()); return new Statement() { @@ -168,7 +172,8 @@ public Statement apply(final Statement base, FrameworkMethod method, Object targ public void evaluate() throws Throwable { try { base.evaluate(); - } finally { + } + finally { postForStatus(savedClient, "/sparklr2/oauth/cache_approvals", new LinkedMultiValueMap()); } @@ -177,7 +182,7 @@ public void evaluate() throws Throwable { }; } - + public String getBaseUrl() { return "http://" + hostName + ":" + port; } @@ -240,7 +245,7 @@ private ResponseEntity postForStatus(RestOperations client, String path, H actualHeaders.putAll(headers); actualHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED); return client.exchange(getUrl(path), HttpMethod.POST, new HttpEntity>(formData, - actualHeaders), (Class) null); + actualHeaders), (Class)null); } public ResponseEntity postForRedirect(String path, HttpHeaders headers, MultiValueMap params) { @@ -257,7 +262,7 @@ public ResponseEntity postForRedirect(String path, HttpHeaders headers, Mu String location = exchange.getHeaders().getLocation().toString(); - return client.exchange(location, HttpMethod.GET, new HttpEntity(null, headers), (Class) null); + return client.exchange(location, HttpMethod.GET, new HttpEntity(null, headers), (Class)null); } public ResponseEntity getForString(String path) { @@ -275,7 +280,7 @@ public ResponseEntity getForString(String path, final HttpHeaders header public ResponseEntity getForResponse(String path, final HttpHeaders headers, Map uriVariables) { HttpEntity request = new HttpEntity(null, headers); - return client.exchange(getUrl(path), HttpMethod.GET, request, (Class) null, uriVariables); + return client.exchange(getUrl(path), HttpMethod.GET, request, (Class)null, uriVariables); } public ResponseEntity getForResponse(String path, HttpHeaders headers) { @@ -298,24 +303,16 @@ public void setRestTemplate(RestOperations restTemplate) { public RestOperations getRestTemplate() { return client; } - + public RestOperations createRestTemplate() { RestTemplate client = new RestTemplate(); client.setRequestFactory(new HttpComponentsClientHttpRequestFactory() { @Override - protected HttpUriRequest createHttpUriRequest(HttpMethod httpMethod, URI uri) { - HttpUriRequest request = super.createHttpUriRequest(httpMethod, uri); - if (request instanceof HttpRequestBase) { - HttpRequestBase base = (HttpRequestBase) request; - Builder builder = RequestConfig.custom(); - if (base.getConfig()!=null) { - builder = RequestConfig.copy(base.getConfig()); - } - RequestConfig config = builder.setRedirectsEnabled(false) - .setCookieSpec("ignoreCookies").build(); - base.setConfig(config); - } - return request; + public HttpClient getHttpClient() { + HttpClient client = super.getHttpClient(); + client.getParams().setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, false); + client.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.IGNORE_COOKIES); + return client; } }); client.setErrorHandler(new ResponseErrorHandler() { @@ -363,7 +360,8 @@ public String pattern() { for (String key : params.keySet()) { if (!first) { builder.append("&"); - } else { + } + else { first = false; } String value = params.get(key); From f3ebc49f93e107a4bc0ed5bdf045c2deba67b865 Mon Sep 17 00:00:00 2001 From: Amanda Anganes Date: Tue, 3 Sep 2013 16:31:19 -0400 Subject: [PATCH 109/831] Changed signature of request validator validateScope() method - now takes in two sets, one of the request scope and one of the client scope --- .../provider/DefaultOAuth2RequestValidator.java | 15 ++++++--------- .../oauth2/provider/OAuth2RequestValidator.java | 2 +- .../provider/endpoint/AuthorizationEndpoint.java | 3 +-- .../oauth2/provider/endpoint/TokenEndpoint.java | 7 ++++--- 4 files changed, 12 insertions(+), 15 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestValidator.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestValidator.java index d1a5e6226..457dfa08b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestValidator.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestValidator.java @@ -1,10 +1,8 @@ package org.springframework.security.oauth2.provider; -import java.util.Map; import java.util.Set; import org.springframework.security.oauth2.common.exceptions.InvalidScopeException; -import org.springframework.security.oauth2.common.util.OAuth2Utils; /** * Default implementation of {@link OAuth2RequestValidator}. @@ -15,13 +13,12 @@ public class DefaultOAuth2RequestValidator implements OAuth2RequestValidator { - public void validateScope(Map parameters, Set clientScopes) { - if (parameters.containsKey("scope")) { - if (clientScopes != null && !clientScopes.isEmpty()) { - for (String scope : OAuth2Utils.parseParameterList(parameters.get("scope"))) { - if (!clientScopes.contains(scope)) { - throw new InvalidScopeException("Invalid scope: " + scope, clientScopes); - } + public void validateScope(Set requestScopes, Set clientScopes) { + + if (clientScopes != null && !clientScopes.isEmpty()) { + for (String scope : requestScopes) { + if (!clientScopes.contains(scope)) { + throw new InvalidScopeException("Invalid scope: " + scope, clientScopes); } } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestValidator.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestValidator.java index 3330f033e..eeadbc9ac 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestValidator.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestValidator.java @@ -20,6 +20,6 @@ public interface OAuth2RequestValidator { * @param clientScopes the requesting client's registered, allowed scopes * @throws InvalidScopeException if a requested scope is invalid */ - public void validateScope(Map parameters, Set clientScopes) throws InvalidScopeException; + public void validateScope(Set requestScopes, Set clientScopes) throws InvalidScopeException; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java index da3800429..45044d61d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java @@ -160,8 +160,7 @@ public ModelAndView authorize(Map model, @RequestParam Map getAccessToken(Principal principal, String clientId = getClientId(principal); ClientDetails client = getClientDetailsService().loadClientByClientId(clientId); HashMap map = new HashMap(parameters); + + TokenRequest tokenRequest = getOAuth2RequestFactory().createTokenRequest(map); + if (clientId != null) { map.put(OAuth2Utils.CLIENT_ID, clientId); // Only validate the client details if a client authenticated during this // request. if (client != null) { - oAuth2RequestValidator.validateScope(map, client.getScope()); + oAuth2RequestValidator.validateScope(tokenRequest.getScope(), client.getScope()); } } - TokenRequest tokenRequest = getOAuth2RequestFactory().createTokenRequest(map); - if (!StringUtils.hasText(tokenRequest.getGrantType())) { throw new InvalidRequestException("Missing grant type"); } From ed5a49b8cd0423c05b2ecc80b683c4b691cdb7a4 Mon Sep 17 00:00:00 2001 From: Amanda Anganes Date: Tue, 24 Sep 2013 15:25:02 -0400 Subject: [PATCH 110/831] Made two validateScope() methods, one for the AuthorzationEndpoint and one for the TokenEndpoint. --- .../DefaultOAuth2RequestValidator.java | 9 ++++++++- .../provider/OAuth2RequestValidator.java | 20 +++++++++++++------ .../endpoint/AuthorizationEndpoint.java | 2 +- .../provider/endpoint/TokenEndpoint.java | 2 +- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestValidator.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestValidator.java index 457dfa08b..445408ddf 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestValidator.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestValidator.java @@ -12,8 +12,15 @@ */ public class DefaultOAuth2RequestValidator implements OAuth2RequestValidator { + public void validateScope(AuthorizationRequest authorizationRequest, ClientDetails client) throws InvalidScopeException { + validateScope(authorizationRequest.getScope(), client.getScope()); + } + + public void validateScope(TokenRequest tokenRequest, ClientDetails client) throws InvalidScopeException { + validateScope(tokenRequest.getScope(), client.getScope()); + } - public void validateScope(Set requestScopes, Set clientScopes) { + private void validateScope(Set requestScopes, Set clientScopes) { if (clientScopes != null && !clientScopes.isEmpty()) { for (String scope : requestScopes) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestValidator.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestValidator.java index eeadbc9ac..b88a765bf 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestValidator.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestValidator.java @@ -1,9 +1,8 @@ package org.springframework.security.oauth2.provider; -import java.util.Map; -import java.util.Set; - import org.springframework.security.oauth2.common.exceptions.InvalidScopeException; +import org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint; +import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint; /** * Validation interface for OAuth2 requests to the {@link AuthorizationEndpoint} and {@link TokenEndpoint}. @@ -16,10 +15,19 @@ public interface OAuth2RequestValidator { /** * Ensure that the client has requested a valid set of scopes. * - * @param parameters the parameters on the request, including scope - * @param clientScopes the requesting client's registered, allowed scopes + * @param authorizationRequest the AuthorizationRequest to be validated + * @param client the client that is making the request + * @throws InvalidScopeException if a requested scope is invalid + */ + public void validateScope(AuthorizationRequest authorizationRequest, ClientDetails client) throws InvalidScopeException; + + /** + * Ensure that the client has requested a valid set of scopes. + * + * @param tokenRequest the TokenRequest to be validated + * @param client the client that is making the request * @throws InvalidScopeException if a requested scope is invalid */ - public void validateScope(Set requestScopes, Set clientScopes) throws InvalidScopeException; + public void validateScope(TokenRequest tokenRequest, ClientDetails client) throws InvalidScopeException; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java index 45044d61d..04bd2585e 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java @@ -160,7 +160,7 @@ public ModelAndView authorize(Map model, @RequestParam Map getAccessToken(Principal principal, // Only validate the client details if a client authenticated during this // request. if (client != null) { - oAuth2RequestValidator.validateScope(tokenRequest.getScope(), client.getScope()); + oAuth2RequestValidator.validateScope(tokenRequest, client); } } if (!StringUtils.hasText(tokenRequest.getGrantType())) { From aa1c5aa41eef594a065d59a27031e8809cef43d5 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Wed, 9 Oct 2013 13:24:35 -0400 Subject: [PATCH 111/831] set the client ID on the token request from the principal, if needed --- .../oauth2/provider/endpoint/TokenEndpoint.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java index 7491744b3..941a12611 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java @@ -28,6 +28,7 @@ import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.exceptions.BadClientCredentialsException; +import org.springframework.security.oauth2.common.exceptions.InvalidClientException; import org.springframework.security.oauth2.common.exceptions.InvalidRequestException; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.common.exceptions.UnsupportedGrantTypeException; @@ -75,14 +76,20 @@ public ResponseEntity getAccessToken(Principal principal, "There is no client authentication. Try adding an appropriate authentication filter."); } + String clientId = getClientId(principal); ClientDetails client = getClientDetailsService().loadClientByClientId(clientId); - HashMap map = new HashMap(parameters); - - TokenRequest tokenRequest = getOAuth2RequestFactory().createTokenRequest(map); + + TokenRequest tokenRequest = getOAuth2RequestFactory().createTokenRequest(parameters); + + if (tokenRequest.getClientId() == null) { + // if the client ID wasn't discovered from the parameters map, add it from the principal + tokenRequest.setClientId(clientId); + } else if (tokenRequest.getClientId().equals(clientId)) { + throw new InvalidClientException("Given client ID does not match authenticated client"); + } if (clientId != null) { - map.put(OAuth2Utils.CLIENT_ID, clientId); // Only validate the client details if a client authenticated during this // request. if (client != null) { From 4f5bf9415052c9e896006617b24ea533485e1202 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Tue, 5 Nov 2013 17:35:21 -0800 Subject: [PATCH 112/831] added in ClientDetails reference to createTokenRequest to allow loading of client_id parameter from authenticated client in addition to or in lieu of parameter request --- .../provider/DefaultOAuth2RequestFactory.java | 12 +++++++++++- .../oauth2/provider/OAuth2RequestFactory.java | 3 ++- .../oauth2/provider/endpoint/TokenEndpoint.java | 14 ++++++-------- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestFactory.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestFactory.java index 93cf01f95..e1093a4d2 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestFactory.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestFactory.java @@ -16,6 +16,7 @@ import java.util.Map; import java.util.Set; +import org.springframework.security.oauth2.common.exceptions.InvalidClientException; import org.springframework.security.oauth2.common.util.OAuth2Utils; /** @@ -64,9 +65,18 @@ public OAuth2Request createOAuth2Request(AuthorizationRequest request) { return request.createOAuth2Request(); } - public TokenRequest createTokenRequest(Map requestParameters) { + public TokenRequest createTokenRequest(Map requestParameters, ClientDetails authenticatedClient) { String clientId = requestParameters.get(OAuth2Utils.CLIENT_ID); + if (clientId == null) { + // if the clientId wasn't passed in in the map, we add pull it from the authenticated client object + clientId = authenticatedClient.getClientId(); + } else { + // otherwise, make sure that they match + if (!clientId.equals(authenticatedClient.getClientId())) { + throw new InvalidClientException("Given client ID does not match authenticated client"); + } + } Set scopes = OAuth2Utils.parseParameterList(requestParameters.get(OAuth2Utils.SCOPE)); String grantType = requestParameters.get(OAuth2Utils.GRANT_TYPE); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestFactory.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestFactory.java index 84315ddae..d98418ab2 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestFactory.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestFactory.java @@ -63,9 +63,10 @@ public interface OAuth2RequestFactory { * Create a new {@link TokenRequest} by extracting the needed information from the incoming request parameter map. * * @param requestParameters the parameters in the request + * @param authenticatedClient the client that authenticated during the token request * @return a new TokenRequest */ - TokenRequest createTokenRequest(Map requestParameters); + TokenRequest createTokenRequest(Map requestParameters, ClientDetails authenticatedClient); /** * Create a new {@link TokenRequest} from an {@link AuthorizationRequest}. Principally used by the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java index 941a12611..2a8e5afa3 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java @@ -78,22 +78,20 @@ public ResponseEntity getAccessToken(Principal principal, String clientId = getClientId(principal); - ClientDetails client = getClientDetailsService().loadClientByClientId(clientId); + ClientDetails authenticatedClient = getClientDetailsService().loadClientByClientId(clientId); - TokenRequest tokenRequest = getOAuth2RequestFactory().createTokenRequest(parameters); + TokenRequest tokenRequest = getOAuth2RequestFactory().createTokenRequest(parameters, authenticatedClient); - if (tokenRequest.getClientId() == null) { - // if the client ID wasn't discovered from the parameters map, add it from the principal - tokenRequest.setClientId(clientId); - } else if (tokenRequest.getClientId().equals(clientId)) { + if (!tokenRequest.getClientId().equals(clientId)) { + // double check to make sure that the client ID in the token request is the same as that in the authenticated client throw new InvalidClientException("Given client ID does not match authenticated client"); } if (clientId != null) { // Only validate the client details if a client authenticated during this // request. - if (client != null) { - oAuth2RequestValidator.validateScope(tokenRequest, client); + if (authenticatedClient != null) { + oAuth2RequestValidator.validateScope(tokenRequest, authenticatedClient); } } if (!StringUtils.hasText(tokenRequest.getGrantType())) { From 37f2db09b35c0c6186218406815601b48bd57a88 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Tue, 5 Nov 2013 18:18:54 -0800 Subject: [PATCH 113/831] moved double check inside null safe test --- .../security/oauth2/provider/endpoint/TokenEndpoint.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java index 2a8e5afa3..b3722722e 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java @@ -82,14 +82,14 @@ public ResponseEntity getAccessToken(Principal principal, TokenRequest tokenRequest = getOAuth2RequestFactory().createTokenRequest(parameters, authenticatedClient); - if (!tokenRequest.getClientId().equals(clientId)) { - // double check to make sure that the client ID in the token request is the same as that in the authenticated client - throw new InvalidClientException("Given client ID does not match authenticated client"); - } if (clientId != null) { // Only validate the client details if a client authenticated during this // request. + if (!tokenRequest.getClientId().equals(clientId)) { + // double check to make sure that the client ID in the token request is the same as that in the authenticated client + throw new InvalidClientException("Given client ID does not match authenticated client"); + } if (authenticatedClient != null) { oAuth2RequestValidator.validateScope(tokenRequest, authenticatedClient); } From 76b6b2889463f5e3b7abdaa27c47fcbd6aad2ce0 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Wed, 6 Nov 2013 07:33:58 -0800 Subject: [PATCH 114/831] Fixed unit tests and changed how the clientId tests are performed in token endpoint --- .../oauth2/provider/endpoint/TokenEndpoint.java | 4 ++-- .../code/TestAuthorizationCodeTokenGranter.java | 10 +++++----- .../oauth2/provider/endpoint/TestTokenEndpoint.java | 7 ++++--- .../TestResourceOwnerPasswordTokenGranter.java | 9 +++++++-- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java index b3722722e..b5c6d4bc7 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java @@ -83,10 +83,10 @@ public ResponseEntity getAccessToken(Principal principal, TokenRequest tokenRequest = getOAuth2RequestFactory().createTokenRequest(parameters, authenticatedClient); - if (clientId != null) { + if (clientId != null && !clientId.equals("")) { // Only validate the client details if a client authenticated during this // request. - if (!tokenRequest.getClientId().equals(clientId)) { + if (!clientId.equals(tokenRequest.getClientId())) { // double check to make sure that the client ID in the token request is the same as that in the authenticated client throw new InvalidClientException("Given client ID does not match authenticated client"); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeTokenGranter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeTokenGranter.java index 1b59691c3..242501eb7 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeTokenGranter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeTokenGranter.java @@ -85,7 +85,7 @@ public void testAuthorizationCodeGrant() { parameters.putAll(storedOAuth2Request.getRequestParameters()); parameters.put("code", code); - TokenRequest tokenRequest = requestFactory.createTokenRequest(parameters); + TokenRequest tokenRequest = requestFactory.createTokenRequest(parameters, client); AuthorizationCodeTokenGranter granter = new AuthorizationCodeTokenGranter(providerTokenServices, authorizationCodeServices, clientDetailsService, requestFactory); @@ -108,7 +108,7 @@ public void testAuthorizationParametersPreserved() { storedOAuth2Request, userAuthentication)); parameters.put("code", code); - TokenRequest tokenRequest = requestFactory.createTokenRequest(parameters); + TokenRequest tokenRequest = requestFactory.createTokenRequest(parameters, client); AuthorizationCodeTokenGranter granter = new AuthorizationCodeTokenGranter(providerTokenServices, authorizationCodeServices, clientDetailsService, requestFactory); @@ -133,7 +133,7 @@ public void testAuthorizationRequestPreserved() { storedOAuth2Request, userAuthentication)); parameters.put("code", code); - TokenRequest tokenRequest = requestFactory.createTokenRequest(parameters); + TokenRequest tokenRequest = requestFactory.createTokenRequest(parameters, client); AuthorizationCodeTokenGranter granter = new AuthorizationCodeTokenGranter(providerTokenServices, authorizationCodeServices, clientDetailsService, requestFactory); @@ -158,7 +158,7 @@ public void testAuthorizationCodeGrantWithNoClientAuthorities() { String code = authorizationCodeServices.createAuthorizationCode(new OAuth2Authentication( storedOAuth2Request, userAuthentication)); parameters.put("code", code); - TokenRequest tokenRequest = requestFactory.createTokenRequest(parameters); + TokenRequest tokenRequest = requestFactory.createTokenRequest(parameters, client); AuthorizationCodeTokenGranter granter = new AuthorizationCodeTokenGranter(providerTokenServices, authorizationCodeServices, clientDetailsService, requestFactory); OAuth2AccessToken token = granter.grant("authorization_code", tokenRequest); @@ -189,7 +189,7 @@ public void testAuthorizationRedirectMismatch() { //AuthorizationRequest oAuth2Request = createFromParameters(initialParameters); //oAuth2Request.setRequestParameters(authorizationParameters); - TokenRequest tokenRequest = requestFactory.createTokenRequest(parameters); + TokenRequest tokenRequest = requestFactory.createTokenRequest(parameters, client); tokenRequest.setRequestParameters(authorizationParameters); AuthorizationCodeTokenGranter granter = new AuthorizationCodeTokenGranter(providerTokenServices, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestTokenEndpoint.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestTokenEndpoint.java index 7acaea2cb..1911ff0f7 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestTokenEndpoint.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestTokenEndpoint.java @@ -39,6 +39,7 @@ import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.util.OAuth2Utils; import org.springframework.security.oauth2.provider.BaseClientDetails; +import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; import org.springframework.security.oauth2.provider.TokenGranter; @@ -82,7 +83,7 @@ public void testGetAccessTokenWithNoClientId() { expectedToken); @SuppressWarnings("unchecked") Map anyMap = Mockito.any(Map.class); - when(authorizationRequestFactory.createTokenRequest(anyMap)).thenReturn(createFromParameters(parameters)); + when(authorizationRequestFactory.createTokenRequest(anyMap, Mockito.any(ClientDetails.class))).thenReturn(createFromParameters(parameters)); ResponseEntity response = endpoint.getAccessToken(new UsernamePasswordAuthenticationToken( null, null, Collections.singleton(new SimpleGrantedAuthority("ROLE_CLIENT"))), parameters); @@ -120,10 +121,10 @@ public void testGetAccessTokenWithScope() { when(tokenGranter.grant(Mockito.eq("authorization_code"), captor2.capture())).thenReturn(expectedToken); @SuppressWarnings("unchecked") Map anyMap = Mockito.any(Map.class); - when(authorizationRequestFactory.createTokenRequest(anyMap)).thenReturn(createFromParameters(parameters)); + when(authorizationRequestFactory.createTokenRequest(anyMap, Mockito.eq(clientDetails))).thenReturn(createFromParameters(parameters)); ResponseEntity response = endpoint.getAccessToken(new UsernamePasswordAuthenticationToken( - null, null, Collections.singleton(new SimpleGrantedAuthority("ROLE_CLIENT"))), parameters); + clientId, null, Collections.singleton(new SimpleGrantedAuthority("ROLE_CLIENT"))), parameters); assertNotNull(response); assertEquals(HttpStatus.OK, response.getStatusCode()); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/TestResourceOwnerPasswordTokenGranter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/TestResourceOwnerPasswordTokenGranter.java index acf51aefb..fb58cf3bf 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/TestResourceOwnerPasswordTokenGranter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/TestResourceOwnerPasswordTokenGranter.java @@ -67,12 +67,17 @@ public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exceptio private TokenRequest tokenRequest; public TestResourceOwnerPasswordTokenGranter() { + String clientId = "client"; + BaseClientDetails clientDetails = new BaseClientDetails(); + clientDetails.setClientId(clientId); + providerTokenServices.setTokenStore(new InMemoryTokenStore()); Map parameters = new HashMap(); parameters.put("username", "foo"); parameters.put("password", "bar"); - parameters.put("client_id", "client"); - tokenRequest = requestFactory.createTokenRequest(parameters); + parameters.put("client_id", clientId); + + tokenRequest = requestFactory.createTokenRequest(parameters, clientDetails); } @Test From 4e5e9e71a4ff057c8de8747634bcd088e2335452 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 7 Nov 2013 08:54:39 +0000 Subject: [PATCH 115/831] Remove unused imports --- .../security/oauth2/provider/endpoint/TokenEndpoint.java | 1 - 1 file changed, 1 deletion(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java index b5c6d4bc7..8a406bfec 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java @@ -18,7 +18,6 @@ import java.security.Principal; import java.util.Collections; -import java.util.HashMap; import java.util.Map; import org.springframework.http.HttpHeaders; From 52421af2dcaf61ca8335cfca7e5f83c359c2e7af Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 7 Nov 2013 09:24:31 +0000 Subject: [PATCH 116/831] Bump version 1.1 => 2.0 --- pom.xml | 2 +- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- .../oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- .../src/main/resources/META-INF/spring.schemas | 4 ++-- ...security-oauth2-1.1.xsd => spring-security-oauth2-2.0.xsd} | 0 .../security/oauth2/provider/token/TestJwtTokenServices.java | 1 + .../security/oauth2/config/authorization-server-extras.xml | 3 +-- 13 files changed, 13 insertions(+), 13 deletions(-) rename spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/{spring-security-oauth2-1.1.xsd => spring-security-oauth2-2.0.xsd} (100%) diff --git a/pom.xml b/pom.xml index ea52eebc6..c2a5ac5ed 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ OAuth for Spring Security Parent Project for OAuth Support for Spring Security pom - 1.1.0.BUILD-SNAPSHOT + 2.0.0.BUILD-SNAPSHOT http://static.springframework.org/spring-security/oauth diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index d737c63c9..4ca71dec4 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 - 1.1.0.BUILD-SNAPSHOT + 2.0.0.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index 485eaf1fe..439d42eca 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 - 1.1.0.BUILD-SNAPSHOT + 2.0.0.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 9210ae0d3..46b3ccad1 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 - 1.1.0.BUILD-SNAPSHOT + 2.0.0.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml index c01cddab3..0b7afa3db 100644 --- a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml +++ b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml @@ -3,7 +3,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:oauth="http://www.springframework.org/schema/security/oauth2" xmlns:sec="http://www.springframework.org/schema/security" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" - xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2%20http://www.springframework.org/schema/security/spring-security-oauth2-1.1.xsd+xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index d12687aac..6d56de571 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 1.1.0.BUILD-SNAPSHOT + 2.0.0.BUILD-SNAPSHOT ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index 643c02272..d88a907a1 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 1.1.0.BUILD-SNAPSHOT + 2.0.0.BUILD-SNAPSHOT spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index edbd3c2a3..a27b2425f 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 - 1.1.0.BUILD-SNAPSHOT + 2.0.0.BUILD-SNAPSHOT spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 1bb803bdc..439ab24dd 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 - 1.1.0.BUILD-SNAPSHOT + 2.0.0.BUILD-SNAPSHOT spring-security-oauth2 diff --git a/spring-security-oauth2/src/main/resources/META-INF/spring.schemas b/spring-security-oauth2/src/main/resources/META-INF/spring.schemas index 206973acf..eead4cac7 100644 --- a/spring-security-oauth2/src/main/resources/META-INF/spring.schemas +++ b/spring-security-oauth2/src/main/resources/META-INF/spring.schemas @@ -1,3 +1,3 @@ http\://www.springframework.org/schema/security/spring-security-oauth2-1.0.xsd=org/springframework/security/oauth2/spring-security-oauth2-1.0.xsd -http\://www.springframework.org/schema/security/spring-security-oauth2-1.1.xsd=org/springframework/security/oauth2/spring-security-oauth2-1.1.xsd -http\://www.springframework.org/schema/security/spring-security-oauth2.xsd=org/springframework/security/oauth2/spring-security-oauth2-1.1.xsd \ No newline at end of file +http\://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd=org/springframework/security/oauth2/spring-security-oauth2-2.0.xsd +http\://www.springframework.org/schema/security/spring-security-oauth2.xsd=org/springframework/security/oauth2/spring-security-oauth2-2.0.xsd \ No newline at end of file diff --git a/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.1.xsd b/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-2.0.xsd similarity index 100% rename from spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.1.xsd rename to spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-2.0.xsd diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJwtTokenServices.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJwtTokenServices.java index b0968d932..fd842dc19 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJwtTokenServices.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJwtTokenServices.java @@ -187,6 +187,7 @@ public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exceptio @Test public void testOneAccessTokenPerAuthentication() throws Exception { OAuth2Authentication authentication = createAuthentication(); + // TODO: occasionally fails because expiry time is different (millis) OAuth2AccessToken first = services.createAccessToken(authentication); OAuth2AccessToken second = services.createAccessToken(authentication); assertEquals(first, second); diff --git a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/authorization-server-extras.xml b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/authorization-server-extras.xml index f73f259dd..acff75874 100644 --- a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/authorization-server-extras.xml +++ b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/authorization-server-extras.xml @@ -1,8 +1,7 @@ - Date: Mon, 18 Nov 2013 08:39:19 +0000 Subject: [PATCH 117/831] SECOAUTH-414: metion error handling options in docs --- docs/oauth2.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/oauth2.md b/docs/oauth2.md index 722960554..94cee73eb 100644 --- a/docs/oauth2.md +++ b/docs/oauth2.md @@ -41,9 +41,8 @@ The provider role in OAuth 2.0 is actually split between Authorization Service a * [`AuthorizationEndpoint`][AuthorizationEndpoint] is used to service requests for authorization. Default URL: `/oauth/authorize`. * [`TokenEndpoint`][TokenEndpoint] is used to service requests for access tokens. Default URL: `/oauth/token`. -The following filters are required to implement an OAuth 2.0 Resource Server: +The following filteris required to implement an OAuth 2.0 Resource Server: -* The [`OAuth2ExceptionHandlerFilter`][OAuth2ExceptionHandlerFilter] is used to handle any errors. * The [`OAuth2AuthenticationProcessingFilter`][OAuth2AuthenticationProcessingFilter] is used to load the Authentication for the request given an authenticated access token. For all the OAuth 2.0 provider features, configuration is simplified using the custom spring configuration elements. The schema for these elements rests at [http://www.springframework.org/schema/security/spring-security-oauth2.xsd][oauth2.xsd]. The namespace is `http://www.springframework.org/schema/security/oauth2`. @@ -112,6 +111,10 @@ You may want to take advantage of Spring Security's [expression-based access con The expressions include _oauth2.clientHasRole_, _oauth2.clientHasAnyRole_, and _oath2.denyClient_ which can be used to provide access based on the role of the oauth client. +## Customizing the Error Handling + +Error handling in an Authorization Server uses standard Spring MVC features, namely `@ExceptionHandler` methods in the endpoints themselves that delegate the rendering of exceptions to `HttpMesssageConverters` (which can be added to the MVC configuration). Users can also provide a `WebResponseExceptionTranslator` to the endpoints themselves which is the best way to change the content of the responses as opposed to the way they are rendered. + ## Resource Server Configuration You need to supply the `` element with an `id` attribute - this is the bean id for a servlet `Filter` that can be added to the standard Spring Security chain, e.g. @@ -195,7 +198,6 @@ Facebook token responses also contain a non-compliant JSON entry for the expiry [InMemoryClientDetailsService]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/InMemoryClientDetailsService.html "InMemoryClientDetailsService" [BaseClientDetails]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/BaseClientDetails.html "BaseClientDetails" [AuthorizationServerTokenServices]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/token/AuthorizationServerTokenServices.html "AuthorizationServerTokenServices" - [OAuth2ExceptionHandlerFilter]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/filter/OAuth2ExceptionHandlerFilter.html "OAuth2ExceptionHandlerFilter" [OAuth2AuthenticationProcessingFilter]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/filter/OAuth2AuthenticationProcessingFilter.html "OAuth2AuthenticationProcessingFilter" [oauth2.xsd]: http://www.springframework.org/schema/security/spring-security-oauth2.xsd "oauth2.xsd" [expressions]: http://static.springsource.org/spring-security/site/docs/3.0.x/reference/el-access.html "Expression Access Control" From cdd0e38d12f2911941807531799d33b8341f41f2 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 18 Nov 2013 09:06:19 +0000 Subject: [PATCH 118/831] SECOAUTH-408: deny /token requests with grant_type=implicit --- .../provider/endpoint/TokenEndpoint.java | 29 +++---- .../provider/endpoint/TestTokenEndpoint.java | 77 ++++++++++++------- 2 files changed, 65 insertions(+), 41 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java index 8a406bfec..9442a15ac 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java @@ -28,6 +28,7 @@ import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.exceptions.BadClientCredentialsException; import org.springframework.security.oauth2.common.exceptions.InvalidClientException; +import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; import org.springframework.security.oauth2.common.exceptions.InvalidRequestException; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.common.exceptions.UnsupportedGrantTypeException; @@ -49,7 +50,7 @@ * parameter (e.g. "authorization_code") and other parameters as determined by the grant type. Supported grant types are * handled by the provided {@link #setTokenGranter(org.springframework.security.oauth2.provider.TokenGranter) token * granter}. - *

+ *

* *

* Clients must be authenticated using a Spring Security {@link Authentication} to access this endpoint, and the client @@ -64,29 +65,28 @@ @RequestMapping(value = "/oauth/token") public class TokenEndpoint extends AbstractEndpoint { - private OAuth2RequestValidator oAuth2RequestValidator = new DefaultOAuth2RequestValidator(); - + private OAuth2RequestValidator oAuth2RequestValidator = new DefaultOAuth2RequestValidator(); + @RequestMapping - public ResponseEntity getAccessToken(Principal principal, - @RequestParam Map parameters) { + public ResponseEntity getAccessToken(Principal principal, @RequestParam + Map parameters) { if (!(principal instanceof Authentication)) { throw new InsufficientAuthenticationException( "There is no client authentication. Try adding an appropriate authentication filter."); } - String clientId = getClientId(principal); ClientDetails authenticatedClient = getClientDetailsService().loadClientByClientId(clientId); - + TokenRequest tokenRequest = getOAuth2RequestFactory().createTokenRequest(parameters, authenticatedClient); - - + if (clientId != null && !clientId.equals("")) { // Only validate the client details if a client authenticated during this // request. if (!clientId.equals(tokenRequest.getClientId())) { - // double check to make sure that the client ID in the token request is the same as that in the authenticated client + // double check to make sure that the client ID in the token request is the same as that in the + // authenticated client throw new InvalidClientException("Given client ID does not match authenticated client"); } if (authenticatedClient != null) { @@ -96,6 +96,9 @@ public ResponseEntity getAccessToken(Principal principal, if (!StringUtils.hasText(tokenRequest.getGrantType())) { throw new InvalidRequestException("Missing grant type"); } + if (tokenRequest.getGrantType().equals("implicit")) { + throw new InvalidGrantException("Implicit grant type not supported from token endpoint"); + } if (isAuthCodeRequest(parameters) || isRefreshTokenRequest(parameters)) { // The scope was requested or determined during the authorization step @@ -104,12 +107,12 @@ public ResponseEntity getAccessToken(Principal principal, tokenRequest.setScope(Collections. emptySet()); } } - + if (isRefreshTokenRequest(parameters)) { // A refresh token has its own default scopes, so we should ignore any added by the factory here. tokenRequest.setScope(OAuth2Utils.parseParameterList(parameters.get(OAuth2Utils.SCOPE))); } - + OAuth2AccessToken token = getTokenGranter().grant(tokenRequest.getGrantType(), tokenRequest); if (token == null) { throw new UnsupportedGrantTypeException("Unsupported grant type: " + tokenRequest.getGrantType()); @@ -162,7 +165,7 @@ private boolean isRefreshTokenRequest(Map parameters) { private boolean isAuthCodeRequest(Map parameters) { return "authorization_code".equals(parameters.get("grant_type")) && parameters.get("code") != null; } - + public void setoAuth2RequestValidator(OAuth2RequestValidator oAuth2RequestValidator) { this.oAuth2RequestValidator = oAuth2RequestValidator; } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestTokenEndpoint.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestTokenEndpoint.java index 1911ff0f7..58092cb68 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestTokenEndpoint.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestTokenEndpoint.java @@ -21,10 +21,12 @@ import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.when; +import java.security.Principal; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; @@ -37,6 +39,7 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; import org.springframework.security.oauth2.common.util.OAuth2Utils; import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.ClientDetails; @@ -60,20 +63,33 @@ public class TestTokenEndpoint { @Mock private ClientDetailsService clientDetailsService; - + + private String clientId = "client"; + private BaseClientDetails clientDetails = new BaseClientDetails(); + + private TokenEndpoint endpoint; + + private Principal clientAuthentication = new UsernamePasswordAuthenticationToken("client", null, + Collections.singleton(new SimpleGrantedAuthority("ROLE_CLIENT"))); + private TokenRequest createFromParameters(Map parameters) { - TokenRequest request = new TokenRequest(parameters, parameters.get(OAuth2Utils.CLIENT_ID), - OAuth2Utils.parseParameterList(parameters.get(OAuth2Utils.SCOPE)), parameters.get(OAuth2Utils.GRANT_TYPE)); + TokenRequest request = new TokenRequest(parameters, parameters.get(OAuth2Utils.CLIENT_ID), + OAuth2Utils.parseParameterList(parameters.get(OAuth2Utils.SCOPE)), + parameters.get(OAuth2Utils.GRANT_TYPE)); return request; } - - @Test - public void testGetAccessTokenWithNoClientId() { - TokenEndpoint endpoint = new TokenEndpoint(); + @Before + public void init() { + endpoint = new TokenEndpoint(); endpoint.setTokenGranter(tokenGranter); endpoint.setOAuth2RequestFactory(authorizationRequestFactory); endpoint.setClientDetailsService(clientDetailsService); + clientDetails.setClientId(clientId); + } + + @Test + public void testGetAccessTokenWithNoClientId() { HashMap parameters = new HashMap(); parameters.put(OAuth2Utils.GRANT_TYPE, "authorization_code"); @@ -83,10 +99,12 @@ public void testGetAccessTokenWithNoClientId() { expectedToken); @SuppressWarnings("unchecked") Map anyMap = Mockito.any(Map.class); - when(authorizationRequestFactory.createTokenRequest(anyMap, Mockito.any(ClientDetails.class))).thenReturn(createFromParameters(parameters)); - - ResponseEntity response = endpoint.getAccessToken(new UsernamePasswordAuthenticationToken( - null, null, Collections.singleton(new SimpleGrantedAuthority("ROLE_CLIENT"))), parameters); + when(authorizationRequestFactory.createTokenRequest(anyMap, Mockito.any(ClientDetails.class))).thenReturn( + createFromParameters(parameters)); + + clientAuthentication = new UsernamePasswordAuthenticationToken(null, null, + Collections.singleton(new SimpleGrantedAuthority("ROLE_CLIENT"))); + ResponseEntity response = endpoint.getAccessToken(clientAuthentication, parameters); assertNotNull(response); assertEquals(HttpStatus.OK, response.getStatusCode()); @@ -98,16 +116,7 @@ public void testGetAccessTokenWithNoClientId() { @Test public void testGetAccessTokenWithScope() { - String clientId = "client"; - BaseClientDetails clientDetails = new BaseClientDetails(); - clientDetails.setClientId(clientId); - when(clientDetailsService.loadClientByClientId(clientId)).thenReturn(clientDetails); - - TokenEndpoint endpoint = new TokenEndpoint(); - endpoint.setTokenGranter(tokenGranter); - endpoint.setOAuth2RequestFactory(authorizationRequestFactory); - endpoint.setClientDetailsService(clientDetailsService); HashMap parameters = new HashMap(); parameters.put("client_id", clientId); @@ -116,22 +125,34 @@ public void testGetAccessTokenWithScope() { parameters.put("code", "kJAHDFG"); OAuth2AccessToken expectedToken = new DefaultOAuth2AccessToken("FOO"); - ArgumentCaptor captor2 = ArgumentCaptor.forClass(TokenRequest.class); - - when(tokenGranter.grant(Mockito.eq("authorization_code"), captor2.capture())).thenReturn(expectedToken); + ArgumentCaptor captor = ArgumentCaptor.forClass(TokenRequest.class); + + when(tokenGranter.grant(Mockito.eq("authorization_code"), captor.capture())).thenReturn(expectedToken); @SuppressWarnings("unchecked") Map anyMap = Mockito.any(Map.class); - when(authorizationRequestFactory.createTokenRequest(anyMap, Mockito.eq(clientDetails))).thenReturn(createFromParameters(parameters)); - - ResponseEntity response = endpoint.getAccessToken(new UsernamePasswordAuthenticationToken( - clientId, null, Collections.singleton(new SimpleGrantedAuthority("ROLE_CLIENT"))), parameters); + when(authorizationRequestFactory.createTokenRequest(anyMap, Mockito.eq(clientDetails))).thenReturn( + createFromParameters(parameters)); + + ResponseEntity response = endpoint.getAccessToken(clientAuthentication, parameters); assertNotNull(response); assertEquals(HttpStatus.OK, response.getStatusCode()); OAuth2AccessToken body = response.getBody(); assertEquals(body, expectedToken); assertTrue("Wrong body: " + body, body.getTokenType() != null); - assertTrue("Scope of token request not cleared", captor2.getValue().getScope().isEmpty()); + assertTrue("Scope of token request not cleared", captor.getValue().getScope().isEmpty()); } + @Test(expected = InvalidGrantException.class) + public void testImplicitGrant() { + HashMap parameters = new HashMap(); + parameters.put(OAuth2Utils.GRANT_TYPE, "implicit"); + parameters.put("client_id", clientId); + @SuppressWarnings("unchecked") + Map anyMap = Mockito.any(Map.class); + when(authorizationRequestFactory.createTokenRequest(anyMap, Mockito.eq(clientDetails))).thenReturn( + createFromParameters(parameters)); + when(clientDetailsService.loadClientByClientId(clientId)).thenReturn(clientDetails); + endpoint.getAccessToken(clientAuthentication, parameters); + } } From 8c3a30834896cace7a0a65d9d5be7f8a91cc9b31 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 18 Nov 2013 09:26:43 +0000 Subject: [PATCH 119/831] SECOAUTH-403, SECOAUTH-415 Fix some error responses I tried to make the exception responses match the spec more accurately, but there are always some cases that don't quite seem to fit. Feedback still welcome if anyone finds an anomaly (and can locate the throwing code). --- .../OAuth2ExceptionJackson1Deserializer.java | 10 ++++++++-- .../OAuth2ExceptionJackson2Deserializer.java | 7 ++++++- .../common/exceptions/RedirectMismatchException.java | 2 +- .../provider/code/AuthorizationCodeTokenGranter.java | 6 +++--- .../provider/endpoint/AuthorizationEndpoint.java | 3 +-- .../provider/endpoint/DefaultRedirectResolver.java | 3 ++- .../exception/TestOAuth2ExceptionDeserializer.java | 10 +++++++--- 7 files changed, 28 insertions(+), 13 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson1Deserializer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson1Deserializer.java index 8bf9fbffa..c9f4b68ab 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson1Deserializer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson1Deserializer.java @@ -78,7 +78,12 @@ else if ("unauthorized_client".equals(errorCode)) { ex = new UnauthorizedClientException(errorMessage); } else if ("invalid_grant".equals(errorCode)) { - ex = new InvalidGrantException(errorMessage); + if (errorMessage.toLowerCase().contains("redirect") && errorMessage.toLowerCase().contains("match")) { + ex = new RedirectMismatchException(errorMessage); + } + else { + ex = new InvalidGrantException(errorMessage); + } } else if ("invalid_scope".equals(errorCode)) { ex = new InvalidScopeException(errorMessage); @@ -102,7 +107,8 @@ else if ("access_denied".equals(errorCode)) { ex = new UserDeniedAuthorizationException(errorMessage); } else if ("insufficient_scope".equals(errorCode)) { - ex = new InsufficientScopeException(errorMessage, OAuth2Utils.parseParameterList((String)errorParams.get("scope"))); + ex = new InsufficientScopeException(errorMessage, OAuth2Utils.parseParameterList((String) errorParams + .get("scope"))); } else { ex = new OAuth2Exception(errorMessage); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson2Deserializer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson2Deserializer.java index 92c23d4c4..c6fb33999 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson2Deserializer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson2Deserializer.java @@ -83,7 +83,12 @@ else if ("unauthorized_client".equals(errorCode)) { ex = new UnauthorizedClientException(errorMessage); } else if ("invalid_grant".equals(errorCode)) { - ex = new InvalidGrantException(errorMessage); + if (errorMessage.toLowerCase().contains("redirect") && errorMessage.toLowerCase().contains("match")) { + ex = new RedirectMismatchException(errorMessage); + } + else { + ex = new InvalidGrantException(errorMessage); + } } else if ("invalid_scope".equals(errorCode)) { ex = new InvalidScopeException(errorMessage); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/RedirectMismatchException.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/RedirectMismatchException.java index eac238ed3..4e66b52f2 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/RedirectMismatchException.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/RedirectMismatchException.java @@ -16,6 +16,6 @@ public RedirectMismatchException(String msg) { @Override public String getOAuth2ErrorCode() { - return "redirect_uri_mismatch"; + return "invalid_grant"; } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranter.java index 1d76768aa..b44afa117 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranter.java @@ -22,14 +22,14 @@ import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.common.exceptions.InvalidClientException; import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; -import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; +import org.springframework.security.oauth2.common.exceptions.InvalidRequestException; import org.springframework.security.oauth2.common.exceptions.RedirectMismatchException; import org.springframework.security.oauth2.common.util.OAuth2Utils; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.OAuth2RequestFactory; import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.token.AbstractTokenGranter; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; @@ -60,7 +60,7 @@ protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, Tok String redirectUri = parameters.get(OAuth2Utils.REDIRECT_URI); if (authorizationCode == null) { - throw new OAuth2Exception("An authorization code must be supplied."); + throw new InvalidRequestException("An authorization code must be supplied."); } OAuth2Authentication storedAuth = authorizationCodeServices.consumeAuthorizationCode(authorizationCode); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java index 04bd2585e..0050b957b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java @@ -32,7 +32,6 @@ import org.springframework.security.oauth2.common.exceptions.BadClientCredentialsException; import org.springframework.security.oauth2.common.exceptions.ClientAuthenticationException; import org.springframework.security.oauth2.common.exceptions.InvalidClientException; -import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; import org.springframework.security.oauth2.common.exceptions.InvalidRequestException; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.common.exceptions.RedirectMismatchException; @@ -283,7 +282,7 @@ private String appendAccessToken(AuthorizationRequest authorizationRequest, OAut String requestedRedirect = authorizationRequest.getRedirectUri(); if (accessToken == null) { - throw new InvalidGrantException("An implicit grant could not be made"); + throw new InvalidRequestException("An implicit grant could not be made"); } StringBuilder url = new StringBuilder(requestedRedirect); if (requestedRedirect.contains("#")) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolver.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolver.java index 11b146a63..3fedb78fa 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolver.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolver.java @@ -23,6 +23,7 @@ import java.util.Set; import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; +import org.springframework.security.oauth2.common.exceptions.InvalidRequestException; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.common.exceptions.RedirectMismatchException; import org.springframework.security.oauth2.provider.ClientDetails; @@ -79,7 +80,7 @@ else if (StringUtils.hasText(requestedRedirect)) { return requestedRedirect; } else { - throw new RedirectMismatchException("A redirect_uri must be supplied."); + throw new InvalidRequestException("A redirect_uri must be supplied."); } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/TestOAuth2ExceptionDeserializer.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/TestOAuth2ExceptionDeserializer.java index e09a90568..6f74b0c05 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/TestOAuth2ExceptionDeserializer.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/TestOAuth2ExceptionDeserializer.java @@ -95,10 +95,10 @@ public void readValueAccessDenied() throws Exception { @Test public void readValueRedirectUriMismatch() throws Exception { - String accessToken = createResponse(OAuth2Exception.REDIRECT_URI_MISMATCH); + String accessToken = createResponse(OAuth2Exception.INVALID_GRANT, "Redirect URI mismatch."); RedirectMismatchException result = (RedirectMismatchException) mapper.readValue(accessToken, OAuth2Exception.class); - assertEquals(DETAILS,result.getMessage()); + assertEquals("Redirect URI mismatch.",result.getMessage()); assertEquals(null,result.getAdditionalInformation()); } @@ -142,8 +142,12 @@ public void readValueWithObjects() throws Exception { assertEquals("{foo=[bar]}",result.getAdditionalInformation().toString()); } + private String createResponse(String error, String message) { + return "{\"error\":\"" + error + "\",\"error_description\":\""+message+"\"}"; + } + private String createResponse(String error) { - return "{\"error\":\"" + error + "\",\"error_description\":\"some detail\"}"; + return createResponse(error, DETAILS); } } From 58e67f7cbf7df2fe79f3b6bc430a74e2cc859c9f Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 18 Nov 2013 09:46:23 +0000 Subject: [PATCH 120/831] Fix some links in docs --- docs/oauth2.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/oauth2.md b/docs/oauth2.md index 94cee73eb..f4374f626 100644 --- a/docs/oauth2.md +++ b/docs/oauth2.md @@ -200,10 +200,10 @@ Facebook token responses also contain a non-compliant JSON entry for the expiry [AuthorizationServerTokenServices]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/token/AuthorizationServerTokenServices.html "AuthorizationServerTokenServices" [OAuth2AuthenticationProcessingFilter]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/filter/OAuth2AuthenticationProcessingFilter.html "OAuth2AuthenticationProcessingFilter" [oauth2.xsd]: http://www.springframework.org/schema/security/spring-security-oauth2.xsd "oauth2.xsd" - [expressions]: http://static.springsource.org/spring-security/site/docs/3.0.x/reference/el-access.html "Expression Access Control" + [expressions]: http://static.springsource.org/spring-security/site/docs/3.2.x/reference/el-access.html "Expression Access Control" [AccessTokenProviderChain]: /spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/AccessTokenProviderChain.java [OAuth2RestTemplate]: /spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/OAuth2RestTemplate.java [OAuth2ProtectedResourceDetails]: /spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/resource/OAuth2ProtectedResourceDetails.java - [restTemplate]: http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/web/client/RestTemplate.html "RestTemplate" + [restTemplate]: http://static.springsource.org/spring/docs/3.2.x/javadoc-api/org/springframework/web/client/RestTemplate.html "RestTemplate" [Facebook]: http://developers.facebook.com/docs/authentication "Facebook" From 26f5204d00e6dffff0d33d6d3d986073cf6a5b7c Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 18 Nov 2013 15:46:18 +0000 Subject: [PATCH 121/831] [maven-release-plugin] prepare release 2.0.0.M2 --- pom.xml | 4 ++-- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index c2a5ac5ed..149ae518d 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.0.BUILD-SNAPSHOT + 2.0.0.M2 http://static.springframework.org/spring-security/oauth @@ -27,7 +27,7 @@ http://github.com/SpringSource/spring-security-oauth scm:git:git://github.com/SpringSource/spring-security-oauth.git scm:git:ssh://git@github.com/SpringSource/spring-security-oauth.git - HEAD + 2.0.0.M2 JIRA diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index 4ca71dec4..8371562cb 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.0.BUILD-SNAPSHOT + 2.0.0.M2 ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index 439d42eca..d0a8a9031 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.0.BUILD-SNAPSHOT + 2.0.0.M2 ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 46b3ccad1..29b39e419 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.0.BUILD-SNAPSHOT + 2.0.0.M2 ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 6d56de571..730588efd 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.0.BUILD-SNAPSHOT + 2.0.0.M2 ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index d88a907a1..4bbe4aa48 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.0.BUILD-SNAPSHOT + 2.0.0.M2 spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index a27b2425f..cb40c5cc7 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.0.BUILD-SNAPSHOT + 2.0.0.M2 spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 439ab24dd..ffb3a3083 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.0.BUILD-SNAPSHOT + 2.0.0.M2 spring-security-oauth2 From 7df0165d1cabe030ad16b9682f83bfe55940c851 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 18 Nov 2013 15:46:29 +0000 Subject: [PATCH 122/831] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index 149ae518d..c2a5ac5ed 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.0.M2 + 2.0.0.BUILD-SNAPSHOT http://static.springframework.org/spring-security/oauth @@ -27,7 +27,7 @@ http://github.com/SpringSource/spring-security-oauth scm:git:git://github.com/SpringSource/spring-security-oauth.git scm:git:ssh://git@github.com/SpringSource/spring-security-oauth.git - 2.0.0.M2 + HEAD JIRA diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index 8371562cb..4ca71dec4 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.0.M2 + 2.0.0.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index d0a8a9031..439d42eca 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.0.M2 + 2.0.0.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 29b39e419..46b3ccad1 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.0.M2 + 2.0.0.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 730588efd..6d56de571 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.0.M2 + 2.0.0.BUILD-SNAPSHOT ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index 4bbe4aa48..d88a907a1 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.0.M2 + 2.0.0.BUILD-SNAPSHOT spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index cb40c5cc7..a27b2425f 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.0.M2 + 2.0.0.BUILD-SNAPSHOT spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index ffb3a3083..439ab24dd 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.0.M2 + 2.0.0.BUILD-SNAPSHOT spring-security-oauth2 From bebf1276163f04277f7a3cf21e7a4506d44cc349 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 11 Dec 2013 15:57:27 +0000 Subject: [PATCH 123/831] SECOAUTH-429: be more liberal in deserializing expires_in Some providers send a String apparently, so it's better to be defensive when deserializing. --- .../common/OAuth2AccessTokenJackson1Deserializer.java | 7 ++++++- .../common/OAuth2AccessTokenJackson2Deserializer.java | 7 ++++++- .../oauth2/common/BaseOAuth2AccessTokenJacksonTest.java | 2 ++ .../common/TestOAuth2AccessTokenJackson1Deserializer.java | 7 +++++++ .../common/TestOAuth2AccessTokenJackson2Deserializer.java | 7 +++++++ 5 files changed, 28 insertions(+), 2 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson1Deserializer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson1Deserializer.java index 1aadd1eac..68bbf55e9 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson1Deserializer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson1Deserializer.java @@ -18,6 +18,7 @@ import java.util.Map; import java.util.Set; +import org.codehaus.jackson.JsonParseException; import org.codehaus.jackson.JsonParser; import org.codehaus.jackson.JsonProcessingException; import org.codehaus.jackson.JsonToken; @@ -71,7 +72,11 @@ else if (OAuth2AccessToken.REFRESH_TOKEN.equals(name)) { refreshToken = jp.getText(); } else if (OAuth2AccessToken.EXPIRES_IN.equals(name)) { - expiresIn = jp.getLongValue(); + try { + expiresIn = jp.getLongValue(); + } catch (JsonParseException e) { + expiresIn = Long.valueOf(jp.getText()); + } } else if (OAuth2AccessToken.SCOPE.equals(name)) { String text = jp.getText(); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2Deserializer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2Deserializer.java index 1c5552678..4f1f9660b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2Deserializer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2Deserializer.java @@ -21,6 +21,7 @@ import org.springframework.security.oauth2.common.util.OAuth2Utils; +import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonToken; @@ -73,7 +74,11 @@ else if (OAuth2AccessToken.REFRESH_TOKEN.equals(name)) { refreshToken = jp.getText(); } else if (OAuth2AccessToken.EXPIRES_IN.equals(name)) { - expiresIn = jp.getLongValue(); + try { + expiresIn = jp.getLongValue(); + } catch (JsonParseException e) { + expiresIn = Long.valueOf(jp.getText()); + } } else if (OAuth2AccessToken.SCOPE.equals(name)) { String text = jp.getText(); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/BaseOAuth2AccessTokenJacksonTest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/BaseOAuth2AccessTokenJacksonTest.java index e82dac222..60fed249d 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/BaseOAuth2AccessTokenJacksonTest.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/BaseOAuth2AccessTokenJacksonTest.java @@ -41,6 +41,8 @@ abstract class BaseOAuth2AccessTokenJacksonTest { protected static final String ACCESS_TOKEN_EMPTYSCOPE = "{\"access_token\":\"token-value\",\"token_type\":\"bearer\",\"refresh_token\":\"refresh-value\",\"expires_in\":10,\"scope\":\"\"}"; + protected static final String ACCESS_TOKEN_BROKENEXPIRES = "{\"access_token\":\"token-value\",\"token_type\":\"bearer\",\"refresh_token\":\"refresh-value\",\"expires_in\":\"10\",\"scope\":\"\"}"; + protected static final String ACCESS_TOKEN_MULTISCOPE = "{\"access_token\":\"token-value\",\"token_type\":\"bearer\",\"refresh_token\":\"refresh-value\",\"expires_in\":10,\"scope\":\"read write\"}"; protected static final String ACCESS_TOKEN_NOSCOPE = "{\"access_token\":\"token-value\",\"token_type\":\"bearer\",\"refresh_token\":\"refresh-value\",\"expires_in\":10}"; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/TestOAuth2AccessTokenJackson1Deserializer.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/TestOAuth2AccessTokenJackson1Deserializer.java index 6631557cb..20611952c 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/TestOAuth2AccessTokenJackson1Deserializer.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/TestOAuth2AccessTokenJackson1Deserializer.java @@ -70,6 +70,13 @@ public void readValueWithEmptyStringScope() throws JsonGenerationException, Json assertTokenEquals(accessToken, actual); } + @Test + public void readValueWithBrokenExpiresIn() throws JsonGenerationException, JsonMappingException, IOException { + accessToken.setScope(new HashSet()); + OAuth2AccessToken actual = mapper.readValue(ACCESS_TOKEN_BROKENEXPIRES, OAuth2AccessToken.class); + assertTokenEquals(accessToken, actual); + } + @Test public void readValueWithMultiScopes() throws Exception { OAuth2AccessToken actual = mapper.readValue(ACCESS_TOKEN_MULTISCOPE, OAuth2AccessToken.class); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/TestOAuth2AccessTokenJackson2Deserializer.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/TestOAuth2AccessTokenJackson2Deserializer.java index e7939dd50..10dc365fb 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/TestOAuth2AccessTokenJackson2Deserializer.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/TestOAuth2AccessTokenJackson2Deserializer.java @@ -70,6 +70,13 @@ public void readValueWithEmptyStringScope() throws JsonGenerationException, Json assertTokenEquals(accessToken, actual); } + @Test + public void readValueWithBrokenExpiresIn() throws JsonGenerationException, JsonMappingException, IOException { + accessToken.setScope(new HashSet()); + OAuth2AccessToken actual = mapper.readValue(ACCESS_TOKEN_BROKENEXPIRES, OAuth2AccessToken.class); + assertTokenEquals(accessToken, actual); + } + @Test public void readValueWithMultiScopes() throws Exception { OAuth2AccessToken actual = mapper.readValue(ACCESS_TOKEN_MULTISCOPE, OAuth2AccessToken.class); From 0316fa4cf6bbb706b9dd888a511ab2c43324bb06 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 30 Dec 2013 09:13:45 +0000 Subject: [PATCH 124/831] Upgrade Spring and Spring Security --- pom.xml | 4 ++-- .../sparklr/src/main/webapp/WEB-INF/spring-servlet.xml | 7 +++++-- .../oauth2/provider/TestResourceOwnerPasswordProvider.java | 2 +- .../oauth2/tonr/src/main/webapp/WEB-INF/spring-servlet.xml | 2 +- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index c2a5ac5ed..0c9087396 100644 --- a/pom.xml +++ b/pom.xml @@ -16,8 +16,8 @@ UTF-8 - 3.2.3.RELEASE - 3.1.4.RELEASE + 3.2.5.RELEASE + 3.2.0.RELEASE [3.2.0,4.0.0) [3.2.0,4.0.0) 1.6 diff --git a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml index 0b7afa3db..dc4cb8c3a 100644 --- a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml +++ b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml @@ -5,7 +5,7 @@ xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2%20http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd%20http://www.springframework.org/schema/mvc%20http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd-http://www.springframework.org/schema/security%20http://www.springframework.org/schema/security/spring-security-3.1.xsd+http://www.springframework.org/schema/security%20http://www.springframework.org/schema/security/spring-security.xsd%20http://www.springframework.org/schema/beans%20http://www.springframework.org/schema/beans/spring-beans-3.1.xsd%20http://www.springframework.org/schema/context%20http://www.springframework.org/schema/context/spring-context-3.1.xsd"> @@ -20,7 +20,10 @@ - + + + + 3.0.1 provided @@ -186,11 +172,17 @@ jstl 1.2 + + + org.webjars + bootstrap + 3.0.3 + junit junit - 4.8.2 + 4.11 test diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/PhotoService.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/PhotoService.java index b8e608d11..7d7c36c70 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/PhotoService.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/PhotoService.java @@ -1,7 +1,7 @@ package org.springframework.security.oauth.examples.sparklr; -import java.util.Collection; import java.io.InputStream; +import java.util.Collection; /** * Service for retrieving photos. diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/PhotoServiceUser.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/PhotoServiceUser.java deleted file mode 100644 index bbc13d796..000000000 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/PhotoServiceUser.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.springframework.security.oauth.examples.sparklr; - -/** - * Photo service user information - added to enable user information to be available to Spring Social client - * - * @author Michael Lavelle - */ -public class PhotoServiceUser { - - private String username; - private String name; - - /** - * Create a new PhotoServiceUser - * - * @param username The unique username for the user - * @param name The name of the user - */ - public PhotoServiceUser(String username,String name) - { - this.username = username; - this.name = name; - } - - /** - * The unique username for the user - * - * @return username of the user - */ - public String getUsername() { - return username; - } - - /** - * The name of the user - * - * @return name of the user - */ - public String getName() { - return name; - } - - - -} diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/MethodSecurityConfig.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/MethodSecurityConfig.java new file mode 100644 index 000000000..bb396e9cc --- /dev/null +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/MethodSecurityConfig.java @@ -0,0 +1,40 @@ +/* + * Copyright 2002-2013 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.oauth.examples.sparklr.config; + +import org.springframework.beans.factory.annotation.Autowired; +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; + +/** + * @author Rob Winch + * @author Dave Syer + * + */ +@Configuration +@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true) +public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration { + @Autowired + private SecurityConfiguration securityConfig; + + @Override + protected MethodSecurityExpressionHandler createExpressionHandler() { + return new OAuth2MethodSecurityExpressionHandler(); + } +} diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java new file mode 100644 index 000000000..91ed68f4a --- /dev/null +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java @@ -0,0 +1,223 @@ +/* + * Copyright 2002-2013 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.oauth.examples.sparklr.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Lazy; +import org.springframework.context.annotation.Scope; +import org.springframework.context.annotation.ScopedProxyMode; +import org.springframework.core.annotation.Order; +import org.springframework.http.HttpMethod; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity.IgnoredRequestConfigurer; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.oauth.examples.sparklr.mvc.AdminController; +import org.springframework.security.oauth.examples.sparklr.oauth.SparklrUserApprovalHandler; +import org.springframework.security.oauth2.config.annotation.authentication.configurers.InMemoryClientDetailsServiceConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configuration.OAuth2AuthorizationServerConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.OAuth2ResourceServerConfigurer; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; +import org.springframework.security.oauth2.provider.approval.ApprovalStore; +import org.springframework.security.oauth2.provider.approval.TokenApprovalStore; +import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; +import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler; +import org.springframework.security.oauth2.provider.token.ConsumerTokenServices; +import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; +import org.springframework.security.oauth2.provider.token.TokenStore; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; + +/** + * @author Rob Winch + * + */ +@Configuration +@Order(3) +public class OAuth2ServerConfig extends WebSecurityConfigurerAdapter { + + private static final String SPARKLR_RESOURCE_ID = "sparklr"; + + @Autowired + private TokenStore tokenStore; + + @Override + public void configure(WebSecurity builder) throws Exception { + IgnoredRequestConfigurer ignoring = builder.ignoring(); + ignoring.antMatchers("/oauth/uncache_approvals", "/oauth/cache_approvals"); + } + + @Bean + public AdminController adminController(TokenStore tokenStore, ConsumerTokenServices tokenServices, SparklrUserApprovalHandler userApprovalHandler) { + AdminController adminController = new AdminController(); + adminController.setTokenStore(tokenStore); + adminController.setTokenServices(tokenServices); + adminController.setUserApprovalHandler(userApprovalHandler); + return adminController; + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http + .authorizeRequests() + .expressionHandler(new OAuth2WebSecurityExpressionHandler()) + .antMatchers("/photos").access("#oauth2.denyOAuthClient() and hasRole('ROLE_USER') or #oauth2.hasScope('read')") + .antMatchers("/photos/trusted/**").access("#oauth2.denyOAuthClient() and hasRole('ROLE_USER') or #oauth2.hasScope('trust')") + .antMatchers("/photos/user/**").access("#oauth2.denyOAuthClient() and hasRole('ROLE_USER') or #oauth2.hasScope('trust')") + .antMatchers("/photos/**").access("#oauth2.denyOAuthClient() and hasRole('ROLE_USER') or #oauth2.hasScope('read')") + .regexMatchers(HttpMethod.DELETE, "/oauth/users/([^/].*?)/tokens/.*") + .access("#oauth2.clientHasRole('ROLE_CLIENT') and (hasRole('ROLE_USER') or #oauth2.isClient()) and #oauth2.hasScope('write')") + .regexMatchers(HttpMethod.GET, "/oauth/users/.*") + .access("#oauth2.clientHasRole('ROLE_CLIENT') and (hasRole('ROLE_USER') or #oauth2.isClient()) and #oauth2.hasScope('read')") + .regexMatchers(HttpMethod.GET, "/oauth/clients/.*") + .access("#oauth2.clientHasRole('ROLE_CLIENT') and #oauth2.isClient() and #oauth2.hasScope('read')") + .and() + .requestMatchers() + .antMatchers("/photos/**", "/oauth/users/**", "/oauth/clients/**") + .and() + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER) + .and() + .exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler()) + .and() + // CSRF protection is awkward for machine clients + .csrf() + .requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/**")).disable() + .apply(new OAuth2ResourceServerConfigurer()).tokenStore(tokenStore) + .resourceId(SPARKLR_RESOURCE_ID); + // @formatter:on + } + + @Configuration + @Order(1) + protected static class AuthorizationServerConfiguration extends OAuth2AuthorizationServerConfigurerAdapter { + + private TokenStore tokenStore = new InMemoryTokenStore(); + + @Autowired + private OAuth2RequestFactory requestFactory; + + @Autowired + @Qualifier("authenticationManagerBean") + private AuthenticationManager authenticationManager; + + @Autowired + private ClientDetailsService clientDetailsService; + + @Value("${tonr.redirect:http://localhost:8080/tonr2/sparklr/redirect}") + private String tonrRedirectUri; + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + + // @formatter:off + auth.apply(new InMemoryClientDetailsServiceConfigurer()) + .withClient("tonr") + .resourceIds(SPARKLR_RESOURCE_ID) + .authorizedGrantTypes("authorization_code", "implicit") + .authorities("ROLE_CLIENT") + .scopes("read", "write") + .secret("secret") + .and() + .withClient("tonr-with-redirect") + .resourceIds(SPARKLR_RESOURCE_ID) + .authorizedGrantTypes("authorization_code", "implicit") + .authorities("ROLE_CLIENT") + .scopes("read", "write") + .secret("secret") + .redirectUris(tonrRedirectUri) + .and() + .withClient("my-client-with-registered-redirect") + .resourceIds(SPARKLR_RESOURCE_ID) + .authorizedGrantTypes("authorization_code", "client_credentials") + .authorities("ROLE_CLIENT") + .scopes("read", "trust") + .redirectUris("http://anywhere/?key=value") + .and() + .withClient("my-trusted-client") + .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit") + .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") + .scopes("read", "write", "trust") + .accessTokenValiditySeconds(60) + .and() + .withClient("my-trusted-client-with-secret") + .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit") + .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") + .scopes("read", "write", "trust") + .secret("somesecret") + .and() + .withClient("my-less-trusted-client") + .authorizedGrantTypes("authorization_code", "implicit") + .authorities("ROLE_CLIENT") + .scopes("read", "write", "trust") + .and() + .withClient("my-less-trusted-autoapprove-client") + .authorizedGrantTypes("implicit") + .authorities("ROLE_CLIENT") + .scopes("read", "write", "trust") + .autoApprove(true); + // @formatter:on + } + + @Bean + @Override + @Lazy + @Scope(proxyMode=ScopedProxyMode.TARGET_CLASS) + public SparklrUserApprovalHandler userApprovalHandler() throws Exception { + SparklrUserApprovalHandler handler = new SparklrUserApprovalHandler(); + handler.setApprovalStore(approvalStore()); + handler.setRequestFactory(requestFactory); + handler.setClientDetailsService(clientDetailsService); + handler.setUseApprovalStore(true); + return handler; + } + + @Bean + public ApprovalStore approvalStore() throws Exception { + TokenApprovalStore store = new TokenApprovalStore(); + store.setTokenStore(tokenStore); + return store; + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http + .authorizeRequests() + .antMatchers("/oauth/token").fullyAuthenticated() + .and() + .requestMatchers() + .antMatchers("/oauth/token") + .and() + .apply(new OAuth2AuthorizationServerConfigurer()) + .tokenStore(tokenStore) + .userApprovalHandler(userApprovalHandler()) + .authenticationManager(authenticationManager) + .realm("sparklr2/client"); + // @formatter:on + } + + } + +} diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/SecurityConfiguration.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/SecurityConfiguration.java new file mode 100644 index 000000000..a2ce93005 --- /dev/null +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/SecurityConfiguration.java @@ -0,0 +1,60 @@ +package org.springframework.security.oauth.examples.sparklr.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; + +@Configuration +@EnableWebSecurity +public class SecurityConfiguration extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication().withUser("marissa").password("koala").roles("USER").and().withUser("paul") + .password("emu").roles("USER"); + } + + @Override + public void configure(WebSecurity web) throws Exception { + web.ignoring().antMatchers("/webjars/**", "/images/**"); + } + + @Override + @Bean + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http + .authorizeRequests().antMatchers("/login.jsp").permitAll().and() + .authorizeRequests() + .anyRequest().hasRole("USER") + .and() + .exceptionHandling() + .accessDeniedPage("/login.jsp?authorization_error=true") + .and() + // TODO: put CSRF protection back into this endpoint + .csrf() + .requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/authorize")).disable() + .logout() + .logoutSuccessUrl("/index.jsp") + .logoutUrl("/logout.do") + .and() + .formLogin() + .usernameParameter("j_username") + .passwordParameter("j_password") + .failureUrl("/login.jsp?authentication_error=true") + .loginPage("/login.jsp") + .loginProcessingUrl("/login.do"); + // @formatter:on + } +} diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/ServletInitializer.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/ServletInitializer.java new file mode 100644 index 000000000..ca0a61a91 --- /dev/null +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/ServletInitializer.java @@ -0,0 +1,56 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.springframework.security.oauth.examples.sparklr.config; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; + +import org.springframework.util.ClassUtils; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; +import org.springframework.web.filter.DelegatingFilterProxy; +import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer; + +/** + * @author Dave Syer + * + */ +public class ServletInitializer extends AbstractDispatcherServletInitializer { + + @Override + protected WebApplicationContext createServletApplicationContext() { + AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); + context.scan(ClassUtils.getPackageName(getClass())); + return context; + } + + @Override + protected String[] getServletMappings() { + return new String[] { "/" }; + } + + @Override + protected WebApplicationContext createRootApplicationContext() { + return null; + } + + @Override + public void onStartup(ServletContext servletContext) throws ServletException { + super.onStartup(servletContext); + DelegatingFilterProxy filter = new DelegatingFilterProxy("springSecurityFilterChain"); + filter.setContextAttribute("org.springframework.web.servlet.FrameworkServlet.CONTEXT.dispatcher"); + servletContext.addFilter("springSecurityFilterChain", filter).addMappingForUrlPatterns(null, false, "/*"); + } + +} diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/WebMvcConfig.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/WebMvcConfig.java new file mode 100644 index 000000000..b164242c8 --- /dev/null +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/WebMvcConfig.java @@ -0,0 +1,102 @@ +package org.springframework.security.oauth.examples.sparklr.config; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; +import org.springframework.http.MediaType; +import org.springframework.security.oauth.examples.sparklr.PhotoInfo; +import org.springframework.security.oauth.examples.sparklr.PhotoService; +import org.springframework.security.oauth.examples.sparklr.impl.PhotoServiceImpl; +import org.springframework.security.oauth.examples.sparklr.mvc.AccessConfirmationController; +import org.springframework.security.oauth.examples.sparklr.mvc.PhotoController; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.approval.ApprovalStore; +import org.springframework.web.accept.ContentNegotiationManagerFactoryBean; +import org.springframework.web.servlet.View; +import org.springframework.web.servlet.ViewResolver; +import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.view.ContentNegotiatingViewResolver; +import org.springframework.web.servlet.view.InternalResourceViewResolver; +import org.springframework.web.servlet.view.json.MappingJacksonJsonView; + +@Configuration +@EnableWebMvc +public class WebMvcConfig extends WebMvcConfigurerAdapter { + + @Bean + public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { + return new PropertySourcesPlaceholderConfigurer(); + } + + @Bean + public ContentNegotiatingViewResolver contentViewResolver() throws Exception { + ContentNegotiationManagerFactoryBean contentNegotiationManager = new ContentNegotiationManagerFactoryBean(); + contentNegotiationManager.addMediaType("json", MediaType.APPLICATION_JSON); + + InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); + viewResolver.setPrefix("/WEB-INF/jsp/"); + viewResolver.setSuffix(".jsp"); + + MappingJacksonJsonView defaultView = new MappingJacksonJsonView(); + defaultView.setExtractValueFromSingleKeyModel(true); + + ContentNegotiatingViewResolver contentViewResolver = new ContentNegotiatingViewResolver(); + contentViewResolver.setContentNegotiationManager(contentNegotiationManager.getObject()); + contentViewResolver.setDefaultViews(Arrays.asList(new MappingJacksonJsonView())); + contentViewResolver.setViewResolvers(Arrays.asList(viewResolver)); + contentViewResolver.setDefaultViews(Arrays.asList(defaultView)); + return contentViewResolver; + } + + @Bean + public PhotoController photoController(PhotoService photoService) { + PhotoController photoController = new PhotoController(); + photoController.setPhotoService(photoService); + return photoController; + } + + @Bean + public AccessConfirmationController accessConfirmationController(ClientDetailsService clientDetailsService, ApprovalStore approvalStore) { + AccessConfirmationController accessConfirmationController = new AccessConfirmationController(); + accessConfirmationController.setClientDetailsService(clientDetailsService); + accessConfirmationController.setApprovalStore(approvalStore); + return accessConfirmationController; + } + + @Bean + public PhotoServiceImpl photoServices() { + List photos = new ArrayList(); + photos.add(createPhoto("1", "marissa")); + photos.add(createPhoto("2", "paul")); + photos.add(createPhoto("3", "marissa")); + photos.add(createPhoto("4", "paul")); + photos.add(createPhoto("5", "marissa")); + photos.add(createPhoto("6", "paul")); + + PhotoServiceImpl photoServices = new PhotoServiceImpl(); + photoServices.setPhotos(photos); + return photoServices; + } + + + private PhotoInfo createPhoto(String id, String userId) { + PhotoInfo photo = new PhotoInfo(); + photo.setId(id); + photo.setName("photo" + id + ".jpg"); + photo.setUserId(userId); + photo.setResourceURL("/org/springframework/security/oauth/examples/sparklr/impl/resources/" + photo.getName()); + return photo; + } + + @Override + public void configureDefaultServletHandling( + DefaultServletHandlerConfigurer configurer) { + configurer.enable(); + } +} diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AdminController.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AdminController.java index e7e0e8212..e0dfca049 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AdminController.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AdminController.java @@ -1,27 +1,16 @@ -/* - * Copyright 2012-2013 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.oauth.examples.sparklr.mvc; import java.security.Principal; +import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; +import java.util.Map; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.oauth.examples.sparklr.oauth.SparklrUserApprovalHandler; +import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.token.ConsumerTokenServices; @@ -42,7 +31,7 @@ public class AdminController { private ConsumerTokenServices tokenServices; - + private TokenStore tokenStore; private SparklrUserApprovalHandler userApprovalHandler; @@ -64,7 +53,7 @@ public void stopCaching() throws Exception { public Collection listTokensForUser(@PathVariable String user, Principal principal) throws Exception { checkResourceOwner(user, principal); - return tokenStore.findTokensByUserName(user); + return enhance(tokenStore.findTokensByUserName(user)); } @RequestMapping(value = "/oauth/users/{user}/tokens/{token}", method = RequestMethod.DELETE) @@ -81,7 +70,22 @@ public ResponseEntity revokeToken(@PathVariable String user, @PathVariable @RequestMapping("/oauth/clients/{client}/tokens") @ResponseBody public Collection listTokensForClient(@PathVariable String client) throws Exception { - return tokenStore.findTokensByClientId(client); + return enhance(tokenStore.findTokensByClientId(client)); + } + + private Collection enhance(Collection tokens) { + Collection result = new ArrayList(); + for (OAuth2AccessToken prototype : tokens) { + DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(prototype); + String clientId = tokenStore.readAuthentication(token).getOAuth2Request().getClientId(); + if (clientId != null) { + Map map = new HashMap(token.getAdditionalInformation()); + map.put("client_id", clientId); + token.setAdditionalInformation(map); + result.add(token); + } + } + return result; } private void checkResourceOwner(String user, Principal principal) { diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/PhotoController.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/PhotoController.java index 3062db63c..023e498fc 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/PhotoController.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/PhotoController.java @@ -1,18 +1,3 @@ -/* - * Copyright 2012-2013 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.oauth.examples.sparklr.mvc; import java.io.ByteArrayOutputStream; diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/PhotoServiceUserController.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/PhotoServiceUserController.java deleted file mode 100644 index 8d9d471f4..000000000 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/PhotoServiceUserController.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.springframework.security.oauth.examples.sparklr.mvc; - -import java.security.Principal; - - -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.oauth.examples.sparklr.PhotoServiceUser; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; - -/** - * @author Michael Lavelle - * - * Added to provide an endpoint from which Spring Social can obtain authentication details - */ -@RequestMapping("/me") -@Controller -public class PhotoServiceUserController { - - private UserDetailsService userDetailsService; - - - @ResponseBody - @RequestMapping("") - public PhotoServiceUser getPhotoServiceUser(Principal principal) - { - UserDetails userDetails = userDetailsService.loadUserByUsername(principal.getName()); - return new PhotoServiceUser(userDetails.getUsername(),userDetails.getUsername()); - } - - public void setUserDetailsService(UserDetailsService userDetailsService) { - this.userDetailsService = userDetailsService; - } - -} diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrTokenEnhancer.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrTokenEnhancer.java deleted file mode 100644 index 505ac4903..000000000 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrTokenEnhancer.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2012-2013 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.oauth.examples.sparklr.oauth; - -import java.util.Collections; - -import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; -import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.token.TokenEnhancer; - -public class SparklrTokenEnhancer implements TokenEnhancer { - - @Override - public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { - DefaultOAuth2AccessToken result = new DefaultOAuth2AccessToken(accessToken); - result.setAdditionalInformation(Collections.singletonMap("client_id", (Object) authentication.getOAuth2Request().getClientId())); - return result; - } - -} diff --git a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/jsp/access_confirmation.jsp b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/jsp/access_confirmation.jsp index 515914ebc..6cc9ed96f 100644 --- a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/jsp/access_confirmation.jsp +++ b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/jsp/access_confirmation.jsp @@ -1,50 +1,91 @@ -<%@ page import="org.springframework.security.core.AuthenticationException" %> -<%@ page import="org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter" %> -<%@ page import="org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException" %> -<%@ taglib prefix="authz" uri="http://www.springframework.org/security/tags" %> +<%@ page + import="org.springframework.security.core.AuthenticationException"%> +<%@ page + import="org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter"%> +<%@ page + import="org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException"%> +<%@ taglib prefix="authz" + uri="http://www.springframework.org/security/tags"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> - - + + - - Sparklr - "/> + + +Sparklr + + + -

Sparklr

+
+

Sparklr

-
+ <% + if (session.getAttribute(AbstractAuthenticationProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY) != null + && !(session + .getAttribute(AbstractAuthenticationProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY) instanceof UnapprovedClientAuthenticationException)) { + %> +
+

Woops!

- <% if (session.getAttribute(AbstractAuthenticationProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY) != null && !(session.getAttribute(AbstractAuthenticationProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY) instanceof UnapprovedClientAuthenticationException)) { %> -
-

Woops!

+

+ Access could not be granted. (<%=((AuthenticationException) session + .getAttribute(AbstractAuthenticationProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY)) + .getMessage()%>) +

+
+ <% + } + %> + -

Access could not be granted. (<%= ((AuthenticationException) session.getAttribute(AbstractAuthenticationProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY)).getMessage() %>)

-
- <% } %> - + +

Please Confirm

- -

Please Confirm

+

+ You hereby authorize " + + " to access your protected resources. +

-

You hereby authorize "" to access your protected resources.

+
+ +
    + + + checked + + + checked + +
  • +
    + ${scope.key}: Approve Deny +
    +
  • +
    +
+ +
-
- -
    - checked checked -
  • ${scope.key}: ApproveDeny
  • -
    -
- -
-
-
+ - + +
diff --git a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/jsp/oauth_error.jsp b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/jsp/oauth_error.jsp index 0367c5829..e5f23f0f1 100644 --- a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/jsp/oauth_error.jsp +++ b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/jsp/oauth_error.jsp @@ -1,23 +1,40 @@ <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> - - + + - - Sparklr - "/> + + +Sparklr + + + -

Sparklr OAuth2 Error

+
-
-

()

-

Please go back to your client application and try again, or contact the owner and ask for support

-
+

Sparklr OAuth2 Error

- +

+ + ( + + ) +

+

Please go back to your client application and try again, or + contact the owner and ask for support

+ + + +
diff --git a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml deleted file mode 100644 index dc4cb8c3a..000000000 --- a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml +++ /dev/null @@ -1,343 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/web.xml b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index 712743393..000000000 --- a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - springSecurityFilterChain - org.springframework.web.filter.DelegatingFilterProxy - - contextAttribute - org.springframework.web.servlet.FrameworkServlet.CONTEXT.spring - - - - - springSecurityFilterChain - /* - - - - spring - org.springframework.web.servlet.DispatcherServlet - 1 - - - - spring - / - - - diff --git a/samples/oauth2/sparklr/src/main/webapp/browse.html b/samples/oauth2/sparklr/src/main/webapp/browse.html index 79cdd4d62..fb5bbb390 100644 --- a/samples/oauth2/sparklr/src/main/webapp/browse.html +++ b/samples/oauth2/sparklr/src/main/webapp/browse.html @@ -2,9 +2,11 @@ Client Authentication Example - + + + src="http://github.com/webjars/bootstrap/3.0.3/js/bootstrap.min.js"> - + + +Sparklr + + + + + + + -

Sparklr

+
+ +

Sparklr

+ +

Home

-
-

Home

+

This is a great site to store and view your photos. + Unfortunately, we don't have any services for printing your photos. + For that, you'll have to go to Tonr.

-

This is a great site to store and view your photos. Unfortunately, we don't have any services - for printing your photos. For that, you'll have to go to Tonr.

+ +
+
" role="form"> + +
+
- -

Login

-
" method="post"> -

-

- -

-
-
- -
">
- -

Your Photos

+

Your Photos

-

- -

-
-
+

+ +

+ - + +
diff --git a/samples/oauth2/sparklr/src/main/webapp/login.jsp b/samples/oauth2/sparklr/src/main/webapp/login.jsp index d9ab9c407..843b0c750 100644 --- a/samples/oauth2/sparklr/src/main/webapp/login.jsp +++ b/samples/oauth2/sparklr/src/main/webapp/login.jsp @@ -1,19 +1,23 @@ <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> - - - + + - + + Sparklr " /> + href="http://github.com/webjars/bootstrap/3.0.3/css/bootstrap.min.css" /> + + -

Sparklr

+
+ +

Sparklr

-

Woops!

@@ -25,32 +29,38 @@

You are not permitted to access that resource.

-

Login

- -

We've got a grand total of 2 users: marissa and paul. Go ahead - and log in. Marissa's password is "koala" and Paul's password is - "emu".

-
" method="post"> -

- -

-

- -

- -

- -

-
-
+
+

We've got a grand total of 2 users: marissa and paul. Go ahead + and log in. Marissa's password is "koala" and Paul's password is + "emu".

+
" method="post" role="form"> +
+ +

Login

+
+
+ +
+
+ +
+ + +
+
+ +
+ + - diff --git a/samples/oauth2/sparklr/src/main/webapp/request_token_authorized.jsp b/samples/oauth2/sparklr/src/main/webapp/request_token_authorized.jsp deleted file mode 100644 index 8fed03235..000000000 --- a/samples/oauth2/sparklr/src/main/webapp/request_token_authorized.jsp +++ /dev/null @@ -1,25 +0,0 @@ -<%@ taglib prefix="authz" uri="http://www.springframework.org/security/tags" %> -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> - - - - - Sparklr - "/> - - - - -

Sparklr

- -
-

Home

- -

You have successfully authorized the request for a protected resource.

-
- - - - - - diff --git a/samples/oauth2/sparklr/src/main/webapp/sparklr_gadget.xml b/samples/oauth2/sparklr/src/main/webapp/sparklr_gadget.xml deleted file mode 100644 index 3f914b85a..000000000 --- a/samples/oauth2/sparklr/src/main/webapp/sparklr_gadget.xml +++ /dev/null @@ -1,147 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - ]]> - - \ No newline at end of file diff --git a/samples/oauth2/sparklr/src/main/webapp/style.css b/samples/oauth2/sparklr/src/main/webapp/style.css deleted file mode 100644 index aab5b1e64..000000000 --- a/samples/oauth2/sparklr/src/main/webapp/style.css +++ /dev/null @@ -1,85 +0,0 @@ -/* CSS Document */ - -body { - color: white; - font-family: 'Trebuchet MS', Helvetica, sans-serif; - font-size: 12px; - margin: 0 auto; - width: 736px; - background: url(http://github.com/'images/bg.gif'); -} - -#content { - background: #3d3d3d; - width: 676px; - margin-top: 20px; - padding: 0 30px 25px 30px; -} - -a { - color: lightblue; - text-decoration: none; -} - -a:hover { - color: red; - text-decoration: none; -} - -h1 { - background: url(http://github.com/'images/header.jpg'); - height: 36px; - width: 721px; - margin: 0 0 1em 0; - padding-top: 80px; - padding-left: 15px; - font-size: 1.8em; - font-variant: small-caps; -} - -h2 { - font-size: 1.2em; - margin-left: -10px; - padding-top: 20px; - font-weight: bold; - letter-spacing: .3px; -} - -.error h2 { - color: red; - font-size: 1.2em; - padding-top: 20px; - font-weight: bold; - letter-spacing: .3px; -} - -.error p { - color: red; -} - -p { - letter-spacing: .2px; -} - -label { - text-indent: 20px; - letter-spacing: .2px; - padding: 5px 5px 5px 5px; -} - -#footer { - font-size: .8em; - margin-top: 1em; -} - -#footer a { - color: #333333; - font-weight: bold; - font-size: 1em -} - -#footer a:hover { - color: red; - font-weight: bold; - font-size: 1em -} \ No newline at end of file diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ServerRunning.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ServerRunning.java index 9d77345cd..03a20984f 100644 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ServerRunning.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ServerRunning.java @@ -59,6 +59,7 @@ * @author Dave Syer * */ +@SuppressWarnings("deprecation") public class ServerRunning implements MethodRule, RestTemplateHolder { private static Log logger = LogFactory.getLog(ServerRunning.class); diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestAdminEndpoints.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestAdminEndpoints.java index 407fe3737..a9a32971c 100644 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestAdminEndpoints.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestAdminEndpoints.java @@ -68,6 +68,7 @@ public void testRevokeTokenByUser() throws Exception { // exception should be thrown. ResponseEntity result = serverRunning.getForString("/sparklr2/oauth/users/marissa/tokens", headers); fail("Should have thrown an exception"); + assertNotNull(result); } catch (InsufficientScopeException ex) { assertEquals(HttpStatus.FORBIDDEN.value(), ex.getHttpErrorCode()); assertEquals("insufficient_scope", ex.getOAuth2ErrorCode()); diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationCodeProvider.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationCodeProvider.java index 95c23ca3b..fd6d0d915 100755 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationCodeProvider.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationCodeProvider.java @@ -21,6 +21,8 @@ import java.io.IOException; import java.util.Arrays; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.junit.Rule; import org.junit.Test; @@ -120,20 +122,7 @@ public ResponseEntity extractData(ClientHttpResponse response) throws IOEx @BeforeOAuth2Context public void loginAndExtractCookie() { - - MultiValueMap formData; - formData = new LinkedMultiValueMap(); - formData.add("j_username", "marissa"); - formData.add("j_password", "koala"); - - String location = "/sparklr2/login.do"; - ResponseEntity result = serverRunning.postForStatus(location, formData); - assertEquals(HttpStatus.FOUND, result.getStatusCode()); - String cookie = result.getHeaders().getFirst("Set-Cookie"); - - assertNotNull("Expected cookie in " + result.getHeaders(), cookie); - this.cookie = cookie; - + this.cookie = loginAndGrabCookie(); } @Test @@ -313,7 +302,8 @@ public void testInsufficientScopeInResourceRequest() throws Exception { try { serverRunning.getForString("/sparklr2/photos?format=json"); fail("Should have thrown exception"); - } catch (InsufficientScopeException ex) { + } + catch (InsufficientScopeException ex) { // ignore / all good } } @@ -388,23 +378,31 @@ private String getAuthorizeUrl(String clientId, String redirectUri, String scope return uri.build().toString(); } - private String loginAndGrabCookie() { - HttpHeaders headers = new HttpHeaders(); - headers.setAccept(Arrays.asList(MediaType.TEXT_HTML)); + ResponseEntity page = serverRunning.getForString("/sparklr2/login.jsp"); + String cookie = page.getHeaders().getFirst("Set-Cookie"); + Matcher matcher = Pattern.compile("(?s).*name=\"_csrf\".*?value=\"([^\"]+).*").matcher(page.getBody()); - MultiValueMap formData = new LinkedMultiValueMap(); + MultiValueMap formData; + formData = new LinkedMultiValueMap(); formData.add("j_username", "marissa"); formData.add("j_password", "koala"); + if (matcher.matches()) { + formData.add("_csrf", matcher.group(1)); + } - // Should be redirected to the original URL, but now authenticated - ResponseEntity result = serverRunning.postForStatus("/sparklr2/login.do", headers, formData); + String location = "/sparklr2/login.do"; + HttpHeaders headers = new HttpHeaders(); + headers.set("Cookie", cookie); + headers.setAccept(Arrays.asList(MediaType.TEXT_HTML)); + ResponseEntity result = serverRunning.postForStatus(location, headers , formData); assertEquals(HttpStatus.FOUND, result.getStatusCode()); + cookie = result.getHeaders().getFirst("Set-Cookie"); - assertTrue(result.getHeaders().containsKey("Set-Cookie")); + assertNotNull("Expected cookie in " + result.getHeaders(), cookie); - return result.getHeaders().getFirst("Set-Cookie"); + return cookie; } diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestBootstrap.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestBootstrap.java deleted file mode 100755 index 792f917a9..000000000 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestBootstrap.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2006-2010 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; - -import org.junit.Test; -import org.springframework.context.support.GenericXmlApplicationContext; -import org.springframework.core.io.FileSystemResource; - -/** - * @author Dave Syer - * - */ -public class TestBootstrap { - - @Test - public void testRootContext() throws Exception { - GenericXmlApplicationContext context = new GenericXmlApplicationContext(new FileSystemResource("src/main/webapp/WEB-INF/spring-servlet.xml")); - context.close(); - } - -} diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestImplicitProvider.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestImplicitProvider.java index e8e813f9d..02d203d33 100644 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestImplicitProvider.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestImplicitProvider.java @@ -7,6 +7,8 @@ import java.io.IOException; import java.util.Arrays; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.junit.Rule; import org.junit.Test; @@ -46,15 +48,22 @@ public class TestImplicitProvider { @BeforeOAuth2Context public void loginAndExtractCookie() { + ResponseEntity page = serverRunning.getForString("/sparklr2/login.jsp"); + String cookie = page.getHeaders().getFirst("Set-Cookie"); + Matcher matcher = Pattern.compile("(?s).*name=\"_csrf\".*?value=\"([^\"]+).*").matcher(page.getBody()); + MultiValueMap formData; formData = new LinkedMultiValueMap(); formData.add("j_username", "marissa"); formData.add("j_password", "koala"); + if (matcher.matches()) { + formData.add("_csrf", matcher.group(1)); + } String location = "/sparklr2/login.do"; ResponseEntity result = serverRunning.postForStatus(location, formData); assertEquals(HttpStatus.FOUND, result.getStatusCode()); - String cookie = result.getHeaders().getFirst("Set-Cookie"); + cookie = result.getHeaders().getFirst("Set-Cookie"); assertNotNull("Expected cookie in " + result.getHeaders(), cookie); this.cookie = cookie; @@ -84,7 +93,7 @@ public ClientHttpResponse intercept(HttpRequest request, byte[] body, context.getAccessTokenRequest().setCookie(cookie); assertNotNull(context.getAccessToken()); assertTrue("Wrong location header: " + latestHeaders.getLocation().getFragment(), latestHeaders.getLocation().getFragment() - .contains("scope=read trust write")); + .contains("scope=read write trust")); } @Test diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestRefreshTokenSupport.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestRefreshTokenSupport.java index 77eb6717b..69cc21541 100644 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestRefreshTokenSupport.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestRefreshTokenSupport.java @@ -2,6 +2,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertNotNull; import java.util.Map; @@ -61,7 +62,7 @@ private OAuth2AccessToken refreshAccessToken(String refreshToken) { @SuppressWarnings("rawtypes") ResponseEntity response = serverRunning.postForMap("/sparklr2/oauth/token", formData); assertEquals(HttpStatus.OK, response.getStatusCode()); - assertEquals("no-store", response.getHeaders().getFirst("Cache-Control")); + assertTrue("Wrong cache control: " + response.getHeaders().getFirst("Cache-Control"), response.getHeaders().getFirst("Cache-Control").contains("no-store")); @SuppressWarnings("unchecked") OAuth2AccessToken newAccessToken = DefaultOAuth2AccessToken.valueOf(response.getBody()); return newAccessToken; @@ -74,7 +75,7 @@ private OAuth2AccessToken getAccessToken(String scope, String clientId) throws E @SuppressWarnings("rawtypes") ResponseEntity response = serverRunning.postForMap("/sparklr2/oauth/token", formData); assertEquals(HttpStatus.OK, response.getStatusCode()); - assertEquals("no-store", response.getHeaders().getFirst("Cache-Control")); + assertTrue("Wrong cache control: " + response.getHeaders().getFirst("Cache-Control"), response.getHeaders().getFirst("Cache-Control").contains("no-store")); @SuppressWarnings("unchecked") OAuth2AccessToken accessToken = DefaultOAuth2AccessToken.valueOf(response.getBody()); diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestResourceOwnerPasswordProvider.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestResourceOwnerPasswordProvider.java index c9094478e..adc0fc132 100644 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestResourceOwnerPasswordProvider.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestResourceOwnerPasswordProvider.java @@ -132,7 +132,8 @@ public void testTokenNotGrantedIfSecretNotProvided() throws Exception { assertEquals(HttpStatus.UNAUTHORIZED, e.getStatusCode()); List values = tokenEndpointResponse.getHeaders().get("WWW-Authenticate"); assertEquals(1, values.size()); - assertTrue(values.get(0).contains("Basic realm=\"sparklr2/client\"")); + String header = values.get(0); + assertTrue("Wrong header " + header, header.contains("Basic realm=\"sparklr2/client\"")); } } diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/samples/config/SecurityConfigTests.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/samples/config/SecurityConfigTests.java new file mode 100644 index 000000000..4274a96ae --- /dev/null +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/samples/config/SecurityConfigTests.java @@ -0,0 +1,55 @@ +/* + * Copyright 2002-2013 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.samples.config; + +import static org.junit.Assert.assertNotNull; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.oauth.examples.sparklr.config.SecurityConfiguration; +import org.springframework.security.oauth2.provider.token.TokenStore; +import org.springframework.security.web.FilterChainProxy; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +/** + * @author Rob Winch + * + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration +@WebAppConfiguration +public class SecurityConfigTests { + + @Configuration + @ComponentScan(basePackageClasses = SecurityConfiguration.class) + public static class Config {} + + @Autowired + private FilterChainProxy springSecurityFilterChain; + + @Autowired + private TokenStore tokenStore; + + @Test + public void securityConfigurationLoads() { + assertNotNull(tokenStore); + } +} diff --git a/samples/oauth2/tonr/.springBeans b/samples/oauth2/tonr/.springBeans index 0952433a9..f25fc5ab4 100644 --- a/samples/oauth2/tonr/.springBeans +++ b/samples/oauth2/tonr/.springBeans @@ -1,13 +1,12 @@ 1 - + - src/main/webapp/WEB-INF/spring-servlet.xml diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 6d56de571..057276026 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -1,4 +1,5 @@ - + 4.0.0 @@ -13,6 +14,10 @@ war OAuth for Spring Security - Tonr2 (OAuth 2 Client Example) + + /tonr2 + + integration @@ -55,6 +60,15 @@ + + + ${pom.groupId} + java-sparklr2 + ${pom.version} + war + tomcat + + @@ -98,16 +112,14 @@ - ${pom.groupId} - sparklr2 - ${pom.version} - war - tomcat + ${project.groupId} + spring-security-oauth2 + ${project.version} ${project.groupId} - spring-security-oauth2 + spring-security-oauth2-javaconfig ${project.version} @@ -143,38 +155,33 @@ org.springframework - spring-beans - ${spring.version} - - - - org.springframework - spring-core + spring-aop ${spring.version} org.springframework - spring-aop + spring-expression ${spring.version} org.springframework - spring-expression + spring-tx ${spring.version} org.springframework - spring-tx + spring-test ${spring.version} + test org.codehaus.jackson jackson-mapper-asl - 1.5.5 + 1.9.13 @@ -190,10 +197,16 @@ 1.2 + + org.webjars + bootstrap + 3.0.3 + + junit junit - 4.8.2 + 4.11 test diff --git a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/SecurityConfig.java b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/SecurityConfig.java new file mode 100644 index 000000000..eec85d1d3 --- /dev/null +++ b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/SecurityConfig.java @@ -0,0 +1,57 @@ +package org.springframework.security.oauth.examples.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter; +import org.springframework.security.web.access.ExceptionTranslationFilter; + +@Configuration +@EnableWebSecurity +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + @Bean + public OAuth2ClientContextFilter oauth2ClientFilter() { + OAuth2ClientContextFilter filter = new OAuth2ClientContextFilter(); + return filter; + } + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication().withUser("marissa").password("wombat").roles("USER").and().withUser("sam") + .password("kangaroo").roles("USER"); + } + + @Override + public void configure(WebSecurity web) throws Exception { + web.ignoring().antMatchers("/resources/**"); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http.authorizeRequests() + .antMatchers("/sparklr/**","/facebook/**").hasRole("USER") + .anyRequest().permitAll() + .and() + .addFilterAfter(oauth2ClientFilter(), ExceptionTranslationFilter.class) + .logout() + .logoutSuccessUrl("/login.jsp") + .logoutUrl("/logout.do") + .permitAll() + .and() + .formLogin() + .loginPage("/login.jsp") + .loginProcessingUrl("/login.do") + .failureUrl("/login.jsp?authentication_error=true") + .usernameParameter("j_username") + .passwordParameter("j_password") + .permitAll(); + // @formatter:on + } + +} diff --git a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/ServletInitializer.java b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/ServletInitializer.java new file mode 100644 index 000000000..a820d5212 --- /dev/null +++ b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/ServletInitializer.java @@ -0,0 +1,55 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.springframework.security.oauth.examples.config; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; + +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; +import org.springframework.web.filter.DelegatingFilterProxy; +import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer; + +/** + * @author Dave Syer + * + */ +public class ServletInitializer extends AbstractDispatcherServletInitializer { + + @Override + protected WebApplicationContext createServletApplicationContext() { + AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); + context.register(SecurityConfig.class, WebMvcConfig.class); + return context; + } + + @Override + protected String[] getServletMappings() { + return new String[] { "/" }; + } + + @Override + protected WebApplicationContext createRootApplicationContext() { + return null; + } + + @Override + public void onStartup(ServletContext servletContext) throws ServletException { + super.onStartup(servletContext); + DelegatingFilterProxy filter = new DelegatingFilterProxy("springSecurityFilterChain"); + filter.setContextAttribute("org.springframework.web.servlet.FrameworkServlet.CONTEXT.dispatcher"); + servletContext.addFilter("springSecurityFilterChain", filter).addMappingForUrlPatterns(null, false, "/*"); + } + +} diff --git a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/WebMvcConfig.java b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/WebMvcConfig.java new file mode 100644 index 000000000..d9d41f629 --- /dev/null +++ b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/WebMvcConfig.java @@ -0,0 +1,248 @@ +package org.springframework.security.oauth.examples.config; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import javax.annotation.Resource; + +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.context.annotation.PropertySource; +import org.springframework.context.annotation.Scope; +import org.springframework.context.annotation.ScopedProxyMode; +import org.springframework.context.support.ConversionServiceFactoryBean; +import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; +import org.springframework.http.MediaType; +import org.springframework.http.converter.BufferedImageHttpMessageConverter; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter; +import org.springframework.security.oauth.examples.tonr.SparklrService; +import org.springframework.security.oauth.examples.tonr.converter.AccessTokenRequestConverter; +import org.springframework.security.oauth.examples.tonr.impl.SparklrServiceImpl; +import org.springframework.security.oauth.examples.tonr.mvc.FacebookController; +import org.springframework.security.oauth.examples.tonr.mvc.SparklrController; +import org.springframework.security.oauth.examples.tonr.mvc.SparklrRedirectController; +import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext; +import org.springframework.security.oauth2.client.OAuth2RestTemplate; +import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails; +import org.springframework.security.oauth2.client.token.AccessTokenRequest; +import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails; +import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails; +import org.springframework.security.oauth2.common.AuthenticationScheme; +import org.springframework.security.oauth2.config.annotation.web.configuration.OAuth2ClientConfiguration; +import org.springframework.web.accept.ContentNegotiationManagerFactoryBean; +import org.springframework.web.client.RestOperations; +import org.springframework.web.servlet.View; +import org.springframework.web.servlet.ViewResolver; +import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.view.ContentNegotiatingViewResolver; +import org.springframework.web.servlet.view.InternalResourceViewResolver; +import org.springframework.web.servlet.view.json.MappingJacksonJsonView; + +@Configuration +@EnableWebMvc +@PropertySource("classpath:sparklr.properties") +public class WebMvcConfig extends WebMvcConfigurerAdapter { + + @Bean + public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { + return new PropertySourcesPlaceholderConfigurer(); + } + + @Bean + public ContentNegotiatingViewResolver contentViewResolver() throws Exception { + ContentNegotiatingViewResolver contentViewResolver = new ContentNegotiatingViewResolver(); + ContentNegotiationManagerFactoryBean contentNegotiationManager = new ContentNegotiationManagerFactoryBean(); + contentNegotiationManager.addMediaType("json", MediaType.APPLICATION_JSON); + contentViewResolver.setContentNegotiationManager(contentNegotiationManager.getObject()); + contentViewResolver.setDefaultViews(Arrays. asList(new MappingJacksonJsonView())); + return contentViewResolver; + } + + @Bean + public ViewResolver viewResolver() { + InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); + viewResolver.setPrefix("/WEB-INF/jsp/"); + viewResolver.setSuffix(".jsp"); + return viewResolver; + } + + @Override + public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { + configurer.enable(); + } + + @Bean + public SparklrController sparklrController(@Qualifier("sparklrService") + SparklrService sparklrService) { + SparklrController controller = new SparklrController(); + controller.setSparklrService(sparklrService); + return controller; + } + + @Bean + public SparklrRedirectController sparklrRedirectController(@Qualifier("sparklrRedirectService") + SparklrService sparklrService) { + SparklrRedirectController controller = new SparklrRedirectController(); + controller.setSparklrService(sparklrService); + return controller; + } + + @Bean + public FacebookController facebookController(@Qualifier("facebookRestTemplate") + RestOperations facebookRestTemplate) { + FacebookController controller = new FacebookController(); + controller.setFacebookRestTemplate(facebookRestTemplate); + return controller; + } + + @Bean + public SparklrServiceImpl sparklrService(@Value("${sparklrPhotoListURL}") + String sparklrPhotoListURL, @Value("${sparklrPhotoURLPattern}") + String sparklrPhotoURLPattern, @Value("${sparklrTrustedMessageURL}") + String sparklrTrustedMessageURL, @Qualifier("sparklrRestTemplate") + RestOperations sparklrRestTemplate, @Qualifier("trustedClientRestTemplate") + RestOperations trustedClientRestTemplate) { + SparklrServiceImpl sparklrService = new SparklrServiceImpl(); + sparklrService.setSparklrPhotoListURL(sparklrPhotoListURL); + sparklrService.setSparklrPhotoURLPattern(sparklrPhotoURLPattern); + sparklrService.setSparklrTrustedMessageURL(sparklrTrustedMessageURL); + sparklrService.setSparklrRestTemplate(sparklrRestTemplate); + sparklrService.setTrustedClientRestTemplate(trustedClientRestTemplate); + return sparklrService; + } + + @Bean + public SparklrServiceImpl sparklrRedirectService(@Value("${sparklrPhotoListURL}") + String sparklrPhotoListURL, @Value("${sparklrPhotoURLPattern}") + String sparklrPhotoURLPattern, @Value("${sparklrTrustedMessageURL}") + String sparklrTrustedMessageURL, @Qualifier("sparklrRedirectRestTemplate") + RestOperations sparklrRestTemplate, @Qualifier("trustedClientRestTemplate") + RestOperations trustedClientRestTemplate) { + SparklrServiceImpl sparklrService = new SparklrServiceImpl(); + sparklrService.setSparklrPhotoListURL(sparklrPhotoListURL); + sparklrService.setSparklrPhotoURLPattern(sparklrPhotoURLPattern); + sparklrService.setSparklrTrustedMessageURL(sparklrTrustedMessageURL); + sparklrService.setSparklrRestTemplate(sparklrRestTemplate); + sparklrService.setTrustedClientRestTemplate(trustedClientRestTemplate); + return sparklrService; + } + + @Bean + public ConversionServiceFactoryBean conversionService() { + ConversionServiceFactoryBean conversionService = new ConversionServiceFactoryBean(); + conversionService.setConverters(Collections.singleton(new AccessTokenRequestConverter())); + return conversionService; + } + + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("/resources/**").addResourceLocations("/resources/"); + } + + @Override + public void configureMessageConverters(List> converters) { + converters.add(new BufferedImageHttpMessageConverter()); + } + + @Configuration + @Import(OAuth2ClientConfiguration.class) + protected static class ResourceConfiguration { + + @Value("${accessTokenUri}") + private String accessTokenUri; + + @Value("${userAuthorizationUri}") + private String userAuthorizationUri; + + @Resource + @Qualifier("accessTokenRequest") + private AccessTokenRequest accessTokenRequest; + + @Bean + public OAuth2ProtectedResourceDetails sparklr() { + AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails(); + details.setId("sparklr/tonr"); + details.setClientId("tonr"); + details.setClientSecret("secret"); + details.setAccessTokenUri(accessTokenUri); + details.setUserAuthorizationUri(userAuthorizationUri); + details.setScope(Arrays.asList("read", "write")); + return details; + } + + @Bean + public OAuth2ProtectedResourceDetails sparklrRedirect() { + AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails(); + details.setId("sparklr/tonr-redirect"); + details.setClientId("tonr-with-redirect"); + details.setClientSecret("secret"); + details.setAccessTokenUri(accessTokenUri); + details.setUserAuthorizationUri(userAuthorizationUri); + details.setScope(Arrays.asList("read", "write")); + details.setUseCurrentUri(false); + return details; + } + + @Bean + public OAuth2ProtectedResourceDetails facebook() { + AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails(); + details.setId("facebook"); + details.setClientId("233668646673605"); + details.setClientSecret("33b17e044ee6a4fa383f46ec6e28ea1d"); + details.setAccessTokenUri("https://graph.facebook.com/oauth/access_token"); + details.setUserAuthorizationUri("https://www.facebook.com/dialog/oauth"); + details.setTokenName("oauth_token"); + details.setAuthenticationScheme(AuthenticationScheme.query); + details.setClientAuthenticationScheme(AuthenticationScheme.form); + return details; + } + + @Bean + public OAuth2ProtectedResourceDetails trusted() { + ClientCredentialsResourceDetails details = new ClientCredentialsResourceDetails(); + details.setId("sparklr/trusted"); + details.setClientId("my-client-with-registered-redirect"); + details.setAccessTokenUri(accessTokenUri); + details.setScope(Arrays.asList("trust")); + return details; + } + + @Bean + @Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES) + public OAuth2RestTemplate facebookRestTemplate() { + OAuth2RestTemplate template = new OAuth2RestTemplate(facebook(), new DefaultOAuth2ClientContext( + accessTokenRequest)); + MappingJacksonHttpMessageConverter converter = new MappingJacksonHttpMessageConverter(); + converter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON, + MediaType.valueOf("text/javascript"))); + template.setMessageConverters(Arrays.> asList(converter)); + return template; + } + + @Bean + @Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES) + public OAuth2RestTemplate sparklrRestTemplate() { + return new OAuth2RestTemplate(sparklr(), new DefaultOAuth2ClientContext(accessTokenRequest)); + } + + @Bean + @Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES) + public OAuth2RestTemplate sparklrRedirectRestTemplate() { + return new OAuth2RestTemplate(sparklrRedirect(), new DefaultOAuth2ClientContext(accessTokenRequest)); + } + + @Bean + public OAuth2RestTemplate trustedClientRestTemplate() { + return new OAuth2RestTemplate(trusted(), new DefaultOAuth2ClientContext()); + } + + } + +} diff --git a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/impl/SparklrServiceImpl.java b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/impl/SparklrServiceImpl.java index c5b88a1c6..1057d6b8b 100644 --- a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/impl/SparklrServiceImpl.java +++ b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/impl/SparklrServiceImpl.java @@ -13,7 +13,6 @@ import org.springframework.security.oauth.examples.tonr.SparklrException; import org.springframework.security.oauth.examples.tonr.SparklrService; -import org.springframework.security.oauth2.client.OAuth2RestTemplate; import org.springframework.web.client.RestOperations; import org.xml.sax.Attributes; import org.xml.sax.SAXException; @@ -81,7 +80,7 @@ public void setSparklrTrustedMessageURL(String sparklrTrustedMessageURL) { this.sparklrTrustedMessageURL = sparklrTrustedMessageURL; } - public void setSparklrRestTemplate(OAuth2RestTemplate sparklrRestTemplate) { + public void setSparklrRestTemplate(RestOperations sparklrRestTemplate) { this.sparklrRestTemplate = sparklrRestTemplate; } diff --git a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/mvc/FacebookController.java b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/mvc/FacebookController.java index 9df956d8d..7d10f8aa3 100644 --- a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/mvc/FacebookController.java +++ b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/mvc/FacebookController.java @@ -5,7 +5,6 @@ import org.codehaus.jackson.JsonNode; import org.codehaus.jackson.node.ArrayNode; import org.codehaus.jackson.node.ObjectNode; -import org.springframework.security.oauth2.client.OAuth2RestTemplate; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; @@ -33,7 +32,7 @@ public String photos(Model model) throws Exception { return "facebook"; } - public void setFacebookRestTemplate(OAuth2RestTemplate facebookRestTemplate) { + public void setFacebookRestTemplate(RestOperations facebookRestTemplate) { this.facebookRestTemplate = facebookRestTemplate; } diff --git a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/mvc/SparklrController.java b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/mvc/SparklrController.java index 48336863f..eac4a2147 100644 --- a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/mvc/SparklrController.java +++ b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/mvc/SparklrController.java @@ -33,7 +33,6 @@ public class SparklrController { @RequestMapping("/sparklr/photos") public String photos(Model model) throws Exception { model.addAttribute("photoIds", sparklrService.getSparklrPhotoIds()); - model.addAttribute("path", "photos"); return "sparklr"; } diff --git a/samples/oauth2/tonr/src/main/webapp/LICENSE.txt b/samples/oauth2/tonr/src/main/webapp/LICENSE.txt deleted file mode 100644 index 5c83a364b..000000000 --- a/samples/oauth2/tonr/src/main/webapp/LICENSE.txt +++ /dev/null @@ -1,211 +0,0 @@ -THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE -("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE -OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. - -BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS -OF THIS LICENSE. THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE -OF SUCH TERMS AND CONDITIONS. - -1. Definitions - - a. "Collective Work" means a work, such as a periodical issue, anthology or encyclopedia, - in which the Work in its entirety in unmodified form, along with a number of other - contributions, constituting separate and independent works in themselves, are assembled - into a collective whole. A work that constitutes a Collective Work will not be - considered a Derivative Work (as defined below) for the purposes of this License. - - b. "Derivative Work" means a work based upon the Work or upon the Work and other - pre-existing works, such as a translation, musical arrangement, dramatization, - fictionalization, motion picture version, sound recording, art reproduction, abridgment, - condensation, or any other form in which the Work may be recast, transformed, or adapted, - except that a work that constitutes a Collective Work will not be considered a Derivative - Work for the purpose of this License. For the avoidance of doubt, where the Work is a - musical composition or sound recording, the synchronization of the Work in timed-relation - with a moving image ("synching") will be considered a Derivative Work for the purpose of - this License. - - c. "Licensor" means the individual or entity that offers the Work under the terms of this - License. - - d. "Original Author" means the individual or entity who created the Work. - - e. "Work" means the copyrightable work of authorship offered under the terms of this - License. - - f. "You" means an individual or entity exercising rights under this License who has not - previously violated the terms of this License with respect to the Work, or who has - received express permission from the Licensor to exercise rights under this License - despite a previous violation. - - g. "License Elements" means the following high-level license attributes as selected by - Licensor and indicated in the title of this License: Attribution, ShareAlike. - -2. Fair Use Rights. Nothing in this license is intended to reduce, limit, or restrict any rights -arising from fair use, first sale or other limitations on the exclusive rights of the copyright -owner under copyright law or other applicable laws. - -3. License Grant. Subject to the terms and conditions of this License, Licensor hereby grants -You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable -copyright) license to exercise the rights in the Work as stated below: - - a. to reproduce the Work, to incorporate the Work into one or more Collective Works, and to - reproduce the Work as incorporated in the Collective Works; - - b. to create and reproduce Derivative Works; - - c. to distribute copies or phonorecords of, display publicly, perform publicly, and perform - publicly by means of a digital audio transmission the Work including as incorporated in - Collective Works; - - d. to distribute copies or phonorecords of, display publicly, perform publicly, and perform - publicly by means of a digital audio transmission Derivative Works. - - e. For the avoidance of doubt, where the work is a musical composition: - - i. Performance Royalties Under Blanket Licenses. Licensor waives the exclusive right to - collect, whether individually or via a performance rights society (e.g. ASCAP, BMI, - SESAC), royalties for the public performance or public digital performance (e.g. - webcast) of the Work. - - ii. Mechanical Rights and Statutory Royalties. Licensor waives the exclusive right to - collect, whether individually or via a music rights society or designated agent (e.g. - Harry Fox Agency), royalties for any phonorecord You create from the Work ("cover - version") and distribute, subject to the compulsory license created by 17 USC Section - 115 of the US Copyright Act (or the equivalent in other jurisdictions). - - f. Webcasting Rights and Statutory Royalties. For the avoidance of doubt, where the Work is - a sound recording, Licensor waives the exclusive right to collect, whether individually - or via a performance-rights society (e.g. SoundExchange), royalties for the public - digital performance (e.g. webcast) of the Work, subject to the compulsory license created - by 17 USC Section 114 of the US Copyright Act (or the equivalent in other jurisdictions). - -The above rights may be exercised in all media and formats whether now known or hereafter devised. -The above rights include the right to make such modifications as are technically necessary to -exercise the rights in other media and formats. All rights not expressly granted by Licensor are -hereby reserved. - -4. Restrictions.The license granted in Section 3 above is expressly made subject to and limited by -the following restrictions: - - a. You may distribute, publicly display, publicly perform, or publicly digitally perform the - Work only under the terms of this License, and You must include a copy of, or the Uniform - Resource Identifier for, this License with every copy or phonorecord of the Work You - distribute, publicly display, publicly perform, or publicly digitally perform. You may - not offer or impose any terms on the Work that alter or restrict the terms of this - License or the recipients' exercise of the rights granted hereunder. You may not - sublicense the Work. You must keep intact all notices that refer to this License and to - the disclaimer of warranties. You may not distribute, publicly display, publicly perform, - or publicly digitally perform the Work with any technological measures that control - access or use of the Work in a manner inconsistent with the terms of this License - Agreement. The above applies to the Work as incorporated in a Collective Work, but this - does not require the Collective Work apart from the Work itself to be made subject to the - terms of this License. If You create a Collective Work, upon notice from any Licensor You - must, to the extent practicable, remove from the Collective Work any reference to such - Licensor or the Original Author, as requested. If You create a Derivative Work, upon - notice from any Licensor You must, to the extent practicable, remove from the Derivative - Work any reference to such Licensor or the Original Author, as requested. - - b. You may distribute, publicly display, publicly perform, or publicly digitally perform a - Derivative Work only under the terms of this License, a later version of this License - with the same License Elements as this License, or a Creative Commons iCommons license - that contains the same License Elements as this License (e.g. Attribution-ShareAlike 2.0 - Japan). You must include a copy of, or the Uniform Resource Identifier for, this License - or other license specified in the previous sentence with every copy or phonorecord of - each Derivative Work You distribute, publicly display, publicly perform, or publicly - digitally perform. You may not offer or impose any terms on the Derivative Works that - alter or restrict the terms of this License or the recipients' exercise of the rights - granted hereunder, and You must keep intact all notices that refer to this License and to - - the disclaimer of warranties. You may not distribute, publicly display, publicly perform, - or publicly digitally perform the Derivative Work with any technological measures that - control access or use of the Work in a manner inconsistent with the terms of this License - Agreement. The above applies to the Derivative Work as incorporated in a Collective Work, - but this does not require the Collective Work apart from the Derivative Work itself to be - made subject to the terms of this License. - - c. If you distribute, publicly display, publicly perform, or publicly digitally perform the - Work or any Derivative Works or Collective Works, You must keep intact all copyright - notices for the Work and give the Original Author credit reasonable to the medium or - means You are utilizing by conveying the name (or pseudonym if applicable) of the - Original Author if supplied; the title of the Work if supplied; to the extent reasonably - practicable, the Uniform Resource Identifier, if any, that Licensor specifies to be - associated with the Work, unless such URI does not refer to the copyright notice or - licensing information for the Work; and in the case of a Derivative Work, a credit - identifying the use of the Work in the Derivative Work (e.g., "French translation of the - Work by Original Author," or "Screenplay based on original Work by Original Author"). - Such credit may be implemented in any reasonable manner; provided, however, that in the - case of a Derivative Work or Collective Work, at a minimum such credit will appear where - any other comparable authorship credit appears and in a manner at least as prominent as - such other comparable authorship credit. - -5. Representations, Warranties and Disclaimer - -UNLESS OTHERWISE AGREED TO BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO -REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE MATERIALS, EXPRESS, IMPLIED, STATUTORY OR -OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A -PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE -PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE -EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU. - -6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL -LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE -OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN -ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - -7. Termination - - a. This License and the rights granted hereunder will terminate automatically upon any - breach by You of the terms of this License. Individuals or entities who have received - Derivative Works or Collective Works from You under this License, however, will not have - their licenses terminated provided such individuals or entities remain in full compliance - with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this - License. - - b. Subject to the above terms and conditions, the license granted here is perpetual (for the - duration of the applicable copyright in the Work). Notwithstanding the above, Licensor - reserves the right to release the Work under different license terms or to stop - distributing the Work at any time; provided, however that any such election will not - serve to withdraw this License (or any other license that has been, or is required to be, - granted under the terms of this License), and this License will continue in full force - and effect unless terminated as stated above. - -8. Miscellaneous - - a. Each time You distribute or publicly digitally perform the Work or a Collective Work, the - Licensor offers to the recipient a license to the Work on the same terms and conditions - as the license granted to You under this License. - - b. Each time You distribute or publicly digitally perform a Derivative Work, Licensor offers - to the recipient a license to the original Work on the same terms and conditions as the - license granted to You under this License. - - c. If any provision of this License is invalid or unenforceable under applicable law, it - shall not affect the validity or enforceability of the remainder of the terms of this - License, and without further action by the parties to this agreement, such provision - shall be reformed to the minimum extent necessary to make such provision valid and - enforceable. - - d. No term or provision of this License shall be deemed waived and no breach consented to - unless such waiver or consent shall be in writing and signed by the party to be charged - with such waiver or consent. - - e. This License constitutes the entire agreement between the parties with respect to the - Work licensed here. There are no understandings, agreements or representations with - respect to the Work not specified here. Licensor shall not be bound by any additional - provisions that may appear in any communication from You. This License may not be - modified without the mutual written agreement of the Licensor and You. - -Creative Commons is not a party to this License, and makes no warranty whatsoever in connection -with the Work. Creative Commons will not be liable to You or any party on any legal theory for -any damages whatsoever, including without limitation any general, special, incidental or -consequential damages arising in connection to this license. Notwithstanding the foregoing two -(2) sentences, if Creative Commons has expressly identified itself as the Licensor hereunder, -it shall have all rights and obligations of Licensor. - -Except for the limited purpose of indicating to the public that the Work is licensed under the -CCPL, neither party will use the trademark "Creative Commons" or any related trademark or logo -of Creative Commons without the prior written consent of Creative Commons. Any permitted use will -be in compliance with Creative Commons' then-current trademark usage guidelines, as may be -published on its website or otherwise made available upon request from time to time. - -Creative Commons may be contacted at http://creativecommons.org/. \ No newline at end of file diff --git a/samples/oauth2/tonr/src/main/webapp/WEB-INF/jsp/facebook.jsp b/samples/oauth2/tonr/src/main/webapp/WEB-INF/jsp/facebook.jsp index b7b1cb9e7..3bd3c9c5e 100644 --- a/samples/oauth2/tonr/src/main/webapp/WEB-INF/jsp/facebook.jsp +++ b/samples/oauth2/tonr/src/main/webapp/WEB-INF/jsp/facebook.jsp @@ -1,32 +1,51 @@ -<%@ taglib prefix="authz" uri="http://www.springframework.org/security/tags" %> +<%@ taglib prefix="authz" + uri="http://www.springframework.org/security/tags"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> - " rel="stylesheet" type="text/css"/> - tonr + + + + + + +tonr -
- - - -
-

Your Facebook Friends:

- -
    - -
  • -
    -
-
-
+ +
+

Your Facebook Friends:

+
    + +
  • +
    +
+
\ No newline at end of file diff --git a/samples/oauth2/tonr/src/main/webapp/WEB-INF/jsp/sparklr.jsp b/samples/oauth2/tonr/src/main/webapp/WEB-INF/jsp/sparklr.jsp index 3537257ae..884c02dfc 100644 --- a/samples/oauth2/tonr/src/main/webapp/WEB-INF/jsp/sparklr.jsp +++ b/samples/oauth2/tonr/src/main/webapp/WEB-INF/jsp/sparklr.jsp @@ -1,32 +1,53 @@ -<%@ taglib prefix="authz" uri="http://www.springframework.org/security/tags" %> +<%@ taglib prefix="authz" + uri="http://www.springframework.org/security/tags"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> - " rel="stylesheet" type="text/css"/> - tonr + + + + + + +tonr -
+ - - -
-

Your Sparklr Photos

- -
    - -
  • "/>
  • -
    -
-
-
+
+

Your Sparklr Photos

+
    + +
  • +
    +
+
\ No newline at end of file diff --git a/samples/oauth2/tonr/src/main/webapp/WEB-INF/spring-servlet.xml b/samples/oauth2/tonr/src/main/webapp/WEB-INF/spring-servlet.xml deleted file mode 100644 index 6d0b5f260..000000000 --- a/samples/oauth2/tonr/src/main/webapp/WEB-INF/spring-servlet.xml +++ /dev/null @@ -1,166 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/oauth2/tonr/src/main/webapp/WEB-INF/web.xml b/samples/oauth2/tonr/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index 712743393..000000000 --- a/samples/oauth2/tonr/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - springSecurityFilterChain - org.springframework.web.filter.DelegatingFilterProxy - - contextAttribute - org.springframework.web.servlet.FrameworkServlet.CONTEXT.spring - - - - - springSecurityFilterChain - /* - - - - spring - org.springframework.web.servlet.DispatcherServlet - 1 - - - - spring - / - - - diff --git a/samples/oauth2/tonr/src/main/webapp/demo.html b/samples/oauth2/tonr/src/main/webapp/demo.html index e12f39150..d3d99bbb1 100644 --- a/samples/oauth2/tonr/src/main/webapp/demo.html +++ b/samples/oauth2/tonr/src/main/webapp/demo.html @@ -1,56 +1,62 @@ - - - - Tonr JS Client Demo - - - - - - +Tonr JS Client Demo + + + + + + + -

Sparklr Client Authentication Sample

+
-
+

Sparklr Client Authentication Sample

Once you have authenticated and approved the access, some - JavaScript in this page will render a list of photos from Sparklr below:

+ JavaScript in this page will render a list of photos from Sparklr + below:

- diff --git a/samples/oauth2/tonr/src/main/webapp/images/bg.gif b/samples/oauth2/tonr/src/main/webapp/images/bg.gif deleted file mode 100644 index 5cbfaa356239da3ea20b77fa88a79b10053171e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 79 zcmZ?wbhEHb6k-r!XkcJ?{`~p>|Nj+#vM_*v4u}BBFfggP)U_?#Jy)j1$F5rNZsg+| ejeX)_Pc&z(IJNEa^di+a(~6?jm-mS=SOWkBCLJ6A diff --git a/samples/oauth2/tonr/src/main/webapp/images/header.jpg b/samples/oauth2/tonr/src/main/webapp/images/header.jpg deleted file mode 100644 index 4f9014ba9eddb83cca96d97667fe4987aeb7680e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1987 zcmex=C5UDGKfoZ!!BE2VfSFN{fk}{&S&;Gn5r%T0 z!x)&D8G-JE0S*=}R(4Kqpg0;30E#fNv9q#pvO;B;Ss0l_SlKuPg+;epRB$Q^iLr}+ zFmzN2Oq{4>qN*k#x$&d2F_$2QN&jy#@Br;(5@Z%+uxGe_?em^={q9pA_P&?+`fNS- zwW_?2^JjKP&AOsrkRwfWFkx)Q$92s1ub1#oq_};B` zG_o~TG!zQ6@wuJ)=>2*j-m0wdwd&QCn_J$kJ{GstG;^_!=I(uEI$B?ik*@4Z#=a@?`Lt4!wMO{GHp+L#OS26$B_>Aj1fBEv&7V zPxs&H{oFdO_RE6>?hDZ6$>4KyFP|>IQ~Ei#&hM889r_)}FalkRn7F^5eUbS&vB>Y2 zn;PXB(B;YC>*&pkse6(?M`!c<<*ZD$WSD@VB_h^l$KMn8Eh5wJ`*E>UVaSsquwhqa z;qQt23O1eJH%Ely3mGP$Yax^@%YN6`&6RCH*G2>%&8>X*%P-&l_&wv_10wViP=cB8 z`Ljy?GsLd}>-)8L-~9ptCg77sO|UQD9IQ0&+Vu5#{j7Z+$9gOP&wb2RB}IZB(?_9;Cfrp1*RsF6?#=SG^R)iHeq+7;uw3(-ewiQHJEc>8o!_?K zvT^GUf133m)80C1+qsul-~Law-n#exx83`4|KkpJ z4Y3^id(OM-@4snw>uY~%Y~Ajv{Rv-xyDr)~J>!PG!k7OH8Fl=J?@#@{HEjR<_s#!r F0stHff;<2K diff --git a/samples/oauth2/tonr/src/main/webapp/images/xbg.gif b/samples/oauth2/tonr/src/main/webapp/images/xbg.gif deleted file mode 100644 index 9f9cdcabdfc1875324b8530bffaca889eabef16b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23570 zcmWifd05QbAIHDTEZze0%-s;)aZW z&YU?D7k^SZ_1~|bUUc2QRkK5%Rj6N=bt;edwB^d(y1l~}JBF`a{5&-D?bU~89T!i8 zr~mx%t!Go?A}d0lwZ0`X`_Opd zsrmfx@7`T6FMV+6U{C#~6XBarM&zA|%Xr*;L0_8PnVZwKJ@?Gab$9okXqC@AF_ri5 z(D7@^9sPBG>a%v=syX=e<;#{RaaV4|re*U`k=cykbK0G*dv2|v_xx|zkWqY3)FLvc^zF)8T=fau6 zzq(9a=Z+-#KWsmAv!>j*{ZMy)c~4>fg~e5dt%b*?Bpk~Q`uzNP@7BsAe&H?AQ9b#J z`Ms-cE{14+1^?gnIjdJbDdGqcaJ7BtY zwx@E-h~d`#`m=_uTl;s_9G*CF~!%u4n~vL&?^*CG(F5Z9L+ib3 zkx2=+TB`5uzpS0Tw1E}!>Ot?(faIgoCtEBQ_a7MG|HbeB&HrNpKrDcTz#QFvQ?bZx zx#|KhQ?UcPcSOPxwlrKRV@z4~*wE70vz--L%8WgIu=h{)++!)drw?7*HKDk?G|F6U z>x0~i(j`F#Zv+}Ms`T z=aJjTm)^W|@#lB*vug)tU%vF~=ji7*|J=NM*a6RsDt<{sOBX3j)m*Zpc<#|mzxIyL?Yy2GVmCM#OFikR>Eft0xe=aCGT4SU3 z6ZeeI*DQ#1aYDww*gNa46m@o4Wh_daS+Op2NjL}cs6!{$6cRD#WyPD~DxN7AYjCfd zHbklh70AfJ!NxhShoyrl5mNKW5#dyR2gYXDL(~{^!n6A@T+(=B;gn>H2;0<3t-0ov zOr{x{D@J0$ZIjCuAGCax&A_7Zr)@skBJCkrRP`|EXy zCt{z57;ljzDd79RO%cf= zCV#jx!+&~U13Et_xFwoOSuy57yQvoYE*LU!aE@LdVjYgpd!8%reibbfwi|$JcdfU6 zNsRUA>Ankqlj^G1&09n^s&sy3DF)+nkAuW_8hERz4%UW6Qgo=+~&I%4N|B1^H2n zZV;%K^k#H9xU%I<^WM~PWYZ6eo`h@|#y}jxVe_vY$Z;<4_;j zB0YDAKEVTeMOYNPVHhZw?Gb^ZM=;T8{4e&513QEM8+}HO-i^R*_YbT2KX8U>U!~3= z)dRs_H9;h^#{aOU3*dOu!kKA6FQTwF%+OH}E3IyvneVzh$zegfU@cM2_x%)75?auw z-~`U{|MZt%Ts&lJE~}?*=>$b7H{4>cU4bndg;5V%pCNy0>x2AWT1~e7SaOU2uxb2~ zd~7-s0@3N-oB;ObmMQg&UH4akO6DMD6L*D`B1{popdiL&$(ABT%%*+r02t3%*n^#~1u_PBHk*Za>=~@sn`WSTo#y#^ zgG^=rB~z5bl1~)m+vaE$U^M4C(!oKOkG~ySFaWXTpP(bHD0orlA!%OFx7HPpWEdaM zO1*3AXzM}0llRi$(MJpU=f#76POk#F_jJCF>@-TW?*5zx0DS#wF3&JCYSQK^l|b8w zyro6a=i_VVedA+1fR2EBxMG4fa`}vvz?3)+ws=|~FM);z?dQm&nn7fu`l#TShuk~R z16eEu9uZrxSz@xrhYk!Pg32|?I;byyymAo>=`3%=@kG!BQX+!;QjaX6Jr~8WNR`B4 za9q=jsmoD&1j9R4(t_je{M%t&1n5{X0>kP3#Q|DRgsM577;i!+)&^PGH{qu_t=yUR z7CNa~2@tyCcCA-~%v3uiA@^JPw3Jiq1!jTg;Q$(9YQ!88t;lF3KIqJrNtnG|q)asS zghj>2E&qiNbK=MENRi{5MsLqBXmOJy87#0Cf{NT{xAXxUP6U-BV&`z)h{^W4-8CnZ z_++&Nu*u`Xf%93`Gn)r(mW<)8;u1^K>I?DjHL8OR*Bqzk58}@7RwWrs+oNhRHf>zk z&favhyscq*x1Av@LIz;k?Ito&8P5WpEV;75~n4MDogcOlH zg7eKyBUMsO8s)a6L5h36f~4!KaU^FT_C{q)|X77Eh1ibfo!z>h4Wc_)~d;#(LCg~pW8-zDt=X=PWGjkx>;eB_M)zIQV=Ad zStl;8G_Y{Fnj>>rU}0d24&jQG!ZB@D!3qrr3P91DT3IADlbM)5V=DWPyv7A%lw~ZO zecqTA0~!42F3zGjaVj>LCf}pBTxs8Z3m+=|*iFlTe#cFtENPL_3e**osHtCioDb~n87;<={gt%Z4r^Pf4l`%QgKZLx zW0L5~^SzTx6AS+HyN57Jq2z1U`_DLIGy%nFZFnM6v(9Sg~aW{!s`mT|MnK3s}HIvUrf6 z5!<~{x&1zI#sIeDHhe;xUnvcH?nT?h!X_EXd7=#o0T@4n%p(zAB(Z+2#ciocVC7&L zD0muOM1)^WgKYw6D@Bx*sP!yu*&jve%Xth( zJt?sXuAyP-w8Ur)W&sQKpb=DUyi!3(Q;+ySyC%wnEuLN`abQ#YB5SaiUTNB)tyRm~yo8KrOLWhIH6 z0=31#M~JOl>r@lcBF2L39W#oh0vg!KA>*s97Sw|8UhL?07n#(lp&}&9yinjy1$nF8 ztMKbMf^d2&yg^a`kfEY&m!&eyN58+u!JkYpB!-9@aGIKAt$|zAs;f=v8O8ad9IMql z>>P6``oQra4=MyQ;6x1H6g7iS{r7ZfL=IsOx^{w=wUFhc7+irj?)YTFKIVasb%fjF z!8;G|b=vGSsd7H5I@Y^q{R6Do!m&ySjhn`EH>W{4n!Rup;jIbqCu3i_Yr3 z7r{lG`_Ubz>a~s(L39(zL%IXu5tp&-g0$dS`*=GU^&id7_FcO%gP7yueOpb~ojOvE zdM;H1Po<$}dB_HtnI*KdBj!`cmaT|SkR0) z&=(Ua(VdC|D04ReZTX;1ye>(%qL$_5?g^)(GlNW6sakbH1RTQx0vbRrv~m+k?H1K< zF{zhXatPBj@*h>$y;|TC!F>n-KcH3}xlp_sx?qCua8@GH9Wz^?_QS-`BlHP8{2nbF zuBl+85n#=pW#Y-7;opxa*dDc7CIa4TH>LLj$5d|NX8dY`KSc-A%)kW^cHFB{Yzy^` zxrWaNwzLsGj94!;l9I&*OGFTc4*K(st!<&Q_P9A|f#(GO0v)^?$fvNNO*8;B12i?h zCeC_iEOxszmQzJI06^EcWLOWoiGUwYK9khgU>QmGz9hQ+W5z#NM2!>?7sXB} z-MzZN)5a0r1nXlki6X%hSSqcoJuilliX&Wpob{E=Gft{yuXw z(A*336e&=vuD&X+`I-m^s&RNTb&8a_5{37wkA14AREWcg9BBT-{V0ITRcjacI8LFV zZs?pu-Z3X5K_rDYN@0-{$<3m_L5Um97eW9eg;qB`2V7&u;x$kpi?FiVEl>)$NP*kH z@;w0IOFdv~u7cgItTh*%`U&4HD9+{reU}JpN|3u4G-7a4xU>i+;p>;d2?zG2Zrt3AdWlx!O$3IO@jH63GRwp<=?_ zBNS`VR{MS+0Kn}N)2)BfL7o230O}Ueu2v2K>Y_KGkWayd81dz505Ov;=WeuJXu`40 z*lk7}Ug{nsB3}{19)7f78orw3+Gk4rR1a)5R>S>(H4kw~gBbvFzY$u)15q{Z*L0Yv31PaXtbKiqRlcBB>?WbI%sz}z3<`WJP@{9 z05FM|>UbK>G<&`Hg6=kSPj8hW*^*i?JTkl7uEG zs2lWGQ;M|sT`qbTcZkI4UJVfN=37rHAZOhDH@Q3P#aQG65V4eEPrp4cL7-&X-05$A?V_cU%zu?>KtIY{GbtK;HlA(eCri$oPI zewIuRqQT!S;?C>tRHhF6)1!r{gYKB=&KvNkxMQORdE;vx!CHApi?=shJyBBzfaOCh zN)bxw10o#E^32E8wMJa#7=9Z-xcqoRD(~st2pW&~FidQ9fYZEfKYbw$U$B+FUfp+~ z*{PXJy!0DCi>#*WAUhG!hXbGXYxyxuj1j+@nBCE&YjxLyito5iYwQ;36FA`Y7G4h{ zjXH_-Cd)r%C8rxTs8 z1WXwu`5E`oImB!6K&ce|>Q0vPix;ugO#5)_&n}d2|RZmB+$(Od6-Zjeqzs}JT>E*&(f>KLu}gCtpIV=E)2@) zUik!L>)nR3RW7sXHFu9@W4(#YX>P&!dgf5?2mA#T1j8n2K@N=^Xt*g z1Pn@iICh~M{oz8#E~CAUG*W~jV40fo)I{;85s1>CL|q8$(has0wx*HzyoIsSp(j&| zpA&`~uM_NJo`y-Wu@}BD>XDy3@UQpuY35z)s_&W;~lLWcCUMFY0%mAgia5<(M>`|J)cK*GpsioJdHKIuf`%)*5!O zZR4`;>exO*O9(r6z8HRV|HD$940|MHDA)dmzGPj@pe*^L!p8GV-VWJI+%4y(;hF*m zNYKe%cKTx4H&a6J^4tG*J#@+`NR?Br59NiVGq3d4 zOj_|YMe0p#UNb69-B-_@M!p~VA9t1vavUE0+gWfs)+JE*p}m2B`l_}l;wq!##jB;~ ze{30TC3S=e-9`E7hV6_?qfl|U7t&C;{a)e>Ps)7Rl{QuCnfC(nlslZz(6^h8HafIP z#F2YO4TE*`{i9?r#~lL=NY=>JlJMPKX~UJyw=Q@Vt(>(d%_{PnNmK9mlyh+Jwnc0u zctTq{TDXwrJA(qUq3;OF?j+wH=l@MJpLxH1ojgkr8H z-S%|EjX7s4mq;?a4xIxQw@;@e@iRd!yB*ic5(+?<`oFc*V zHUoIgTLd|ZS|#cG(k=bG-RY$*e8*KYoaDQGulB08PtL1)QMZjI%K&DDUj&Js5kiiA zX55g1w8s0Ee*f&0G>Lj%)$t7})CR_=SQ)TNhs;Rsedm#w{80_nTECDmCwGfikg%$Y zmE_5bkgG$Nj_GjD`!_G#b#|5l!R?-Qj_84}c48c~euivP*VErOm?o5kBD|F9vP*X{ z^Er}+dOxI!i%YcSZ1!{kc;cH1@jB)=|6&Af~1{vlw^>!!Ec#=6J8?Lf}Yz(?Z<^Bo`Cxz-~a zFbf6BiUN^*pGODvk8#r~_3847Ow*1Xv+$D4t_oMxm^HRtG_PUap6e2)I?v6w(`VoL z9Z(fTrZn6ix0*&bjV-9|awR8&&x*o^tvpfd9Y+H_(23>X8YsS(>(oEqaTs;Z^1K3I z>gl->yW~Kf!$K{d6m*Gir*lnQWI(aZ*}A*nmu5z7EpF|s<=folnv;Sm^J|3 z%B>!kCx=w)luXID&TYehZJY$8)!nDru=%pt?a2YD#a($`>3}KOiA`)d2Qv9&2geQ@ z+ThVyKVZ^X%`DiKQ#QM)(sO3p%yGlXCxk`;Wz1*@<(exOiqprRi);Y0ScI)_J#qWY zY9_Il7M|Rh<<_o3N;yRVxr9m0SFLw7+1Il;<^3y_R+BVfz3ZmFvO9w~aU1M;uv?hKnhUyT$?Q{i!9$h` zw1~M$#!N?vcC63LEachrog(CExm<_h(MF=aej z8imU>DT~uNr@cIG?3|u7gNhpEyylzKKZjFiFw!s)k3UrH&NtCfnsWBhKf%{YjYow2 zNZQ!kai16msLRv(0;@c&-L)O;Q7vh@ou4NBx{x}I;y44IIH!am%3C@w^BkMT8=d9f zzO!t*fk%(2#qy#7jI$Xjw_q7#*d~F3@<5)Z2tO8yp(A|9 zZ$`>;40T6yt+zJnU<$Bf1GeJWT{;=Ybf3Ic9B(zWgGz!>U1} zqu_F)Dh38|&B92btrq8vP21|AA7Gr*iptG;=JHi&@LLV)BVOQ197vn@`A8)@DJlGp z(+qpme3ujNLG~I2BjQM5`0SnDuan>I?n^A3^R~lgnYqZl-CgO*s(0Qp@@}sDH#p3V zBLA!HnZSl8jzeMUN?0CKSyi5C+fm@e$GiV|8{Ob{0>}EI3Z0dP3H`#^c9JXip43pe zufpWmNI5=!KdmsQ4%k2OXIF9+SFwiH_SaL(Z}PaACfjD)>%7JIP;ufhZ5mq;mZi;! zi87X9ykKg|J1ONXXSr1MebyVZjIcpo%hA&RURW*6`8flQ(!n-r7I;+I zV{;X}9ZCkaEFQ#8b>u2H3Olhgzr_S=Wx($@B=Let=e(KpxZH>$S41CbNJq&oVsYQ? z>jo!l0KZMAN6+5YO}-_fur>Va8=b)L)79k|%mwOmRye7TN=P+da3$wWW;=^$5>7Fl|*%gWRr0=p23$iIs8y zs@^|}butoT`xwHn;DHvGj`Q}ZdycvkA{!tt^XsiXV#=oFLYH(F-u8VG?x^t&@Z}l} zdnX<65}{TjeL6tcd8aD_9wSw4u^n1V+cRXiAGo36{-YLIJ zx`#Ge{anslWvNHwc%VaDGR8kCN4n@P4~QO#CdKGfXLxnig{DFrtx>*!q4&_cL_#l& z^nlt1`!wmlo}bM(ow7f>4I>yIYmFjcft+uV%IOb9mn#dLm@6jp=yoiB1u@ZO7 zqW*UF!#w6ibK8tr9DLNMvu2mD6KX@(7ir<4nx-h)w{x)7*q~Jsr^BwdrSybU;h^5O z-wgqu{CDt&n;Yew=}Mw#bgE0_P5XKgtVCH`5;Td2^%N-?Xh5hMGhM~&qvJi_s4O#4a4v!=?WApDK|z6p zO&s8~@e;gJf#nprh*gsTnXYjfffL~nffhL7H#F&4$%WzZgy}-ngtvN~Rxy$1<2Rta zc1<-=)wWsbT3SDEJx1Jz_F^XDv=D^goFF1O^cGX44^Jec&`yz9FPB6A#Z82 zhFP|brXr_dT;ojgG!)~RjLb}_94Fj+0)?YQ6LLnoFe8P(xr!L3^=M@Y8pzi;ZSlbG zV@iI?Q5GEWTOxqC8s+9R)yi6|#q+m@E#}RhgM(`ACOop5NW-oKJ&!$=5SO;vjmYti4W{45`fV}7tbapaeYn<-O0VoUcHkvvg6Te&wbM^{T83EIb zMJt;WN1Y-)&GH3+>s)8Kx1=~Oo{+;JMrf_ssPbqw;%_{^DjDs@knK1qYz7Vv_wEm* zF^%~AHXIRw2yHT}2;}!%Gn@2r1M-f8S1%``lbj9}JR{;IvKU&hr%my8;<+Hr5tk8k z%7D^>e9?1}x^SVn?G@^Bp zsu#KO`{JPr6mV!NrvEH+VaX|GVD)fsXQV8cR`zpDH`jzt6RG1Q%HH_IMt3~l)E;B- z$>j->ozHCeQu9cu_(KP#sO72WG0*A<0r`-6e7{Nq7_!K@xhuxnyz>!O!gU&%{9bkXTwpy6rG(nt=eItNy%!$oG6&vofh?w*+NIA z^p|0+0Vus))g6Y)-T<5K(6BUg90z>$7`d3FoO3AYMH|KmRX*UNv$!ZltXy!yeKt+* zuPF>sm3OrPA<2M3bSG*bWsF(l+=L-E@scO*@%O{vli4=nV7#`S)f8TCR8U8GjtPt$ zT4B`rM#(ZN#U!6AR5%O>Drqv}2;{E8l0;M=BWlNOZxP;czcQPxK`(Oer@P~qjTPU> z1=2f_00w+51K=mKJq9rTh5RzdVhh74oK8!ALo0SdFJAntN>tzXm&)eZkv%v?*xHKg znMpBNOh}V#_T7O%dT~S(^nR?E4nW)8VJT1?B!be9%don_d$4g89nR3840SQ5=E06+ zyq)2~dLG`66*OZ!K8UsuBdv^ljryi7j46a{N6^3lSySFaO8vr(DBv`xsQ!97UUe0x zQyy)Ur?YlP8t4ZFkDj-o_vv_wR^~t}M6avV(Qy_?Fv{}xog;;7Deg2<#Eec8T zm9^l;T8N|t7_}u%qnMw5*QXnm?zQsG$v1Pj7=ppn7oWtGDE@O!^YBj(+zm3&135C# zfhMPo-t`wNHYS(EYn80pf8-K)(kQUVT$m?8a#f1{uAzhRsI-T$KSNkKJZyrg zrs5^Zi(T`9ugqe1v3xvRL1Y8L0}6XrT#W}IN2PcT+kE^b&k}<{ET?iBFbjoWUjWH! zZ0yrzsg;BrT5&Ezj$=T35g_B-@DdbcG(oQH0kNQDf>6%_l$NQgEE*K7wXu<$u$XXb zbox~4ikurrok_t~K|exYx|>j6RJNoRq>5iI$$tr`p4GK6!x_pS3fRSjNis}3-3I4t zp;aR)oL1o=Eu6{1Z!FBTb$OX;58B;OSOCd#&N;#~2L2-gY)qx^L1lAPz)}&A%1}nK zA+Qxhr>SD4;JBiZN)8aun_avA!G+_e1r3>{RCI#!Xih%5Y?>*Dfprke{KcTVxp2-I z?6jz>oF;V7H&sDfAvyoArdc+K7wz`HUEX^6}U0qwQu*G$#;{`2yt zqsL#UmZ3#b5%zh-8xkFlpfX$TGQ%@CV-0yv6BIm(A`%ladW6J958o@cN{(*F70uu% z$OH4*Z@h^RzBv0{&*m%-2`X_nV^*25-%HR$#_yoUyu1C>%KYZqf5ip0*;6D|nTv{@ znq+(5@pDW7k`Gv>c~94!9Dy$()ACUwH_M(4PUpz)cFV-2KtnZqc~ zVZ3*X!@JVO3g8W zga4J`%$T&_8uCfp=YOR|YWa+OB?U;c9z=_%glE_7_gqprap9DF@T~Zw0(=``SiQ#t z`RZj1i82!RX`4nidRTGu63v^118U`a6HayPz&jfOCj*3!F3!>QGPm6}pNn!eC@eU$ zS(FvyteuD~&!wP65(9qwfXpsgMsOf|10W44Ea%FsMuD^eB*&o44#169SIv~lU00!Q z#q;v0Mw|gIwI^>fC*N51ao`Wkc+Fa$0d%>lNHT)jHC2X=fcE+8inyTth>V!O*f9x= z<=~uY@Fv#b+goqD=L29)g7d1E;EGSoKzP>ofg<%?iV8O+`J1E-JKpg5GOd`%`>K6V zSYNLEY&YA-tXRo{oY_TGhXEXKXxIB2Y=Z*NdRl3eq=gWsa}*NMwK5)lx>`OOtQh?R z6J{v(-&pBa`)v`c*hUN4*UGERinRxDCgXrRqwo^0G&sQG(O$bjX(_mgUZDKRRA4Pd!z?o>e>$`y!$( z|5y?pYmmjWa?9@{cB~Cy=t5`&UAFBbIk~9gx_Ue#ZUW;=l^Rb$s5vZjY=b<0c0cX% zkGi!gnia6ol(qTfiZ~a%O)@kb_OH4LoQLAJ9#JgMS4z<$tO5V;IVximuorGh*ZkOK zf_+%%YU^Usz=qD^h+OF?p0N)n0jRW`j3U%GA9XZ=ZYJ5}BXM1eAS}B6d=KKIE$qFq zCGjRoNybUmR{Dr#R$N(p?S|LCkoBWN%k$M}*I!KUCB;iNzN~cp@LTkadx@6cz_<>q zDfz(9RfAZ=*V{cRl12s_&}B=%El)=6wAmDQ{8Gl)S2DV21f1LSv`lr|L7XRWP^1If z47VkS5d68Zc+;%(1)Sw>fGWbnX>0=fB&$P7beNnyVs`IRS&u7C49?oADzS7eTQ!tX z*RA%LQSG<#lUH2TAD@mgtVKy_ISVQj}P1y-AJVPa$3tBmp9E>uxHcjmA8^MMdb_&3i7Zc z`y+xil~$q2Hh9|P^4q*k?4u?S_g!WEYI^WvuzP&C{l6ykYBxt@3W7Ib;a*|dKI;D4QZnpU+YDb~(pfS&{wLflglM7M! z>gvha%jyx^Oa6MA=XW&VTI+M);ixG$PD}hRy!+dE4%>#DCw4!z`Y3Y72RwW)f)m(AoBzowYE_}i22&Cc%_x!_p>bjH+bG@4@%9mZfAM%&Og*RVv%WK|;cd6X0 zKLQp$kT`Hk@;e z?@guF#^{57<1C)aUaTtgMCl$w`EuB)o^t5~Y!@TqU(JoA1|{pu>21%Lq)+lKV!)0{ z?^%|d#?#+rt++X%cvTU`YeGx)_ zs}ABWayy(J>N}Mx!1jO?Wi5)GN>M?xcL`zqZW~|%%A?q+qCVC(A#s%y4_}rtAWDzj zQ<8xa_12_qIM89FgZ5O1n@wu~a9?Bv3HdSP17K{0A4tzihC>|%l@pr>kxX9W`O{|k zlY{)q^K^XBW*xMV`Pprkx{IPgOI1a0p>%|eDHcI%lLMXSiG*-FfX^E1q_PUr+$(dg zmIS6z4j7^OT#Yg)umN$Os~7C;R3HT!;D;qX!=8~=>@+r68fBLPJQb_584YBzViok`+0N}A4OmR#U*=I@Td`nJcKw!gf587_$!~J#RwI&!G^~+rutOPKclVnFI z_}eOErH+X5#XM?j0QxQ+M7#zSWK2s@0Plrc!axUoTGg%UCBW=989-`A(cxPTnFZqa zY?nFI0-=L*PtDZ;ldgg#bs$|{ZwRwBQfpTQsx>qjR7z6@vCmyv&=BK!HzV!ml8*CX zHYaW_Hy34_*E2{ZrIz4-0X!Eoc+AFdrKAxcZum0fXv5+cp31C{2T8n$8lMp3>yvIqapKr z>yP;WSYZZNme47^y^gz&{BW#X5b=yreCzM-ya!;nG!%ROR zykA=w!&1~mj|5~^7F@)Yr`!G*_m`=Thq|m!9&#t;1;-ifbD9V5lM#XYJtH(XFx{H- z`2FF2vQ!$im)w?wOm-RsGDSjK#ef`|T>7#8a{_agdGuzK&MLVVb#Bo?u=gO~+#{-a z{QQd-jgHu8FR;9MQSMG4=F_-?1eK&KU3ZTl5D;$|SL4pQ%{J_SNCtSVNEHr$$rRc$%kEmlG3Rpc&B+gE%x7u*|r4^`vsaW)0jk0k|z^@IT_JKA=?awhSIpEzUN2j)}?|;Nly{E5bh9ZSN zMRb6Q(b*tun6!Dx#;8_LyyrYsP}7`A5z4USNETaf&z9Ycn%{`s9oZ)5)HywR%bVuc ziA_N#Cb9lL153Wy7bi%XF^P{c6fu0}z8tD9`(QG{tWbFPnT0&M@DZ9}d-^}LoF zC7YxjDBa2%AF(@9g;uP7xVbO}Mg$Bl{2(#G=Pv3tDsy?7b~{DxMnfa=T!zd%cMSh^ ztZDiv5MnFeS*UYP*6s9*q6T(c-sHTl4I-#{;p*#ur?76V^tiwvY#NvyTCSVYthd;8 zaU}{^Ct!#bsWl*`4vq}e(RuwqdFnb7|_uH-QtQ! z8v~DBtGmK4<7Uc2M;i5aP(%fo0-~sD8R3h^z4(6wQZ#UfEHF>u!z|&l`CqnXrUvpS zB7&98Hk=0?vAkja0*Ux=gXo(j1mg}up zf{EP7mxXeM*RtMPg-zyg@*kz#VV(_o$e1agFpxnyzsyFg_o^Kh1_Bab4eiIK^w3cLccnoGMHeNnr!8IOIsx3a_e2 zn*yJOqdKPuermFiT@F~ar}IYv53y|g0LzePou0lz@-_x;?L-Xd1T}f$uSj_Xz(yfj za^z<3-^NnK^jUQ-hRjHeC@Pa6*T4W-=cPToZBa6%yp#L8U%Ad^ly|>GXZe8w0O;5X ze71|CsAbNFtE`wSgafh}b4Ua-u;1N47QupHS#pu&!k74k!4^JMT}d|U*X~$WIjf&L zvKMFt9Lss(DWGHg$k#wUA$yk4pbNNq)oN5R{>$>%KpwW)#YX2^E$@?)4^1E+dgX<2 zt2<-`%(g*vn=%GZ0 zibvD@%a$wC3d9I!NZf+pRhVJv0X>L1Zb2WH3m*YPs~`30)Z5^B?;Z(#b@ zmn$gz@X?8}<@^V~bHf+@f9W@<*&R>>CvH?`YdrOsErS8s#nTDxzlW`gJS&N$Vgznq z5%9Xv8VOP6uYzlxPB2o|P)Y#V26I%KfP|@r3p(txW#gKX zCwswu+=om&2!(eM&<{)UH7O|&$AsF7Szcb<6%kjsV;$a2l*o6{n_6`@Lw7NkGz+^j${<*pg;=NfcQ z=!s1^3Rr}~Oz5?*a=cRiu%*;S@*AMZ7+FdiFVH0)@Xwah{UE!6q=iyFsCzMW4>7X+ zmd`Lsw$%qT^I5C)He8TG3;HM9_lY3Yy8v>08)rk4BY}GNu|4A?k@R>!!JQ5(^``>A z-3ci=>hKgh4H~d<$ouy{Fw+&PAAqw&+8a^tW*vSHiMeQszzjMTbT|cm-R`0Q3^VJ} zscf@gZNX%L0rew4#gsR4)j+^oOK(`+jj)t2Q8XR&7^0eV-V8vm>il_2Um`m#{O!XO z$^vMBg9HV69gyE|5jwQutZA}U)*`?$f=i;-0G)rfQW&?kvXxxM-d#)bq#dq?Of!Tl;4{~7w zUQ879>!jKy@n)BW8u>V;z*E}kBI0u~-Pa3*kx_j3PHU@K#_*G!{iF5SU7Zhel3%I& zpF9mGO2BUIw2f-8ug&)Y`0OuL0e%3nRqvLMg3TLK`}U_O1w<+B^gSJ9>Nqx_jCjW1 z7HJV!7ev+xL9dbg?g2faPOz^)@8$>H$=2a&_1-D6$nsAAChv~&P8)#lU+^JgX?3tJ zIdYh{$C32E2F}K>sp^m8_hHYBZERzVF~;4P2#7f3K}3YR2XH7NC?FEr9U!5if~ldA z-i?WXXo#q2R2M`-G(|*3vVM016%mz;6cy_Z(M-+I$fyi{`xDMN-*aB)`~AE>AMQK< z04^%+pZodkxe}{c(tkg)1@IgD!)N@Q7wy8yQB)c>Q|My>s_;k@;tiOEpVFcR0C3Qx zQ-f-}iY>Rq5H>$l|M}2$&NFSiMRzg0N031VSKU3k4>)oIDERV{o(o7fwXunGy&6TiX86P3r+(6_B*4?!Z*LtI^{5(8@sV zKQ6ja9@IUjsYI8B`@Q@#w&`_xsFk3Rw=V8sjag{V$cNuW-JWG-g;^YFsK+Up&HzOV z^sEv0EPxcBg6815nI&c3$(IZN>*fujaw9-5 zoV%ih1To#VZ~CT1f=gGM@!#X+L4O=S4S%>drey-4lR9pX_Gb6?;A%27L(geLS(pC^ z+O1_-NpXn|(mXLln!$kypQcy^)p?-D%qzJuEtyolD@|9?l&O}W@;JG(83e5OPM9qT zD;7Aki>rgDZJrQh8!AN8?_@k}!VqRrpHdDrEEHGzCL9V1c-rSa&u_(rdSg=kq9dVe zZWXjKTwtLH70mlW_fmn2%h=7ge81 zX)f)XEcx5Mn(#4Zpg3as_?z-g)#QGyu)P#wtEpV;&d3(5vKy+eZk4@jF%w&50ga%w zG4xZrAg;=2bz9tIbSY-k5xe;iVyw#eCtp_)BQ#QVZY7caQ+w&j`Q4J|j6SGb@y|E$ zr6O0E;n0lD<)!tO2^1C3r*)3_xT(r9*0gV%{1wxKk@Bke7`MmBrdAy6nYHBQotu%1 z$9K^sS(pXcl*oeiWeELq_e@i({n^dY2&4>0pMhUQwNGqX;@RVfV=ijAy^VGppt zz1HT84yG_HMKf+GACg&z#0 zJ)VEKb^dd=nx9G>Bfh&>LlaafI`le}wG}l#o|5jK7#Q6X`@m?gw;C{8FQ=Xy=vj1n z_7hg*VX2{GhET3n%p(^AxVg-%eSgkw7SI!2azy#5XC8|%1Fb_(%+YTs@aLV4ZTG#2 zCzsVsds(6R$)V3rp8z8`0$XkF1{$;0+a2!)GhMqd*uN09)$Q&%OZ+eMLipJ-Nv@!j zCYp59*QI_@uD7j-`sWwcfZcmQ2ZBA7UxrHKWu(=7PRe+guvOr!;S9yCE$5 z@cFO38YCt`$h6&$)R9(VdyKJds#;K84427L#~$A)T`S1>oPF(ePJiU>3KhpqUEfd{ zIDF|HZAEegcu>?x;k%Uv>T&%Si&jo!G@ju23|)+H>BLf7mJx=#$_4->kdX{MG@4hv zO>33@_x(Zb!~iZzG|L8!TFCtz&y$rcT+my(Vq9sC+I&JTLG6Mt1pGwa$nEkkogo3} zbL6AKnsQK~IPV?PLeV{}2O|wCXck~+uu>Wi2N$s(e{bbK($Iuii0hJQjK4aAlID~G zte>WNE+i5-RXvu7y^q0Tbvku3P#XC1cI2p38@P1;9ubm_JTKOkPTH97vuxh{XYsy) z%H2DuV_s8Jl-+xhoM$O)FvW7KcWK^+#p5S}0IN6MD^1 zsWS6>7;zfVr&>S-fpc#E*UcVHlr(odc7j;#tHaAdh9##_o^PT(`b^*xsi~Tc`3gTS z)<^tAK_!KF?M1`q%C9LGOBLd|u7w>giBtHR31}NWeOFSUwJCrLJsQ%p+Rrlc-sxc% z((IM3+P91V+z$(wv1MoNFCuNcxXm(;4Vd-8-d-_<*y00H%L;2snQ8voDfX?FuxjkfrcXy(q;werqtX*x87i!gCKFB!d-owoJO)3UG&@DK ziJkN3FVMgfXB^ibpj`q!PWY3P-2c{)N$P^Cr$TBL`BTu5{HK}E9hPrHJnW%t zboHz*|L{Z;YwpD7?nopJ0qRz%$g=4ip_ARvdc@*C7!RIoL!kx_Em~mc+0PD^f}G^? z-ywrp>E6-cGZD~B=T=)6tZXdVv=l^MQN1-J&K_Q!ARvri<7U8w;=< zB}VbWYKyr8$ly_D^lPyy#np?l;^Z>_!U2Z6+`zx-45iSVirG?4_ zU(Yzc3da*}G%|VvHVNcDB1YGt4mN0hBF8#2Bv5EXp+pDbbat{5`jJF0PnIY`* ze8_hLfgJ-rf;KFVX|n7$Jn8U9{%V3#%*^jl+DxmKbx&_U@3P4tBqv|NIOHBhFg#A}~Qs_&!!r11n$Yq(?eoSv0{~{Yz*XNff`KxbZUUE#;TA6fVMG9z^d%qc5_EJ1=1Nf|lnk$v=RjQ2Ig>l< z8z9N~CBN`rbkwcXYuN0jTmJ3VtJ?3Kgu@$wl6f{U6pfB(+}Wt-b}f^A zo&OAhqcHkW+$|GfWCQ&Q3#(q0kWYy#li8nv9ucG`gW|PTbBX}oAu6gz>p4uiO0~L{ z20-w=`l{JA-^Q6bblUGFDK_GrqzQU9_DpSe_oo=y6nzA6eTBM3FA+T4uZefG$2-=r z08uue$f8^Y2&b5O+iYVc;}_+lw56cSooY!nPHUmKlYj!npfLlSYUV^ys%%p6QVY?H zs^^3Z&?;Ufi#fk@2?tlB;qN#cLtC;|(s=fX@yk+)uz^m^@v}jEeJ&hxn~dXL=vd*Z@y`XF?J|1)>Z-sbLur zVbp*GcX-+Fqz95ldFA~)(mRlXRV4K6H=kVG8(&XG&Js1^G%3n{w;qvU?gP%_qTFA$ z1>~HY2H{By_XR%5WtE-bwqpEh+_Q{OY!E8Nr0Vx};Rb+tiv)i%(T|!rP3YV_NAO0# zGr$5&0-P`hGGJmV4j@T@;sWYk?nZyt;1+aZC`<{@COo51PU6gvUb7%w>y>9=>WDbp z4;Xg-DyWaTDkVlUJqUX+X>+euPET+0z;W+S&7eT*H?5Je%I3cp9my5xS7)7*te{hPbRglk21GwbXoCb4Z}Lb#&aO5I?-CYH zqemMCjqg((C0SW}A*Tx?v^FVi39U)##i9I;*aTUW&Q-M-GkDM5eS?TwjtRGDxb`?pfh^(TaHW-qCu z1VJX5JUhS6>9hp8PHpb)s-&v`pqTjG3^l^Y(lYKi)#md_Qzy^g zoLIwRoJ3klL7O?$Wd!^Qqe8&ifbUfsDKZvg<)UjiNN3tVc)X-^Sm4^Ee3 zZpq>BIOS7=73P}CjBf^@6>1IUbfGLx>c`BSh=+NELV#awCb&{IeKWpH`lFkiblHG1FJt5W z7H5dU#exrbYfZeN6saAcKL~}JNIt_Z$#6@1D2n;|n3H`DnlyQI1v+;mCS(_zShQ%3 zS%RXA^th|a0S1u^eX*I8pG26a>cMrt1KU|D{?taweKIwV`O%+!CPpF()trOHW;DHa z*?5Cwnod4O!s&-pkqB3fB!rT$-Za2R!OfvKFFkEuY8da%@mN11%0;(j2fAqId1%tj@S^bfzwVoV|D31BQQy%`i=qRw%f+>SA{Zgg!!vAeKT=WK1MK2=4T7*c z%3uKc9=*>S;bK!H+Aa{y%a)y@wTGx0b(roWW4;xYW&)QS4;f$8$VP6~3AtkkQ(4 zs~~X04GS}dxGe55mMfKI1nnnsvm)Cg;=*vNoo4w(nRlBvs#OG=8E;JM?!nFn1sVnP z^=Qejc-7&In)j|U`!z1fpmUKT#>upK$3;;Tf9tEr8F8M;2h{y0dPdQQEB7ZnR`G{$ z1xnI2Z$FB`rJZZvpN6oyI9|t_xEC6@#x>p?>Z2fZUOHCVpoG)02UoS+V3K!L=`w{Y z6TFLS&a8Ofd4F8&?xY!%5>cO^+qaPDA*~8DrEDbKvU>GvEILeqSIJmp(zZaoTzps$&TPCDU4Hk}4O8Tlgq{-yP_&}98 zU|eY0vkMMBFenLPosOGRbLMFK!5&W(=$TY9aXh^dTe$^?D&HaoWc6z043&qH3kZWd z7}bAcu0;7etaRFY^U7?TE`%Eh@&sB}|EIBElZ3GVDJGgO=Q+J{^x5A;X_T*KqwdIu z%v3Y432UG6uq!T?b0|uAR~zN+xS`7SUW?zT^2hWWJde zXmeAD8A%j8c`i0z`J&9UFw@qyb6?Sg$51*_wJvHPOvw($&YpQ_yXeb#CspR6`8h-GzVF^`ppoF14PNXh7?p;adxGb?UCEX89o3O^i=THfDQa8!kpJDy9+S6>$iA+n$ym#-YDZ?7 zN8FDwqA^irIm2KBBnZ20SXrP<_?0+#0-DoO<1M-JH@DG?aH0nt%PNgg(1v0lNqXr(-k97for@fo>Oja(yEkL`rS-oG^UR`}oqtWIF|g*JKG1n}ldls9@7D8R z6bX|%YlF4C=j6?`q>Hny?~8qR(yjq4@cHN|jx4%d(_r7lb*U_rJoRK}pO$4_E)O|& zb+24hxv1Tib#1?TktAAut*P%|&{W0Wh6R254uwsvdvLiT^n)(|x=GM~q$rEf9N59) zsGmELher5md)aX(}vcBqO^`o9WUa|Y4=Vr%9R8}A) z?$Y?LgD2nn-;RMaD}Q|O)D0Gh)7SEgvDi;zzWwLV8NMribr$pwWhHOgQjYoQ{Qr3Q z@4r*;KZ-ni_L_~Ep7C1CIS>*?^ZM(ojpoeQGMc8=Z*6j_2+?iM-%U^IS;4a7!^^dq z?q8H=SDM2$ahxN-1j!8Q?Y*koHleGMx#KM(>mOJDkW*dn`npkU74cmFn6pi+3zU5NRYtU1@?kVmi64%^Ob`K?ELZmPM6g$vQjGG zt@6}s)2-tb`6o{&UC{?0d*{rKVHOc_icSArs~5QT3$*;-S5(uX0z#>SMQp>t z(QX%6^uM1%tLg?`o_w%j-7>!=0#W?bnyK;+Es_(jqqy9>C#E=7fjF7`gg${Dh>Y+b zTf&<)T08UNTVF>Pdr(uRP zMekSnxNnwb(cK?~E#^igBcE#j+mQI-&4ot*AiBxw#;%M`)%afK|1!v?&l>o~z+I)e zW4)OayMCDh5ajeN5!b-o%%+mU>;A9XUjs?)S*B{p+JmybOFnZmBEg<~>1S(6KY*96 zweH>bNmSYT1B@9LU5hENZ|7cvf3pfJq{4kQKR;rnlzur2K0VqUW_f?#HvNla(L(Lq z#D*(y=$A||{I3+)c90PcT>4#h48Oh7y7 zZWJ9z;-p2!J`yy)U>%S9`8@#tyJI6xOEij4xmEtI&XsR#>xMgP|7RR!0;Xekb;IUp zm#WjayyKCegS5If?&ix|bn4-T{Y5CXF8Wu(rQw>jr|5=<8>Xk%{$-bQZZYp-5N+iX znElgN+oOU;ekdbb*H=6S=N4Z3yNY$ie_>H&>ZwNeGv!x;))wu_dfDjlKh{+z8Zz(y D(weWl diff --git a/samples/oauth2/tonr/src/main/webapp/index.jsp b/samples/oauth2/tonr/src/main/webapp/index.jsp index 2e4829d81..7b699e37e 100644 --- a/samples/oauth2/tonr/src/main/webapp/index.jsp +++ b/samples/oauth2/tonr/src/main/webapp/index.jsp @@ -1,41 +1,73 @@ -<%@ taglib prefix="authz" uri="http://www.springframework.org/security/tags" %> +<%@ taglib prefix="authz" + uri="http://www.springframework.org/security/tags"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> - - + + - " rel="stylesheet" type="text/css"/> - tonr + + + + + + +tonr -
+ - +
-
-

Welcome to Tonr.com!

- -

This is a website that will allow you to print your photos that you've uploaded to sparklr.com! - And since this site uses OAuth to access your photos, we will never ask you - for your Sparklr credentials.

+

Welcome to Tonr!

-

Tonr.com has only two users: "marissa" and "sam". The password for "marissa" is password is "wombat" and for "sam" is password is "kangaroo".

+

+ This is a website that will allow you to print your photos that + you've uploaded to Sparklr! + And since this site uses OAuth to + access your photos, we will never ask you for your Sparklr + credentials. +

- -

">Login to Tonr

-
- -

">View my Sparklr photos

-
+

Tonr.com has only two users: "marissa" and "sam". The password + for "marissa" is password is "wombat" and for "sam" is password is + "kangaroo".

- -
-
+ +

+ ">Login to Tonr +

+
+ +

+ ">View my Sparklr + photos +

+
+ +
\ No newline at end of file diff --git a/samples/oauth2/tonr/src/main/webapp/js/libs/json2.js b/samples/oauth2/tonr/src/main/webapp/js/libs/json2.js deleted file mode 100644 index 2ffe91c7e..000000000 --- a/samples/oauth2/tonr/src/main/webapp/js/libs/json2.js +++ /dev/null @@ -1,487 +0,0 @@ -/* - http://www.JSON.org/json2.js - 2011-10-19 - - Public Domain. - - NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. - - See http://www.JSON.org/js.html - - - This code should be minified before deployment. - See http://javascript.crockford.com/jsmin.html - - USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO - NOT CONTROL. - - - This file creates a global JSON object containing two methods: stringify - and parse. - - JSON.stringify(value, replacer, space) - value any JavaScript value, usually an object or array. - - replacer an optional parameter that determines how object - values are stringified for objects. It can be a - function or an array of strings. - - space an optional parameter that specifies the indentation - of nested structures. If it is omitted, the text will - be packed without extra whitespace. If it is a number, - it will specify the number of spaces to indent at each - level. If it is a string (such as '\t' or ' '), - it contains the characters used to indent at each level. - - This method produces a JSON text from a JavaScript value. - - When an object value is found, if the object contains a toJSON - method, its toJSON method will be called and the result will be - stringified. A toJSON method does not serialize: it returns the - value represented by the name/value pair that should be serialized, - or undefined if nothing should be serialized. The toJSON method - will be passed the key associated with the value, and this will be - bound to the value - - For example, this would serialize Dates as ISO strings. - - Date.prototype.toJSON = function (key) { - function f(n) { - // Format integers to have at least two digits. - return n < 10 ? '0' + n : n; - } - - return this.getUTCFullYear() + '-' + - f(this.getUTCMonth() + 1) + '-' + - f(this.getUTCDate()) + 'T' + - f(this.getUTCHours()) + ':' + - f(this.getUTCMinutes()) + ':' + - f(this.getUTCSeconds()) + 'Z'; - }; - - You can provide an optional replacer method. It will be passed the - key and value of each member, with this bound to the containing - object. The value that is returned from your method will be - serialized. If your method returns undefined, then the member will - be excluded from the serialization. - - If the replacer parameter is an array of strings, then it will be - used to select the members to be serialized. It filters the results - such that only members with keys listed in the replacer array are - stringified. - - Values that do not have JSON representations, such as undefined or - functions, will not be serialized. Such values in objects will be - dropped; in arrays they will be replaced with null. You can use - a replacer function to replace those with JSON values. - JSON.stringify(undefined) returns undefined. - - The optional space parameter produces a stringification of the - value that is filled with line breaks and indentation to make it - easier to read. - - If the space parameter is a non-empty string, then that string will - be used for indentation. If the space parameter is a number, then - the indentation will be that many spaces. - - Example: - - text = JSON.stringify(['e', {pluribus: 'unum'}]); - // text is '["e",{"pluribus":"unum"}]' - - - text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); - // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' - - text = JSON.stringify([new Date()], function (key, value) { - return this[key] instanceof Date ? - 'Date(' + this[key] + ')' : value; - }); - // text is '["Date(---current time---)"]' - - - JSON.parse(text, reviver) - This method parses a JSON text to produce an object or array. - It can throw a SyntaxError exception. - - The optional reviver parameter is a function that can filter and - transform the results. It receives each of the keys and values, - and its return value is used instead of the original value. - If it returns what it received, then the structure is not modified. - If it returns undefined then the member is deleted. - - Example: - - // Parse the text. Values that look like ISO date strings will - // be converted to Date objects. - - myData = JSON.parse(text, function (key, value) { - var a; - if (typeof value === 'string') { - a = -/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); - if (a) { - return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], - +a[5], +a[6])); - } - } - return value; - }); - - myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { - var d; - if (typeof value === 'string' && - value.slice(0, 5) === 'Date(' && - value.slice(-1) === ')') { - d = new Date(value.slice(5, -1)); - if (d) { - return d; - } - } - return value; - }); - - - This is a reference implementation. You are free to copy, modify, or - redistribute. -*/ - -/*jslint evil: true, regexp: true */ - -/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, - call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, - getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, - lastIndex, length, parse, prototype, push, replace, slice, stringify, - test, toJSON, toString, valueOf -*/ - - -// Create a JSON object only if one does not already exist. We create the -// methods in a closure to avoid creating global variables. - -var JSON; -if (!JSON) { - JSON = {}; -} - -(function () { - 'use strict'; - - function f(n) { - // Format integers to have at least two digits. - return n < 10 ? '0' + n : n; - } - - if (typeof Date.prototype.toJSON !== 'function') { - - Date.prototype.toJSON = function (key) { - - return isFinite(this.valueOf()) - ? this.getUTCFullYear() + '-' + - f(this.getUTCMonth() + 1) + '-' + - f(this.getUTCDate()) + 'T' + - f(this.getUTCHours()) + ':' + - f(this.getUTCMinutes()) + ':' + - f(this.getUTCSeconds()) + 'Z' - : null; - }; - - String.prototype.toJSON = - Number.prototype.toJSON = - Boolean.prototype.toJSON = function (key) { - return this.valueOf(); - }; - } - - var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, - escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, - gap, - indent, - meta = { // table of character substitutions - '\b': '\\b', - '\t': '\\t', - '\n': '\\n', - '\f': '\\f', - '\r': '\\r', - '"' : '\\"', - '\\': '\\\\' - }, - rep; - - - function quote(string) { - -// If the string contains no control characters, no quote characters, and no -// backslash characters, then we can safely slap some quotes around it. -// Otherwise we must also replace the offending characters with safe escape -// sequences. - - escapable.lastIndex = 0; - return escapable.test(string) ? '"' + string.replace(escapable, function (a) { - var c = meta[a]; - return typeof c === 'string' - ? c - : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); - }) + '"' : '"' + string + '"'; - } - - - function str(key, holder) { - -// Produce a string from holder[key]. - - var i, // The loop counter. - k, // The member key. - v, // The member value. - length, - mind = gap, - partial, - value = holder[key]; - -// If the value has a toJSON method, call it to obtain a replacement value. - - if (value && typeof value === 'object' && - typeof value.toJSON === 'function') { - value = value.toJSON(key); - } - -// If we were called with a replacer function, then call the replacer to -// obtain a replacement value. - - if (typeof rep === 'function') { - value = rep.call(holder, key, value); - } - -// What happens next depends on the value's type. - - switch (typeof value) { - case 'string': - return quote(value); - - case 'number': - -// JSON numbers must be finite. Encode non-finite numbers as null. - - return isFinite(value) ? String(value) : 'null'; - - case 'boolean': - case 'null': - -// If the value is a boolean or null, convert it to a string. Note: -// typeof null does not produce 'null'. The case is included here in -// the remote chance that this gets fixed someday. - - return String(value); - -// If the type is 'object', we might be dealing with an object or an array or -// null. - - case 'object': - -// Due to a specification blunder in ECMAScript, typeof null is 'object', -// so watch out for that case. - - if (!value) { - return 'null'; - } - -// Make an array to hold the partial results of stringifying this object value. - - gap += indent; - partial = []; - -// Is the value an array? - - if (Object.prototype.toString.apply(value) === '[object Array]') { - -// The value is an array. Stringify every element. Use null as a placeholder -// for non-JSON values. - - length = value.length; - for (i = 0; i < length; i += 1) { - partial[i] = str(i, value) || 'null'; - } - -// Join all of the elements together, separated with commas, and wrap them in -// brackets. - - v = partial.length === 0 - ? '[]' - : gap - ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' - : '[' + partial.join(',') + ']'; - gap = mind; - return v; - } - -// If the replacer is an array, use it to select the members to be stringified. - - if (rep && typeof rep === 'object') { - length = rep.length; - for (i = 0; i < length; i += 1) { - if (typeof rep[i] === 'string') { - k = rep[i]; - v = str(k, value); - if (v) { - partial.push(quote(k) + (gap ? ': ' : ':') + v); - } - } - } - } else { - -// Otherwise, iterate through all of the keys in the object. - - for (k in value) { - if (Object.prototype.hasOwnProperty.call(value, k)) { - v = str(k, value); - if (v) { - partial.push(quote(k) + (gap ? ': ' : ':') + v); - } - } - } - } - -// Join all of the member texts together, separated with commas, -// and wrap them in braces. - - v = partial.length === 0 - ? '{}' - : gap - ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' - : '{' + partial.join(',') + '}'; - gap = mind; - return v; - } - } - -// If the JSON object does not yet have a stringify method, give it one. - - if (typeof JSON.stringify !== 'function') { - JSON.stringify = function (value, replacer, space) { - -// The stringify method takes a value and an optional replacer, and an optional -// space parameter, and returns a JSON text. The replacer can be a function -// that can replace values, or an array of strings that will select the keys. -// A default replacer method can be provided. Use of the space parameter can -// produce text that is more easily readable. - - var i; - gap = ''; - indent = ''; - -// If the space parameter is a number, make an indent string containing that -// many spaces. - - if (typeof space === 'number') { - for (i = 0; i < space; i += 1) { - indent += ' '; - } - -// If the space parameter is a string, it will be used as the indent string. - - } else if (typeof space === 'string') { - indent = space; - } - -// If there is a replacer, it must be a function or an array. -// Otherwise, throw an error. - - rep = replacer; - if (replacer && typeof replacer !== 'function' && - (typeof replacer !== 'object' || - typeof replacer.length !== 'number')) { - throw new Error('JSON.stringify'); - } - -// Make a fake root object containing our value under the key of ''. -// Return the result of stringifying the value. - - return str('', {'': value}); - }; - } - - -// If the JSON object does not yet have a parse method, give it one. - - if (typeof JSON.parse !== 'function') { - JSON.parse = function (text, reviver) { - -// The parse method takes a text and an optional reviver function, and returns -// a JavaScript value if the text is a valid JSON text. - - var j; - - function walk(holder, key) { - -// The walk method is used to recursively walk the resulting structure so -// that modifications can be made. - - var k, v, value = holder[key]; - if (value && typeof value === 'object') { - for (k in value) { - if (Object.prototype.hasOwnProperty.call(value, k)) { - v = walk(value, k); - if (v !== undefined) { - value[k] = v; - } else { - delete value[k]; - } - } - } - } - return reviver.call(holder, key, value); - } - - -// Parsing happens in four stages. In the first stage, we replace certain -// Unicode characters with escape sequences. JavaScript handles many characters -// incorrectly, either silently deleting them, or treating them as line endings. - - text = String(text); - cx.lastIndex = 0; - if (cx.test(text)) { - text = text.replace(cx, function (a) { - return '\\u' + - ('0000' + a.charCodeAt(0).toString(16)).slice(-4); - }); - } - -// In the second stage, we run the text against regular expressions that look -// for non-JSON patterns. We are especially concerned with '()' and 'new' -// because they can cause invocation, and '=' because it can cause mutation. -// But just to be safe, we want to reject all unexpected forms. - -// We split the second stage into 4 regexp operations in order to work around -// crippling inefficiencies in IE's and Safari's regexp engines. First we -// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we -// replace all simple value tokens with ']' characters. Third, we delete all -// open brackets that follow a colon or comma or that begin the text. Finally, -// we look to see that the remaining characters are only whitespace or ']' or -// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. - - if (/^[\],:{}\s]*$/ - .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@') - .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') - .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { - -// In the third stage we use the eval function to compile the text into a -// JavaScript structure. The '{' operator is subject to a syntactic ambiguity -// in JavaScript: it can begin a block or an object literal. We wrap the text -// in parens to eliminate the ambiguity. - - j = eval('(' + text + ')'); - -// In the optional fourth stage, we recursively walk the new structure, passing -// each name/value pair to a reviver function for possible transformation. - - return typeof reviver === 'function' - ? walk({'': j}, '') - : j; - } - -// If the text is not JSON parseable, then a SyntaxError is thrown. - - throw new SyntaxError('JSON.parse'); - }; - } -}()); \ No newline at end of file diff --git a/samples/oauth2/tonr/src/main/webapp/js/libs/localstorage.js b/samples/oauth2/tonr/src/main/webapp/js/libs/localstorage.js deleted file mode 100644 index 2e156ab4b..000000000 --- a/samples/oauth2/tonr/src/main/webapp/js/libs/localstorage.js +++ /dev/null @@ -1,3 +0,0 @@ -(function(){if(!this.localStorage)if(this.globalStorage)try{this.localStorage=this.globalStorage}catch(e){}else{var a=document.createElement("div");a.style.display="none";document.getElementsByTagName("head")[0].appendChild(a);if(a.addBehavior){a.addBehavior("#default#userdata");var d=this.localStorage={length:0,setItem:function(b,d){a.load("localStorage");b=c(b);a.getAttribute(b)||this.length++;a.setAttribute(b,d);a.save("localStorage")},getItem:function(b){a.load("localStorage");b=c(b);return a.getAttribute(b)}, -removeItem:function(b){a.load("localStorage");b=c(b);a.removeAttribute(b);a.save("localStorage");this.length--;if(0>this.length)this.length=0},clear:function(){a.load("localStorage");for(var b=0;attr=a.XMLDocument.documentElement.attributes[b++];)a.removeAttribute(attr.name);a.save("localStorage");this.length=0},key:function(b){a.load("localStorage");return a.XMLDocument.documentElement.attributes[b]}},c=function(a){return a.replace(/[^-._0-9A-Za-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u37f-\u1fff\u200c-\u200d\u203f\u2040\u2070-\u218f]/g, -"-")};a.load("localStorage");d.length=a.XMLDocument.documentElement.attributes.length}}})(); \ No newline at end of file diff --git a/samples/oauth2/tonr/src/main/webapp/js/libs/modernizr-2.5.3.min.js b/samples/oauth2/tonr/src/main/webapp/js/libs/modernizr-2.5.3.min.js deleted file mode 100755 index 27fcdae82..000000000 --- a/samples/oauth2/tonr/src/main/webapp/js/libs/modernizr-2.5.3.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/* Modernizr 2.5.3 (Custom Build) | MIT & BSD - * Build: http://www.modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-shiv-mq-cssclasses-addtest-prefixed-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load - */ -;window.Modernizr=function(a,b,c){function D(a){j.cssText=a}function E(a,b){return D(n.join(a+";")+(b||""))}function F(a,b){return typeof a===b}function G(a,b){return!!~(""+a).indexOf(b)}function H(a,b){for(var d in a)if(j[a[d]]!==c)return b=="pfx"?a[d]:!0;return!1}function I(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:F(f,"function")?f.bind(d||b):f}return!1}function J(a,b,c){var d=a.charAt(0).toUpperCase()+a.substr(1),e=(a+" "+p.join(d+" ")+d).split(" ");return F(b,"string")||F(b,"undefined")?H(e,b):(e=(a+" "+q.join(d+" ")+d).split(" "),I(e,b,c))}function L(){e.input=function(c){for(var d=0,e=c.length;d",a,""].join(""),k.id=h,m.innerHTML+=f,m.appendChild(k),l||(m.style.background="",g.appendChild(m)),i=c(k,a),l?k.parentNode.removeChild(k):m.parentNode.removeChild(m),!!i},z=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return y("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},A=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=F(e[d],"function"),F(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),B={}.hasOwnProperty,C;!F(B,"undefined")&&!F(B.call,"undefined")?C=function(a,b){return B.call(a,b)}:C=function(a,b){return b in a&&F(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e});var K=function(c,d){var f=c.join(""),g=d.length;y(f,function(c,d){var f=b.styleSheets[b.styleSheets.length-1],h=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"",i=c.childNodes,j={};while(g--)j[i[g].id]=i[g];e.touch="ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch||(j.touch&&j.touch.offsetTop)===9,e.csstransforms3d=(j.csstransforms3d&&j.csstransforms3d.offsetLeft)===9&&j.csstransforms3d.offsetHeight===3,e.generatedcontent=(j.generatedcontent&&j.generatedcontent.offsetHeight)>=1,e.fontface=/src/i.test(h)&&h.indexOf(d.split(" ")[0])===0},g,d)}(['@font-face {font-family:"font";src:url("https://")}',["@media (",n.join("touch-enabled),("),h,")","{#touch{top:9px;position:absolute}}"].join(""),["@media (",n.join("transform-3d),("),h,")","{#csstransforms3d{left:9px;position:absolute;height:3px;}}"].join(""),['#generatedcontent:after{content:"',l,'";visibility:hidden}'].join("")],["fontface","touch","csstransforms3d","generatedcontent"]);s.flexbox=function(){return J("flexOrder")},s.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},s.canvastext=function(){return!!e.canvas&&!!F(b.createElement("canvas").getContext("2d").fillText,"function")},s.webgl=function(){try{var d=b.createElement("canvas"),e;e=!(!a.WebGLRenderingContext||!d.getContext("experimental-webgl")&&!d.getContext("webgl")),d=c}catch(f){e=!1}return e},s.touch=function(){return e.touch},s.geolocation=function(){return!!navigator.geolocation},s.postmessage=function(){return!!a.postMessage},s.websqldatabase=function(){return!!a.openDatabase},s.indexedDB=function(){return!!J("indexedDB",a)},s.hashchange=function(){return A("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},s.history=function(){return!!a.history&&!!history.pushState},s.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},s.websockets=function(){for(var b=-1,c=p.length;++b",d.insertBefore(c.lastChild,d.firstChild)}function h(){var a=k.elements;return typeof a=="string"?a.split(" "):a}function i(a){var b={},c=a.createElement,e=a.createDocumentFragment,f=e();a.createElement=function(a){var e=(b[a]||(b[a]=c(a))).cloneNode();return k.shivMethods&&e.canHaveChildren&&!d.test(a)?f.appendChild(e):e},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+h().join().replace(/\w+/g,function(a){return b[a]=c(a),f.createElement(a),'c("'+a+'")'})+");return n}")(k,f)}function j(a){var b;return a.documentShived?a:(k.shivCSS&&!e&&(b=!!g(a,"article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio{display:none}canvas,video{display:inline-block;*display:inline;*zoom:1}[hidden]{display:none}audio[controls]{display:inline-block;*display:inline;*zoom:1}mark{background:#FF0;color:#000}")),f||(b=!i(a)),b&&(a.documentShived=b),a)}var c=a.html5||{},d=/^<|^(?:button|form|map|select|textarea)$/i,e,f;(function(){var a=b.createElement("a");a.innerHTML="",e="hidden"in a,f=a.childNodes.length==1||function(){try{b.createElement("a")}catch(a){return!0}var c=b.createDocumentFragment();return typeof c.cloneNode=="undefined"||typeof c.createDocumentFragment=="undefined"||typeof c.createElement=="undefined"}()})();var k={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:j};a.html5=k,j(b)}(this,b),e._version=d,e._prefixes=n,e._domPrefixes=q,e._cssomPrefixes=p,e.mq=z,e.hasEvent=A,e.testProp=function(a){return H([a])},e.testAllProps=J,e.testStyles=y,e.prefixed=function(a,b,c){return b?J(a,b,c):J(a,"pfx")},g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+v.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return o.call(a)=="[object Function]"}function e(a){return typeof a=="string"}function f(){}function g(a){return!a||a=="loaded"||a=="complete"||a=="uninitialized"}function h(){var a=p.shift();q=1,a?a.t?m(function(){(a.t=="c"?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){a!="img"&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l={},o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};y[c]===1&&(r=1,y[c]=[],l=b.createElement(a)),a=="object"?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),a!="img"&&(r||y[c]===2?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i(b=="c"?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),p.length==1&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&o.call(a.opera)=="[object Opera]",l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return o.call(a)=="[object Array]"},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f - - + + -" rel="stylesheet" type="text/css" /> + + + + + + tonr -
- - - -
- -

Woops!

- -

Your login attempt was not successful.

-
- -

Woops!

- -

You are not permitted to access that resource.

-
- -

Login

- -

Tonr.com has only two users: "marissa" and "sam". The password - for "marissa" is password is "wombat" and for "sam" is password is - "kangaroo".

- -
" method="post"> -

- -

-

- -

- -

- -

-
- - + + + +
+ + +

Woops!

+ +

Your login attempt was not successful.

+
+ +

Woops!

+ +

You are not permitted to access that resource.

+
+ +

Tonr.com has only two users: "marissa" and "sam". The password + for "marissa" is password is "wombat" and for "sam" is password is + "kangaroo".

+ +
" method="post" role="form"> +
+ +

Login

+
+
+ +
+
+ +
+ + +
+
+ +
\ No newline at end of file diff --git a/samples/oauth2/tonr/src/main/webapp/main.css b/samples/oauth2/tonr/src/main/webapp/main.css deleted file mode 100644 index 8421c3edb..000000000 --- a/samples/oauth2/tonr/src/main/webapp/main.css +++ /dev/null @@ -1,102 +0,0 @@ -body { - font-size: 10pt; - letter-spacing: 1px; - background: url(http://github.com/images/xbg.gif) no-repeat; - font-family: Helvetica, Arial, sans-serif; - word-spacing: 5px; - color: #515151; -} - -#container { - margin: 100px auto 0 auto; - width: 855px; -} - -#content { - background-color: #f7f7f7; - padding: 20px 0 20px 20px; -} - -#mainlinks { - height: 60px; - list-style: none; - margin: 0; -} - -#mainlinks li { - float: right; - margin-right: 10px; - list-style-type: none; - list-style-image: none; -} - -#mainlinks li a { - padding: 30px 0 0 0; - background: #d0d0d0; - display: block; - padding-top: 10px; - width: 100px; - height: 50px; - text-align: center; - color: #515151; - text-decoration: none; -} - -#mainlinks li a:hover { - background: #f7f7f7; -} - -#mainlinks li a.selected { - background: #f7f7f7; - color: #515151; -} - -p { - line-height: 1.4em; -} - -p.error { - color: red; -} - -h1 { - padding: 25px 0 5px 0; -} - -#picturelist { - text-align: left; - margin-right: auto; - margin-left: auto; -} - -#picturelist li { - list-style: none; - margin: 42px; - font-weight: bold; - color: #777777; -} - -#picturelist img { - display: block; - border: 2px solid gray; -} - -#picturelist img:hover { - border: 2px solid #515151; -} - -#picturelist a { - color: #777777; - text-decoration: none; -} - -#picturelist a:hover { - color: #999999; -} - -.footer { - margin-top: 100px; - font-size: .8em; - text-align:center; - -} \ No newline at end of file diff --git a/samples/oauth2/tonr/src/main/webapp/oauth_error.jsp b/samples/oauth2/tonr/src/main/webapp/oauth_error.jsp index dcf5d5ca0..f3a332b13 100644 --- a/samples/oauth2/tonr/src/main/webapp/oauth_error.jsp +++ b/samples/oauth2/tonr/src/main/webapp/oauth_error.jsp @@ -1,29 +1,41 @@ -<%@ page import="java.io.PrintWriter" %> -<%@ page import="java.io.StringWriter" %> -<%@ taglib prefix="authz" uri="http://www.springframework.org/security/tags" %> -<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %> - - +<%@ page import="java.io.PrintWriter"%> +<%@ page import="java.io.StringWriter"%> +<%@ taglib prefix="authz" + uri="http://www.springframework.org/security/tags"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core"%> + + - " rel="stylesheet" type="text/css"/> - tonr + + + + + + -
- - - -
- -
-
+ +
\ No newline at end of file diff --git a/samples/oauth2/tonr/src/main/webapp/style.css b/samples/oauth2/tonr/src/main/webapp/style.css deleted file mode 100644 index e69de29bb..000000000 diff --git a/samples/oauth2/tonr/src/main/webapp/template.html b/samples/oauth2/tonr/src/main/webapp/template.html deleted file mode 100644 index 895b8efaf..000000000 --- a/samples/oauth2/tonr/src/main/webapp/template.html +++ /dev/null @@ -1,35 +0,0 @@ - - - - - xgallery - - -
- - - -
-
    -
  • a treea tree
  • -
  • the seathe sea
  • -
  • the forestthe forest
  • -
  • a bunch of orange flowersa bunch of orange flowers
  • -
  • a turtle in the seaa turtle in the sea
  • -
  • a garden/jungle thinga garden/jungle thing
  • -
  • an oryx antelope in the desertan oryx antelope in the desert
  • -
  • mesas in the desertmesas in the desert Courtesy Open - Web DesignThanks -to Dubai Hotels
  • -
-
-
- - \ No newline at end of file diff --git a/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/ServerRunning.java b/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/ServerRunning.java index da70f9039..ffc3c28f4 100755 --- a/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/ServerRunning.java +++ b/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/ServerRunning.java @@ -1,5 +1,6 @@ package org.springframework.security.oauth.examples.tonr; + import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; diff --git a/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestAuthorizationCodeGrant.java b/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestAuthorizationCodeGrant.java index 09ef83659..9df439cd7 100755 --- a/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestAuthorizationCodeGrant.java +++ b/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestAuthorizationCodeGrant.java @@ -1,17 +1,21 @@ package org.springframework.security.oauth.examples.tonr; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.util.Arrays; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.junit.Rule; import org.junit.Test; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.security.oauth2.client.OAuth2RestTemplate; import org.springframework.security.oauth2.client.resource.UserRedirectRequiredException; import org.springframework.security.oauth2.client.token.DefaultAccessTokenRequest; @@ -77,14 +81,24 @@ public void testAttemptedTokenAcquisitionWithNoRedirect() throws Exception { @Test public void testTokenAcquisitionWithCorrectContext() throws Exception { - MultiValueMap form = new LinkedMultiValueMap(); + ResponseEntity page = serverRunning.getForString("/tonr2/login.jsp"); + String cookie = page.getHeaders().getFirst("Set-Cookie"); + HttpHeaders headers = new HttpHeaders(); + headers.set("Cookie", cookie); + Matcher matcher = Pattern.compile("(?s).*name=\"_csrf\".*?value=\"([^\"]+).*").matcher(page.getBody()); + + MultiValueMap form; + form = new LinkedMultiValueMap(); form.add("j_username", "marissa"); form.add("j_password", "wombat"); - HttpHeaders response = serverRunning.postForHeaders("/tonr2/login.do", + if (matcher.matches()) { + form.add("_csrf", matcher.group(1)); + } + ResponseEntity response = serverRunning.postForStatus("/tonr2/login.do", headers, form); - String cookie = response.getFirst("Set-Cookie"); + cookie = response.getHeaders().getFirst("Set-Cookie"); - HttpHeaders headers = new HttpHeaders(); + headers = new HttpHeaders(); headers.set("Cookie", cookie); // headers.setAccept(Collections.singletonList(MediaType.ALL)); headers.setAccept(MediaType @@ -103,14 +117,24 @@ public void testTokenAcquisitionWithCorrectContext() throws Exception { @Test public void testTokenAcquisitionWithRegisteredRedirect() throws Exception { - MultiValueMap form = new LinkedMultiValueMap(); + ResponseEntity page = serverRunning.getForString("/tonr2/login.jsp"); + String cookie = page.getHeaders().getFirst("Set-Cookie"); + HttpHeaders headers = new HttpHeaders(); + headers.set("Cookie", cookie); + Matcher matcher = Pattern.compile("(?s).*name=\"_csrf\".*?value=\"([^\"]+).*").matcher(page.getBody()); + + MultiValueMap form; + form = new LinkedMultiValueMap(); form.add("j_username", "marissa"); form.add("j_password", "wombat"); - HttpHeaders response = serverRunning.postForHeaders("/tonr2/login.do", + if (matcher.matches()) { + form.add("_csrf", matcher.group(1)); + } + ResponseEntity response = serverRunning.postForStatus("/tonr2/login.do", headers, form); - String cookie = response.getFirst("Set-Cookie"); + cookie = response.getHeaders().getFirst("Set-Cookie"); - HttpHeaders headers = new HttpHeaders(); + headers = new HttpHeaders(); headers.set("Cookie", cookie); // The registered redirect is /redirect, but /trigger is used as a test @@ -127,14 +151,22 @@ public void testTokenAcquisitionWithRegisteredRedirect() throws Exception { private String authenticateAndApprove(String location) { - // First authenticate and grab the cookie - MultiValueMap form = new LinkedMultiValueMap(); + ResponseEntity page = serverRunning.getForString("/sparklr2/login.jsp"); + String cookie = page.getHeaders().getFirst("Set-Cookie"); + Matcher matcher = Pattern.compile("(?s).*name=\"_csrf\".*?value=\"([^\"]+).*").matcher(page.getBody()); + + MultiValueMap form; + form = new LinkedMultiValueMap(); form.add("j_username", "marissa"); form.add("j_password", "koala"); + if (matcher.matches()) { + form.add("_csrf", matcher.group(1)); + } + HttpHeaders response = serverRunning.postForHeaders( "/sparklr2/login.do", form); - String cookie = response.getFirst("Set-Cookie"); + cookie = response.getFirst("Set-Cookie"); HttpHeaders headers = new HttpHeaders(); headers.set("Cookie", cookie); diff --git a/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestBootstrap.java b/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestBootstrap.java deleted file mode 100755 index ebd6961db..000000000 --- a/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestBootstrap.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2006-2010 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.oauth.examples.tonr; - -import org.junit.Test; -import org.springframework.context.support.GenericXmlApplicationContext; -import org.springframework.core.io.FileSystemResource; - -/** - * @author Dave Syer - * - */ -public class TestBootstrap { - - @Test - public void testRootContext() throws Exception { - GenericXmlApplicationContext context = new GenericXmlApplicationContext(new FileSystemResource("src/main/webapp/WEB-INF/spring-servlet.xml")); - context.close(); - } - -} diff --git a/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestClientCredentialsGrant.java b/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestClientCredentialsGrant.java index 90b16ccaa..626b4f015 100644 --- a/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestClientCredentialsGrant.java +++ b/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestClientCredentialsGrant.java @@ -1,5 +1,6 @@ package org.springframework.security.oauth.examples.tonr; + import static org.junit.Assert.assertEquals; import java.util.Arrays; @@ -36,10 +37,8 @@ public void testConnectDirectlyToResourceServer() throws Exception { ClientCredentialsAccessTokenProvider provider = new ClientCredentialsAccessTokenProvider(); OAuth2AccessToken accessToken = provider.obtainAccessToken(resource, new DefaultAccessTokenRequest()); - // TODO: should this work? The client id is different. OAuth2RestTemplate template = new OAuth2RestTemplate(resource, new DefaultOAuth2ClientContext(accessToken)); String result = template.getForObject(serverRunning.getUrl("/sparklr2/photos/trusted/message"), String.class); - // System.err.println(result); assertEquals("Hello, Trusted Client", result); } diff --git a/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestRefreshTokenGrant.java b/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestRefreshTokenGrant.java index 366c4579e..3f486ca52 100644 --- a/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestRefreshTokenGrant.java +++ b/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestRefreshTokenGrant.java @@ -1,5 +1,6 @@ package org.springframework.security.oauth.examples.tonr; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; diff --git a/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestResourceOwnerPasswordGrant.java b/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestResourceOwnerPasswordGrant.java index 1cff142c6..635f7461e 100644 --- a/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestResourceOwnerPasswordGrant.java +++ b/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestResourceOwnerPasswordGrant.java @@ -1,5 +1,6 @@ package org.springframework.security.oauth.examples.tonr; + import static org.junit.Assert.assertEquals; import java.util.Arrays; diff --git a/samples/oauth2/tonr/src/test/java/org/springframework/security/samples/config/SecurityConfigTests.java b/samples/oauth2/tonr/src/test/java/org/springframework/security/samples/config/SecurityConfigTests.java new file mode 100644 index 000000000..8109d3a50 --- /dev/null +++ b/samples/oauth2/tonr/src/test/java/org/springframework/security/samples/config/SecurityConfigTests.java @@ -0,0 +1,45 @@ +/* + * Copyright 2002-2013 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.samples.config; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.web.FilterChainProxy; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +/** + * @author Rob Winch + * + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration +@WebAppConfiguration +public class SecurityConfigTests { + @Configuration + @ComponentScan(basePackages = "org.springframework.security.oauth.examples.config") + public static class Config {} + + @Autowired + private FilterChainProxy springSecurityFilterChain; + + @Test + public void securityConfigurationLoads() {} +} From e1587bdbc0d4b0689f45654fb83cba35e0d3488e Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 14 Feb 2014 15:07:24 +0000 Subject: [PATCH 154/831] Ignore missing web.xml --- samples/oauth2/sparklr/pom.xml | 16 ++++++++++------ samples/oauth2/tonr/pom.xml | 15 +++++++++------ 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 58b891e3a..c62721eb4 100644 --- a/samples/oauth2/sparklr/pom.xml +++ b/samples/oauth2/sparklr/pom.xml @@ -83,6 +83,15 @@ true + + org.apache.maven.plugins + maven-war-plugin + 2.3 + + + false + + @@ -105,11 +114,6 @@ - - ${project.groupId} - spring-security-oauth2-javaconfig - ${project.version} - ${project.groupId} @@ -172,7 +176,7 @@ jstl 1.2 - + org.webjars bootstrap diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 057276026..8bb3fd757 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -92,6 +92,15 @@ true + + org.apache.maven.plugins + maven-war-plugin + 2.3 + + + false + + @@ -117,12 +126,6 @@ ${project.version} - - ${project.groupId} - spring-security-oauth2-javaconfig - ${project.version} - - org.springframework.security spring-security-taglibs From 91490523477144ecf7b7dfdfce41e14017d54ff0 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 14 Feb 2014 15:13:51 +0000 Subject: [PATCH 155/831] Rename Test* to *Tests (Consistent with other Spring projects) Fixes gh-153 --- pom.xml | 10 + ...ndpoints.java => AdminEndpointsTests.java} | 6 +- ...va => AuthorizationCodeProviderTests.java} | 4 +- ...va => ClientCredentialsProviderTests.java} | 6 +- ...ovider.java => ImplicitProviderTests.java} | 4 +- ...ort.java => RefreshTokenSupportTests.java} | 2 +- ...> ResourceOwnerPasswordProviderTests.java} | 4 +- ....java => AuthorizationCodeGrantTests.java} | 2 +- ....java => ClientCredentialsGrantTests.java} | 2 +- ...Grant.java => RefreshTokenGrantTests.java} | 2 +- ...a => ResourceOwnerPasswordGrantTests.java} | 2 +- spring-security-oauth/.springBeans | 3 +- ...java => GoogleCodeCompatibilityTests.java} | 2 +- ...stOAuthCodec.java => OAuthCodecTests.java} | 2 +- ...CoreOAuthSignatureMethodFactoryTests.java} | 2 +- ...ava => HMAC_SHA1SignatureMethodTests.java} | 2 +- ...ava => PlainTextSignatureMethodTests.java} | 2 +- ...java => RSA_SHA1SignatureMethodTests.java} | 2 +- ...ationServerBeanDefinitionParserTests.java} | 2 +- ...umerServiceBeanDefinitionParserTests.java} | 2 +- ...va => FilterChainInitializationTests.java} | 2 +- ...GoogleOAuth.java => GoogleOAuthTests.java} | 2 +- ...ava => CoreOAuthConsumerSupportTests.java} | 2 +- ...a => OAuthConsumerContextFilterTests.java} | 2 +- ...pSessionOAuthRememberMeServicesTests.java} | 2 +- ...ava => CoreOAuthProviderSupportTests.java} | 2 +- ... => AccessTokenProcessingFilterTests.java} | 2 +- ...r.java => OAuthProcessingFilterTests.java} | 2 +- ...erAuthorizationProcessingFilterTests.java} | 2 +- ...otectedResourceProcessingFilterTests.java} | 2 +- ...tedRequestTokenProcessingFilterTests.java} | 2 +- ...SuccessfulAuthenticationHandlerTests.java} | 2 +- ...s.java => InMemoryNonceServicesTests.java} | 2 +- ...rverBeanDefinitionParserTests-context.xml} | 0 ...viceBeanDefinitionParserTests-context.xml} | 0 ...ilterChainInitializationTests-context.xml} | 0 spring-security-oauth2/.springBeans | 2 - ...late.java => OAuth2RestTemplateTests.java} | 2 +- ...tAuthenticationProcessingFilterTests.java} | 2 +- ...va => OAuth2ClientContextFilterTests.java} | 2 +- ...dler.java => OAuth2ErrorHandlerTests.java} | 2 +- ...ava => AccessTokenProviderChainTests.java} | 4 +- ...java => JdbcClientTokenServicesTests.java} | 2 +- ...ava => OAuth2AccessTokenSupportTests.java} | 2 +- ...tAuthorizationCodeAccessTokenProvider.java | 101 -------- ...CodeAccessTokenProviderWithConversion.java | 231 ------------------ .../TestAuthorizationCodeResourceDetails.java | 47 ---- ... => ImplicitAccessTokenProviderTests.java} | 2 +- ...faultOAuth2SerializationServiceTests.java} | 2 +- ...ation.java => JsonSerializationTests.java} | 2 +- ...AccessTokenJackson1DeserializerTests.java} | 2 +- ...h2AccessTokenJackson1SerializerTests.java} | 2 +- ...AccessTokenJackson2DeserializerTests.java} | 2 +- ...h2AccessTokenJackson2SerializerTests.java} | 2 +- ... => OAuth2ExceptionDeserializerTests.java} | 2 +- ...va => OAuth2ExceptionSerializerTests.java} | 2 +- ...uthorizationServerConfigurationTests.java} | 4 +- ...ion.java => ClientConfigurationTests.java} | 2 +- ... => ResourceServerConfigurationTests.java} | 2 +- ...ationServerBeanDefinitionParserTests.java} | 4 +- ...rizationServerCustomGrantParserTests.java} | 4 +- ...ailsServiceBeanDefinitionParserTests.java} | 2 +- ...lidResourceBeanDefinitionParserTests.java} | 2 +- ...=> ResourceBeanDefinitionParserTests.java} | 2 +- ...ourceServerBeanDefinitionParserTests.java} | 2 +- ...uth2AccessTokenMessageConverterTests.java} | 2 +- ...OAuth2ExceptionMessageConverterTests.java} | 2 +- ...st.java => AuthorizationRequestTests.java} | 2 +- ...tails.java => BaseClientDetailsTests.java} | 2 +- ...aultAuthorizationRequestManagerTests.java} | 2 +- ... => DefaultAuthorizationRequestTests.java} | 2 +- ...ava => JdbcClientDetailsServiceTests.java} | 2 +- ...on.java => OAuth2AuthenticationTests.java} | 2 +- ...pprovalStoreUserApprovalHandlerTests.java} | 2 +- ...a => DefaultUserApprovalHandlerTests.java} | 2 +- ...e.java => InMemoryApprovalStoreTests.java} | 2 +- ...Store.java => JdbcApprovalStoreTests.java} | 2 +- ...tore.java => TokenApprovalStoreTests.java} | 2 +- ...> TokenStoreUserApprovalHandlerTests.java} | 2 +- ... => OAuth2AuthenticationManagerTests.java} | 2 +- ...2AuthenticationProcessingFilterTests.java} | 2 +- ...tCredentialsTokenEndpointFilterTests.java} | 2 +- .../TestAuthorizationCodeServicesBase.java | 82 ------- .../TestAuthorizationCodeTokenGranter.java | 207 ---------------- .../code/TestDefaultRedirectResolver.java | 103 -------- .../code/TestExactMatchRedirectResolver.java | 63 ----- ...TestInMemoryAuthorizationCodeServices.java | 18 -- .../TestJdbcAuthorizationCodeServices.java | 29 --- .../code/TestSubdomainRedirectResolver.java | 43 ---- ...t.java => AuthorizationEndpointTests.java} | 2 +- ...kenEndpointAuthenticationFilterTests.java} | 2 +- ...nEndpoint.java => TokenEndpointTests.java} | 2 +- ...a => WhitelabelApprovalEndpointTests.java} | 2 +- ...va => OAuth2AccessDeniedHandlerTests.java} | 2 +- ... OAuth2AuthenticationEntryPointTests.java} | 2 +- ...MethodSecurityExpressionHandlerTests.java} | 2 +- ...OAuth2SecurityExpressionMethodsTests.java} | 2 +- ...th2WebSecurityExpressionHandlerTests.java} | 2 +- ...=> InMemoryImplicitGrantServiceTests.java} | 2 +- ...sourceOwnerPasswordTokenGranterTests.java} | 4 +- ...efaultTokenServicesWithInMemoryTests.java} | 2 +- ...=> DefaultTokenServicesWithJdbcTests.java} | 2 +- ...tore.java => InMemoryTokenStoreTests.java} | 2 +- ...kenStore.java => JdbcTokenStoreTests.java} | 2 +- ...hancer.java => JwtTokenEnhancerTests.java} | 2 +- ...rvices.java => JwtTokenServicesTests.java} | 2 +- ...toreBase.java => TokenStoreBaseTests.java} | 2 +- ...eVoter.java => ClientScopeVoterTests.java} | 2 +- ...stScopeVoter.java => ScopeVoterTests.java} | 2 +- ...viceBeanDefinitionParserTests-context.xml} | 0 ...urceBeanDefinitionParserTests-context.xml} | 0 .../xml/authorization-server-custom-grant.xml | 2 +- 112 files changed, 117 insertions(+), 1034 deletions(-) rename samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/{TestAdminEndpoints.java => AdminEndpointsTests.java} (97%) rename samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/{TestAuthorizationCodeProvider.java => AuthorizationCodeProviderTests.java} (99%) rename samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/{TestClientCredentialsProvider.java => ClientCredentialsProviderTests.java} (96%) rename samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/{TestImplicitProvider.java => ImplicitProviderTests.java} (98%) rename samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/{TestRefreshTokenSupport.java => RefreshTokenSupportTests.java} (98%) rename samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/{TestResourceOwnerPasswordProvider.java => ResourceOwnerPasswordProviderTests.java} (98%) rename samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/{TestAuthorizationCodeGrant.java => AuthorizationCodeGrantTests.java} (99%) rename samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/{TestClientCredentialsGrant.java => ClientCredentialsGrantTests.java} (98%) rename samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/{TestRefreshTokenGrant.java => RefreshTokenGrantTests.java} (98%) rename samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/{TestResourceOwnerPasswordGrant.java => ResourceOwnerPasswordGrantTests.java} (96%) rename spring-security-oauth/src/test/java/net/oauth/signature/{TestGoogleCodeCompatibility.java => GoogleCodeCompatibilityTests.java} (99%) rename spring-security-oauth/src/test/java/org/springframework/security/oauth/common/{TestOAuthCodec.java => OAuthCodecTests.java} (97%) rename spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/{TestCoreOAuthSignatureMethodFactory.java => CoreOAuthSignatureMethodFactoryTests.java} (98%) rename spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/{TestHMAC_SHA1SignatureMethod.java => HMAC_SHA1SignatureMethodTests.java} (98%) rename spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/{TestPlainTextSignatureMethod.java => PlainTextSignatureMethodTests.java} (96%) rename spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/{TestRSA_SHA1SignatureMethod.java => RSA_SHA1SignatureMethodTests.java} (98%) rename spring-security-oauth/src/test/java/org/springframework/security/oauth/config/{TestAuthorizationServerBeanDefinitionParser.java => AuthorizationServerBeanDefinitionParserTests.java} (97%) rename spring-security-oauth/src/test/java/org/springframework/security/oauth/config/{TestConsumerServiceBeanDefinitionParser.java => ConsumerServiceBeanDefinitionParserTests.java} (95%) rename spring-security-oauth/src/test/java/org/springframework/security/oauth/config/{TestFilterChainInitialization.java => FilterChainInitializationTests.java} (95%) rename spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/{TestGoogleOAuth.java => GoogleOAuthTests.java} (98%) rename spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/client/{TestCoreOAuthConsumerSupport.java => CoreOAuthConsumerSupportTests.java} (99%) rename spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/filter/{TestOAuthConsumerContextFilter.java => OAuthConsumerContextFilterTests.java} (99%) rename spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/rememberme/{TestHttpSessionOAuthRememberMeServices.java => HttpSessionOAuthRememberMeServicesTests.java} (98%) rename spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/{TestCoreOAuthProviderSupport.java => CoreOAuthProviderSupportTests.java} (99%) rename spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/{TestAccessTokenProcessingFilter.java => AccessTokenProcessingFilterTests.java} (98%) rename spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/{TestOAuthProcessingFilter.java => OAuthProcessingFilterTests.java} (99%) rename spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/{TestOAuthUserAuthorizationProcessingFilter.java => OAuthUserAuthorizationProcessingFilterTests.java} (98%) rename spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/{TestProtectedResourceProcessingFilter.java => ProtectedResourceProcessingFilterTests.java} (98%) rename spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/{TestUnauthenticatedRequestTokenProcessingFilter.java => UnauthenticatedRequestTokenProcessingFilterTests.java} (98%) rename spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/{TestUserAuthorizationSuccessfulAuthenticationHandler.java => UserAuthorizationSuccessfulAuthenticationHandlerTests.java} (97%) rename spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/nonce/{TestInMemoryNonceServices.java => InMemoryNonceServicesTests.java} (98%) rename spring-security-oauth/src/test/resources/org/springframework/security/oauth/config/{TestAuthorizationServerBeanDefinitionParser-context.xml => AuthorizationServerBeanDefinitionParserTests-context.xml} (100%) rename spring-security-oauth/src/test/resources/org/springframework/security/oauth/config/{TestConsumerServiceBeanDefinitionParser-context.xml => ConsumerServiceBeanDefinitionParserTests-context.xml} (100%) rename spring-security-oauth/src/test/resources/org/springframework/security/oauth/config/{TestFilterChainInitialization-context.xml => FilterChainInitializationTests-context.xml} (100%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/{TestOAuth2RestTemplate.java => OAuth2RestTemplateTests.java} (99%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/{TestOAuth2ClientAuthenticationProcessingFilter.java => OAuth2ClientAuthenticationProcessingFilterTests.java} (97%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/{TestOAuth2ClientContextFilter.java => OAuth2ClientContextFilterTests.java} (98%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/http/{TestOAuth2ErrorHandler.java => OAuth2ErrorHandlerTests.java} (99%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/{TestAccessTokenProviderChain.java => AccessTokenProviderChainTests.java} (99%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/{TestJdbcClientTokenServices.java => JdbcClientTokenServicesTests.java} (98%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/{TestOAuth2AccessTokenSupport.java => OAuth2AccessTokenSupportTests.java} (99%) delete mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/TestAuthorizationCodeAccessTokenProvider.java delete mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/TestAuthorizationCodeAccessTokenProviderWithConversion.java delete mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/TestAuthorizationCodeResourceDetails.java rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/implicit/{TestImplicitAccessTokenProvider.java => ImplicitAccessTokenProviderTests.java} (98%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/{TestDefaultOAuth2SerializationService.java => DefaultOAuth2SerializationServiceTests.java} (97%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/{TestJsonSerialization.java => JsonSerializationTests.java} (99%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/{TestOAuth2AccessTokenJackson1Deserializer.java => OAuth2AccessTokenJackson1DeserializerTests.java} (97%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/{TestOAuth2AccessTokenJackson1Serializer.java => OAuth2AccessTokenJackson1SerializerTests.java} (97%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/{TestOAuth2AccessTokenJackson2Deserializer.java => OAuth2AccessTokenJackson2DeserializerTests.java} (97%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/{TestOAuth2AccessTokenJackson2Serializer.java => OAuth2AccessTokenJackson2SerializerTests.java} (97%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/{TestOAuth2ExceptionDeserializer.java => OAuth2ExceptionDeserializerTests.java} (99%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/{TestOAuth2ExceptionSerializer.java => OAuth2ExceptionSerializerTests.java} (99%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/{TestAuthorizationServerConfiguration.java => AuthorizationServerConfigurationTests.java} (97%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/{TestClientConfiguration.java => ClientConfigurationTests.java} (99%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/{TestResourceServerConfiguration.java => ResourceServerConfigurationTests.java} (99%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/{TestAuthorizationServerBeanDefinitionParser.java => AuthorizationServerBeanDefinitionParserTests.java} (93%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/{TestAuthorizationServerCustomGrantParser.java => AuthorizationServerCustomGrantParserTests.java} (93%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/{TestClientDetailsServiceBeanDefinitionParser.java => ClientDetailsServiceBeanDefinitionParserTests.java} (98%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/{TestInvalidResourceBeanDefinitionParser.java => InvalidResourceBeanDefinitionParserTests.java} (98%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/{TestResourceBeanDefinitionParser.java => ResourceBeanDefinitionParserTests.java} (98%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/{TestResourceServerBeanDefinitionParser.java => ResourceServerBeanDefinitionParserTests.java} (97%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/{TestJaxbOAuth2AccessTokenMessageConverter.java => JaxbOAuth2AccessTokenMessageConverterTests.java} (98%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/{TestJaxbOAuth2ExceptionMessageConverter.java => JaxbOAuth2ExceptionMessageConverterTests.java} (99%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/{TestAuthorizationRequest.java => AuthorizationRequestTests.java} (99%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/{TestBaseClientDetails.java => BaseClientDetailsTests.java} (99%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/{TestDefaultAuthorizationRequestManager.java => DefaultAuthorizationRequestManagerTests.java} (96%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/{TestDefaultAuthorizationRequest.java => DefaultAuthorizationRequestTests.java} (99%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/{TestJdbcClientDetailsService.java => JdbcClientDetailsServiceTests.java} (99%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/{TestOAuth2Authentication.java => OAuth2AuthenticationTests.java} (98%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/{TestApprovalStoreUserApprovalHandler.java => ApprovalStoreUserApprovalHandlerTests.java} (99%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/{TestDefaultUserApprovalHandler.java => DefaultUserApprovalHandlerTests.java} (97%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/{TestInMemoryApprovalStore.java => InMemoryApprovalStoreTests.java} (91%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/{TestJdbcApprovalStore.java => JdbcApprovalStoreTests.java} (96%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/{TestTokenApprovalStore.java => TokenApprovalStoreTests.java} (97%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/{TestTokenStoreUserApprovalHandler.java => TokenStoreUserApprovalHandlerTests.java} (98%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/{TestOAuth2AuthenticationManager.java => OAuth2AuthenticationManagerTests.java} (97%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/{TestOAuth2AuthenticationProcessingFilter.java => OAuth2AuthenticationProcessingFilterTests.java} (97%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/{TestClientCredentialsTokenEndpointFilter.java => ClientCredentialsTokenEndpointFilterTests.java} (97%) delete mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeServicesBase.java delete mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeTokenGranter.java delete mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestDefaultRedirectResolver.java delete mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestExactMatchRedirectResolver.java delete mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestInMemoryAuthorizationCodeServices.java delete mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestJdbcAuthorizationCodeServices.java delete mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestSubdomainRedirectResolver.java rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/{TestAuthorizationEndpoint.java => AuthorizationEndpointTests.java} (99%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/{TestTokenEndpointAuthenticationFilter.java => TokenEndpointAuthenticationFilterTests.java} (98%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/{TestTokenEndpoint.java => TokenEndpointTests.java} (99%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/{TestWhitelabelApprovalEndpoint.java => WhitelabelApprovalEndpointTests.java} (98%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/{TestOAuth2AccessDeniedHandler.java => OAuth2AccessDeniedHandlerTests.java} (97%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/{TestOAuth2AuthenticationEntryPoint.java => OAuth2AuthenticationEntryPointTests.java} (98%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/{TestOAuth2MethodSecurityExpressionHandler.java => OAuth2MethodSecurityExpressionHandlerTests.java} (99%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/{TestOAuth2SecurityExpressionMethods.java => OAuth2SecurityExpressionMethodsTests.java} (99%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/{TestOAuth2WebSecurityExpressionHandler.java => OAuth2WebSecurityExpressionHandlerTests.java} (98%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/implicit/{TestInMemoryImplicitGrantService.java => InMemoryImplicitGrantServiceTests.java} (97%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/{TestResourceOwnerPasswordTokenGranter.java => ResourceOwnerPasswordTokenGranterTests.java} (98%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/{TestDefaultTokenServicesWithInMemory.java => DefaultTokenServicesWithInMemoryTests.java} (98%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/{TestDefaultTokenServicesWithJdbc.java => DefaultTokenServicesWithJdbcTests.java} (90%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/{TestInMemoryTokenStore.java => InMemoryTokenStoreTests.java} (97%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/{TestJdbcTokenStore.java => JdbcTokenStoreTests.java} (92%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/{TestJwtTokenEnhancer.java => JwtTokenEnhancerTests.java} (99%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/{TestJwtTokenServices.java => JwtTokenServicesTests.java} (99%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/{TestTokenStoreBase.java => TokenStoreBaseTests.java} (99%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/{TestClientScopeVoter.java => ClientScopeVoterTests.java} (98%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/{TestScopeVoter.java => ScopeVoterTests.java} (99%) rename spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/{TestClientDetailsServiceBeanDefinitionParser-context.xml => ClientDetailsServiceBeanDefinitionParserTests-context.xml} (100%) rename spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/{TestResourceBeanDefinitionParser-context.xml => ResourceBeanDefinitionParserTests-context.xml} (100%) diff --git a/pom.xml b/pom.xml index 706926033..0ca951062 100644 --- a/pom.xml +++ b/pom.xml @@ -324,6 +324,16 @@ 1.0 + + + org.apache.maven.plugins + maven-surefire-plugin + + ${skipTests} + + **/*Tests.java + + diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestAdminEndpoints.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/AdminEndpointsTests.java similarity index 97% rename from samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestAdminEndpoints.java rename to samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/AdminEndpointsTests.java index a9a32971c..cb5045658 100644 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestAdminEndpoints.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/AdminEndpointsTests.java @@ -27,7 +27,7 @@ /** * @author Dave Syer */ -public class TestAdminEndpoints { +public class AdminEndpointsTests { @Rule public ServerRunning serverRunning = ServerRunning.isRunning(); @@ -128,7 +128,7 @@ public ResourceOwnerReadOnly(Object target) { setScope(Arrays.asList("read")); setUsername("marissa"); setPassword("koala"); - TestAdminEndpoints test = (TestAdminEndpoints) target; + AdminEndpointsTests test = (AdminEndpointsTests) target; setAccessTokenUri(test.serverRunning.getUrl("/sparklr2/oauth/token")); } } @@ -138,7 +138,7 @@ public ClientCredentialsReadOnly(Object target) { setClientId("my-client-with-registered-redirect"); setId(getClientId()); setScope(Arrays.asList("read")); - TestAdminEndpoints test = (TestAdminEndpoints) target; + AdminEndpointsTests test = (AdminEndpointsTests) target; setAccessTokenUri(test.serverRunning.getUrl("/sparklr2/oauth/token")); } } diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationCodeProvider.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/AuthorizationCodeProviderTests.java similarity index 99% rename from samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationCodeProvider.java rename to samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/AuthorizationCodeProviderTests.java index fd6d0d915..b1c250956 100755 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationCodeProvider.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/AuthorizationCodeProviderTests.java @@ -54,7 +54,7 @@ * @author Dave Syer * @author Luke Taylor */ -public class TestAuthorizationCodeProvider { +public class AuthorizationCodeProviderTests { @Rule public ServerRunning serverRunning = ServerRunning.isRunning(); @@ -455,7 +455,7 @@ public MyLessTrustedClient(Object target) { setClientId("my-less-trusted-client"); setScope(Arrays.asList("read")); setId(getClientId()); - TestAuthorizationCodeProvider test = (TestAuthorizationCodeProvider) target; + AuthorizationCodeProviderTests test = (AuthorizationCodeProviderTests) target; setAccessTokenUri(test.serverRunning.getUrl("/sparklr2/oauth/token")); setUserAuthorizationUri(test.serverRunning.getUrl("/sparklr2/oauth/authorize")); } diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestClientCredentialsProvider.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ClientCredentialsProviderTests.java similarity index 96% rename from samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestClientCredentialsProvider.java rename to samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ClientCredentialsProviderTests.java index 7ca5b04be..a062d1f1c 100644 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestClientCredentialsProvider.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ClientCredentialsProviderTests.java @@ -27,7 +27,7 @@ * @author Ryan Heaton * @author Dave Syer */ -public class TestClientCredentialsProvider { +public class ClientCredentialsProviderTests { @Rule public ServerRunning serverRunning = ServerRunning.isRunning(); @@ -131,7 +131,7 @@ public ClientCredentials(Object target) { setClientId("my-client-with-registered-redirect"); setScope(Arrays.asList("read")); setId(getClientId()); - TestClientCredentialsProvider test = (TestClientCredentialsProvider) target; + ClientCredentialsProviderTests test = (ClientCredentialsProviderTests) target; setAccessTokenUri(test.serverRunning.getUrl("/sparklr2/oauth/token")); test.resource = this; } @@ -148,7 +148,7 @@ static class NoScopeClientCredentials extends ClientCredentialsResourceDetails { public NoScopeClientCredentials(Object target) { setClientId("my-client-with-registered-redirect"); setId(getClientId()); - TestClientCredentialsProvider test = (TestClientCredentialsProvider) target; + ClientCredentialsProviderTests test = (ClientCredentialsProviderTests) target; setAccessTokenUri(test.serverRunning.getUrl("/sparklr2/oauth/token")); } } diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestImplicitProvider.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ImplicitProviderTests.java similarity index 98% rename from samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestImplicitProvider.java rename to samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ImplicitProviderTests.java index 02d203d33..1a91c05e1 100644 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestImplicitProvider.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ImplicitProviderTests.java @@ -33,7 +33,7 @@ * @author Ryan Heaton * @author Dave Syer */ -public class TestImplicitProvider { +public class ImplicitProviderTests { @Rule public ServerRunning serverRunning = ServerRunning.isRunning(); @@ -119,7 +119,7 @@ public AutoApproveImplicit(Object target) { setClientId("my-less-trusted-autoapprove-client"); setId(getClientId()); setPreEstablishedRedirectUri("http://anywhere/"); - TestImplicitProvider test = (TestImplicitProvider) target; + ImplicitProviderTests test = (ImplicitProviderTests) target; setAccessTokenUri(test.serverRunning.getUrl("/sparklr2/oauth/authorize")); setUserAuthorizationUri(test.serverRunning.getUrl("/sparklr2/oauth/authorize")); } diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestRefreshTokenSupport.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/RefreshTokenSupportTests.java similarity index 98% rename from samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestRefreshTokenSupport.java rename to samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/RefreshTokenSupportTests.java index 69cc21541..96298c881 100644 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestRefreshTokenSupport.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/RefreshTokenSupportTests.java @@ -21,7 +21,7 @@ * @author Ryan Heaton * @author Dave Syer */ -public class TestRefreshTokenSupport { +public class RefreshTokenSupportTests { @Rule public ServerRunning serverRunning = ServerRunning.isRunning(); diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestResourceOwnerPasswordProvider.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ResourceOwnerPasswordProviderTests.java similarity index 98% rename from samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestResourceOwnerPasswordProvider.java rename to samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ResourceOwnerPasswordProviderTests.java index adc0fc132..b62a28f8a 100644 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/TestResourceOwnerPasswordProvider.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ResourceOwnerPasswordProviderTests.java @@ -34,7 +34,7 @@ * @author Ryan Heaton * @author Dave Syer */ -public class TestResourceOwnerPasswordProvider { +public class ResourceOwnerPasswordProviderTests { @Rule public ServerRunning serverRunning = ServerRunning.isRunning(); @@ -226,7 +226,7 @@ public ResourceOwner(Object target) { setId(getClientId()); setUsername("marissa"); setPassword("koala"); - TestResourceOwnerPasswordProvider test = (TestResourceOwnerPasswordProvider) target; + ResourceOwnerPasswordProviderTests test = (ResourceOwnerPasswordProviderTests) target; setAccessTokenUri(test.serverRunning.getUrl("/sparklr2/oauth/token")); } } diff --git a/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestAuthorizationCodeGrant.java b/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/AuthorizationCodeGrantTests.java similarity index 99% rename from samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestAuthorizationCodeGrant.java rename to samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/AuthorizationCodeGrantTests.java index 9df439cd7..b12fa92a9 100755 --- a/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestAuthorizationCodeGrant.java +++ b/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/AuthorizationCodeGrantTests.java @@ -29,7 +29,7 @@ * @author Ryan Heaton * @author Dave Syer */ -public class TestAuthorizationCodeGrant { +public class AuthorizationCodeGrantTests { @Rule public ServerRunning serverRunning = ServerRunning.isRunning(); diff --git a/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestClientCredentialsGrant.java b/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/ClientCredentialsGrantTests.java similarity index 98% rename from samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestClientCredentialsGrant.java rename to samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/ClientCredentialsGrantTests.java index 626b4f015..2b4a3c916 100644 --- a/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestClientCredentialsGrant.java +++ b/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/ClientCredentialsGrantTests.java @@ -19,7 +19,7 @@ * @author Ryan Heaton * @author Dave Syer */ -public class TestClientCredentialsGrant { +public class ClientCredentialsGrantTests { @Rule public ServerRunning serverRunning = ServerRunning.isRunning(); diff --git a/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestRefreshTokenGrant.java b/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/RefreshTokenGrantTests.java similarity index 98% rename from samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestRefreshTokenGrant.java rename to samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/RefreshTokenGrantTests.java index 3f486ca52..655e23f0b 100644 --- a/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestRefreshTokenGrant.java +++ b/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/RefreshTokenGrantTests.java @@ -26,7 +26,7 @@ /** * @author Dave Syer */ -public class TestRefreshTokenGrant { +public class RefreshTokenGrantTests { @Rule public ServerRunning serverRunning = ServerRunning.isRunning(); diff --git a/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestResourceOwnerPasswordGrant.java b/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/ResourceOwnerPasswordGrantTests.java similarity index 96% rename from samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestResourceOwnerPasswordGrant.java rename to samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/ResourceOwnerPasswordGrantTests.java index 635f7461e..cde710db1 100644 --- a/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/TestResourceOwnerPasswordGrant.java +++ b/samples/oauth2/tonr/src/test/java/org/springframework/security/oauth/examples/tonr/ResourceOwnerPasswordGrantTests.java @@ -13,7 +13,7 @@ /** * @author Dave Syer */ -public class TestResourceOwnerPasswordGrant { +public class ResourceOwnerPasswordGrantTests { @Rule public ServerRunning serverRunning = ServerRunning.isRunning(); diff --git a/spring-security-oauth/.springBeans b/spring-security-oauth/.springBeans index 9989c639b..f25fc5ab4 100644 --- a/spring-security-oauth/.springBeans +++ b/spring-security-oauth/.springBeans @@ -1,13 +1,12 @@ 1 - + - src/test/resources/org/springframework/security/oauth/config/TestFilterChainInitialization-context.xml diff --git a/spring-security-oauth/src/test/java/net/oauth/signature/TestGoogleCodeCompatibility.java b/spring-security-oauth/src/test/java/net/oauth/signature/GoogleCodeCompatibilityTests.java similarity index 99% rename from spring-security-oauth/src/test/java/net/oauth/signature/TestGoogleCodeCompatibility.java rename to spring-security-oauth/src/test/java/net/oauth/signature/GoogleCodeCompatibilityTests.java index 3d1d3af67..e8c8b3a3e 100644 --- a/spring-security-oauth/src/test/java/net/oauth/signature/TestGoogleCodeCompatibility.java +++ b/spring-security-oauth/src/test/java/net/oauth/signature/GoogleCodeCompatibilityTests.java @@ -43,7 +43,7 @@ * @author Dave Syer */ @RunWith(MockitoJUnitRunner.class) -public class TestGoogleCodeCompatibility { +public class GoogleCodeCompatibilityTests { @Mock private HttpServletRequest request; diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/TestOAuthCodec.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/OAuthCodecTests.java similarity index 97% rename from spring-security-oauth/src/test/java/org/springframework/security/oauth/common/TestOAuthCodec.java rename to spring-security-oauth/src/test/java/org/springframework/security/oauth/common/OAuthCodecTests.java index f1be46169..06c870332 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/TestOAuthCodec.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/OAuthCodecTests.java @@ -24,7 +24,7 @@ /** * @author Ryan Heaton */ -public class TestOAuthCodec { +public class OAuthCodecTests { /** * tests idempotent decode. diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/TestCoreOAuthSignatureMethodFactory.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/CoreOAuthSignatureMethodFactoryTests.java similarity index 98% rename from spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/TestCoreOAuthSignatureMethodFactory.java rename to spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/CoreOAuthSignatureMethodFactoryTests.java index c0bf823b8..90c0b9be0 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/TestCoreOAuthSignatureMethodFactory.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/CoreOAuthSignatureMethodFactoryTests.java @@ -32,7 +32,7 @@ /** * @author Ryan Heaton */ -public class TestCoreOAuthSignatureMethodFactory { +public class CoreOAuthSignatureMethodFactoryTests { /** * tests getting the signature method. diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/TestHMAC_SHA1SignatureMethod.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/HMAC_SHA1SignatureMethodTests.java similarity index 98% rename from spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/TestHMAC_SHA1SignatureMethod.java rename to spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/HMAC_SHA1SignatureMethodTests.java index ccb2c60f1..293cad1d6 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/TestHMAC_SHA1SignatureMethod.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/HMAC_SHA1SignatureMethodTests.java @@ -25,7 +25,7 @@ /** * @author Ryan Heaton */ -public class TestHMAC_SHA1SignatureMethod { +public class HMAC_SHA1SignatureMethodTests { /** * Test sign and verify. diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/TestPlainTextSignatureMethod.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/PlainTextSignatureMethodTests.java similarity index 96% rename from spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/TestPlainTextSignatureMethod.java rename to spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/PlainTextSignatureMethodTests.java index c0b601036..08927a001 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/TestPlainTextSignatureMethod.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/PlainTextSignatureMethodTests.java @@ -21,7 +21,7 @@ /** * @author Ryan Heaton */ -public class TestPlainTextSignatureMethod { +public class PlainTextSignatureMethodTests { /** * tests signing and verifying. diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/TestRSA_SHA1SignatureMethod.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/RSA_SHA1SignatureMethodTests.java similarity index 98% rename from spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/TestRSA_SHA1SignatureMethod.java rename to spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/RSA_SHA1SignatureMethodTests.java index 6c118a547..8b8c77570 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/TestRSA_SHA1SignatureMethod.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/RSA_SHA1SignatureMethodTests.java @@ -31,7 +31,7 @@ /** * @author Ryan Heaton */ -public class TestRSA_SHA1SignatureMethod { +public class RSA_SHA1SignatureMethodTests { /** * tests signing and verifying. diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/config/TestAuthorizationServerBeanDefinitionParser.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/config/AuthorizationServerBeanDefinitionParserTests.java similarity index 97% rename from spring-security-oauth/src/test/java/org/springframework/security/oauth/config/TestAuthorizationServerBeanDefinitionParser.java rename to spring-security-oauth/src/test/java/org/springframework/security/oauth/config/AuthorizationServerBeanDefinitionParserTests.java index 3569e770d..d2000dd4d 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/config/TestAuthorizationServerBeanDefinitionParser.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/config/AuthorizationServerBeanDefinitionParserTests.java @@ -34,7 +34,7 @@ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) -public class TestAuthorizationServerBeanDefinitionParser { +public class AuthorizationServerBeanDefinitionParserTests { @Autowired private UserAuthorizationProcessingFilter filter; diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/config/TestConsumerServiceBeanDefinitionParser.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/config/ConsumerServiceBeanDefinitionParserTests.java similarity index 95% rename from spring-security-oauth/src/test/java/org/springframework/security/oauth/config/TestConsumerServiceBeanDefinitionParser.java rename to spring-security-oauth/src/test/java/org/springframework/security/oauth/config/ConsumerServiceBeanDefinitionParserTests.java index ce91e65f5..cc32cfa44 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/config/TestConsumerServiceBeanDefinitionParser.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/config/ConsumerServiceBeanDefinitionParserTests.java @@ -14,7 +14,7 @@ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) -public class TestConsumerServiceBeanDefinitionParser { +public class ConsumerServiceBeanDefinitionParserTests { @Autowired private ConsumerDetailsService clientDetailsService; diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/config/TestFilterChainInitialization.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/config/FilterChainInitializationTests.java similarity index 95% rename from spring-security-oauth/src/test/java/org/springframework/security/oauth/config/TestFilterChainInitialization.java rename to spring-security-oauth/src/test/java/org/springframework/security/oauth/config/FilterChainInitializationTests.java index 96f1b7762..5aa8ed3d5 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/config/TestFilterChainInitialization.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/config/FilterChainInitializationTests.java @@ -14,7 +14,7 @@ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) -public class TestFilterChainInitialization { +public class FilterChainInitializationTests { @Autowired private ConsumerDetailsService clientDetailsService; diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/TestGoogleOAuth.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/GoogleOAuthTests.java similarity index 98% rename from spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/TestGoogleOAuth.java rename to spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/GoogleOAuthTests.java index e408b515f..0dca1e5c2 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/TestGoogleOAuth.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/GoogleOAuthTests.java @@ -11,7 +11,7 @@ /** * @author Ryan Heaton */ -public class TestGoogleOAuth { +public class GoogleOAuthTests { /** * tests getting a request token. diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/client/TestCoreOAuthConsumerSupport.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/client/CoreOAuthConsumerSupportTests.java similarity index 99% rename from spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/client/TestCoreOAuthConsumerSupport.java rename to spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/client/CoreOAuthConsumerSupportTests.java index 05e898f6f..08673d126 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/client/TestCoreOAuthConsumerSupport.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/client/CoreOAuthConsumerSupportTests.java @@ -69,7 +69,7 @@ */ @SuppressWarnings("restriction") @RunWith(MockitoJUnitRunner.class) -public class TestCoreOAuthConsumerSupport { +public class CoreOAuthConsumerSupportTests { @Mock private ProtectedResourceDetails details; diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/filter/TestOAuthConsumerContextFilter.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/filter/OAuthConsumerContextFilterTests.java similarity index 99% rename from spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/filter/TestOAuthConsumerContextFilter.java rename to spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/filter/OAuthConsumerContextFilterTests.java index a26a7867e..a853a36ac 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/filter/TestOAuthConsumerContextFilter.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/filter/OAuthConsumerContextFilterTests.java @@ -36,7 +36,7 @@ * @author Ryan Heaton */ @RunWith(MockitoJUnitRunner.class) -public class TestOAuthConsumerContextFilter { +public class OAuthConsumerContextFilterTests { @Mock private ProtectedResourceDetails details; @Mock diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/rememberme/TestHttpSessionOAuthRememberMeServices.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/rememberme/HttpSessionOAuthRememberMeServicesTests.java similarity index 98% rename from spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/rememberme/TestHttpSessionOAuthRememberMeServices.java rename to spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/rememberme/HttpSessionOAuthRememberMeServicesTests.java index e4290a1d3..9beba686b 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/rememberme/TestHttpSessionOAuthRememberMeServices.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/rememberme/HttpSessionOAuthRememberMeServicesTests.java @@ -29,7 +29,7 @@ /** * @author Alex Rau */ -public class TestHttpSessionOAuthRememberMeServices { +public class HttpSessionOAuthRememberMeServicesTests { @Test public void testEmptySession() { diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/TestCoreOAuthProviderSupport.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/CoreOAuthProviderSupportTests.java similarity index 99% rename from spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/TestCoreOAuthProviderSupport.java rename to spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/CoreOAuthProviderSupportTests.java index e5037efed..451e42aaf 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/TestCoreOAuthProviderSupport.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/CoreOAuthProviderSupportTests.java @@ -37,7 +37,7 @@ * @author Ryan Heaton */ @RunWith(MockitoJUnitRunner.class) -public class TestCoreOAuthProviderSupport { +public class CoreOAuthProviderSupportTests { @Mock private HttpServletRequest request; diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/TestAccessTokenProcessingFilter.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/AccessTokenProcessingFilterTests.java similarity index 98% rename from spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/TestAccessTokenProcessingFilter.java rename to spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/AccessTokenProcessingFilterTests.java index 415633680..0360eecfb 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/TestAccessTokenProcessingFilter.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/AccessTokenProcessingFilterTests.java @@ -39,7 +39,7 @@ * @author Ryan Heaton */ @RunWith(MockitoJUnitRunner.class) -public class TestAccessTokenProcessingFilter { +public class AccessTokenProcessingFilterTests { @Mock private ConsumerDetails consumerDetails; @Mock diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/TestOAuthProcessingFilter.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/OAuthProcessingFilterTests.java similarity index 99% rename from spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/TestOAuthProcessingFilter.java rename to spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/OAuthProcessingFilterTests.java index 117e21423..ab0a9ac90 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/TestOAuthProcessingFilter.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/OAuthProcessingFilterTests.java @@ -65,7 +65,7 @@ * @author Ryan Heaton */ @RunWith(MockitoJUnitRunner.class) -public class TestOAuthProcessingFilter { +public class OAuthProcessingFilterTests { @Mock private OAuthProviderSupport providerSupport; @Mock diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/TestOAuthUserAuthorizationProcessingFilter.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/OAuthUserAuthorizationProcessingFilterTests.java similarity index 98% rename from spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/TestOAuthUserAuthorizationProcessingFilter.java rename to spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/OAuthUserAuthorizationProcessingFilterTests.java index 068ce765b..76d57d0e0 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/TestOAuthUserAuthorizationProcessingFilter.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/OAuthUserAuthorizationProcessingFilterTests.java @@ -36,7 +36,7 @@ /** * @author Ryan Heaton */ -public class TestOAuthUserAuthorizationProcessingFilter { +public class OAuthUserAuthorizationProcessingFilterTests { /** * tests the attempt to authenticate. diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/TestProtectedResourceProcessingFilter.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/ProtectedResourceProcessingFilterTests.java similarity index 98% rename from spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/TestProtectedResourceProcessingFilter.java rename to spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/ProtectedResourceProcessingFilterTests.java index 9901a3c2a..4f8f4cc30 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/TestProtectedResourceProcessingFilter.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/ProtectedResourceProcessingFilterTests.java @@ -38,7 +38,7 @@ /** * @author Ryan Heaton */ -public class TestProtectedResourceProcessingFilter { +public class ProtectedResourceProcessingFilterTests { /** * test onValidSignature diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/TestUnauthenticatedRequestTokenProcessingFilter.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/UnauthenticatedRequestTokenProcessingFilterTests.java similarity index 98% rename from spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/TestUnauthenticatedRequestTokenProcessingFilter.java rename to spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/UnauthenticatedRequestTokenProcessingFilterTests.java index ae4ebf3e1..c6d27c93d 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/TestUnauthenticatedRequestTokenProcessingFilter.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/UnauthenticatedRequestTokenProcessingFilterTests.java @@ -45,7 +45,7 @@ /** * @author Ryan Heaton */ -public class TestUnauthenticatedRequestTokenProcessingFilter { +public class UnauthenticatedRequestTokenProcessingFilterTests { /** * test onValidSignature diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/TestUserAuthorizationSuccessfulAuthenticationHandler.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/UserAuthorizationSuccessfulAuthenticationHandlerTests.java similarity index 97% rename from spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/TestUserAuthorizationSuccessfulAuthenticationHandler.java rename to spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/UserAuthorizationSuccessfulAuthenticationHandlerTests.java index 8ab181152..6924e6b4d 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/TestUserAuthorizationSuccessfulAuthenticationHandler.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/UserAuthorizationSuccessfulAuthenticationHandlerTests.java @@ -30,7 +30,7 @@ /** * @author Andrew McCall */ -public class TestUserAuthorizationSuccessfulAuthenticationHandler { +public class UserAuthorizationSuccessfulAuthenticationHandlerTests { /** * test determineTargetUrl diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/nonce/TestInMemoryNonceServices.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/nonce/InMemoryNonceServicesTests.java similarity index 98% rename from spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/nonce/TestInMemoryNonceServices.java rename to spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/nonce/InMemoryNonceServicesTests.java index e9da160cd..a42f872ca 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/nonce/TestInMemoryNonceServices.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/nonce/InMemoryNonceServicesTests.java @@ -14,7 +14,7 @@ * @author Ryan Heaton * @author Jilles van Gurp */ -public class TestInMemoryNonceServices { +public class InMemoryNonceServicesTests { private long now; private final InMemoryNonceServices nonceServices = new InMemoryNonceServices(); diff --git a/spring-security-oauth/src/test/resources/org/springframework/security/oauth/config/TestAuthorizationServerBeanDefinitionParser-context.xml b/spring-security-oauth/src/test/resources/org/springframework/security/oauth/config/AuthorizationServerBeanDefinitionParserTests-context.xml similarity index 100% rename from spring-security-oauth/src/test/resources/org/springframework/security/oauth/config/TestAuthorizationServerBeanDefinitionParser-context.xml rename to spring-security-oauth/src/test/resources/org/springframework/security/oauth/config/AuthorizationServerBeanDefinitionParserTests-context.xml diff --git a/spring-security-oauth/src/test/resources/org/springframework/security/oauth/config/TestConsumerServiceBeanDefinitionParser-context.xml b/spring-security-oauth/src/test/resources/org/springframework/security/oauth/config/ConsumerServiceBeanDefinitionParserTests-context.xml similarity index 100% rename from spring-security-oauth/src/test/resources/org/springframework/security/oauth/config/TestConsumerServiceBeanDefinitionParser-context.xml rename to spring-security-oauth/src/test/resources/org/springframework/security/oauth/config/ConsumerServiceBeanDefinitionParserTests-context.xml diff --git a/spring-security-oauth/src/test/resources/org/springframework/security/oauth/config/TestFilterChainInitialization-context.xml b/spring-security-oauth/src/test/resources/org/springframework/security/oauth/config/FilterChainInitializationTests-context.xml similarity index 100% rename from spring-security-oauth/src/test/resources/org/springframework/security/oauth/config/TestFilterChainInitialization-context.xml rename to spring-security-oauth/src/test/resources/org/springframework/security/oauth/config/FilterChainInitializationTests-context.xml diff --git a/spring-security-oauth2/.springBeans b/spring-security-oauth2/.springBeans index 974497c2e..20d3b626f 100644 --- a/spring-security-oauth2/.springBeans +++ b/spring-security-oauth2/.springBeans @@ -9,9 +9,7 @@ src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-custom-grant.xml src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-vanilla.xml - src/test/resources/org/springframework/security/oauth2/config/xml/TestResourceBeanDefinitionParser-context.xml src/test/resources/org/springframework/security/oauth2/config/xml/resource-server-context.xml - src/test/resources/org/springframework/security/oauth2/config/xml/TestClientDetailsServiceBeanDefinitionParser-context.xml diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/TestOAuth2RestTemplate.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/OAuth2RestTemplateTests.java similarity index 99% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/TestOAuth2RestTemplate.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/OAuth2RestTemplateTests.java index 972cdef8c..361f7b56f 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/TestOAuth2RestTemplate.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/OAuth2RestTemplateTests.java @@ -39,7 +39,7 @@ * @author Ryan Heaton * @author Dave Syer */ -public class TestOAuth2RestTemplate { +public class OAuth2RestTemplateTests { private BaseOAuth2ProtectedResourceDetails resource; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/TestOAuth2ClientAuthenticationProcessingFilter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilterTests.java similarity index 97% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/TestOAuth2ClientAuthenticationProcessingFilter.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilterTests.java index 84cd4365f..216d554b5 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/TestOAuth2ClientAuthenticationProcessingFilter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilterTests.java @@ -36,7 +36,7 @@ import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices; -public class TestOAuth2ClientAuthenticationProcessingFilter { +public class OAuth2ClientAuthenticationProcessingFilterTests { private OAuth2ClientAuthenticationProcessingFilter filter = new OAuth2ClientAuthenticationProcessingFilter( "/some/url"); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/TestOAuth2ClientContextFilter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilterTests.java similarity index 98% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/TestOAuth2ClientContextFilter.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilterTests.java index a1c025a49..1959a5dfa 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/TestOAuth2ClientContextFilter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilterTests.java @@ -8,7 +8,7 @@ /** * @author Ryan Heaton */ -public class TestOAuth2ClientContextFilter { +public class OAuth2ClientContextFilterTests { @Test public void testVanillaCurrentUri() throws Exception { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/http/TestOAuth2ErrorHandler.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandlerTests.java similarity index 99% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/http/TestOAuth2ErrorHandler.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandlerTests.java index b716914ee..d079eb6e5 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/http/TestOAuth2ErrorHandler.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandlerTests.java @@ -43,7 +43,7 @@ * */ @RunWith(MockitoJUnitRunner.class) -public class TestOAuth2ErrorHandler { +public class OAuth2ErrorHandlerTests { @Mock private ClientHttpResponse response; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/TestAccessTokenProviderChain.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/AccessTokenProviderChainTests.java similarity index 99% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/TestAccessTokenProviderChain.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/AccessTokenProviderChainTests.java index 7c1d49e8c..9dd0468bb 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/TestAccessTokenProviderChain.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/AccessTokenProviderChainTests.java @@ -43,7 +43,7 @@ * @author Dave Syer * */ -public class TestAccessTokenProviderChain { +public class AccessTokenProviderChainTests { private BaseOAuth2ProtectedResourceDetails resource; @@ -56,7 +56,7 @@ public class TestAccessTokenProviderChain { private ClientTokenServices clientTokenServices = Mockito.mock(ClientTokenServices.class); - public TestAccessTokenProviderChain() { + public AccessTokenProviderChainTests() { resource = new BaseOAuth2ProtectedResourceDetails(); resource.setId("resource"); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/TestJdbcClientTokenServices.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/JdbcClientTokenServicesTests.java similarity index 98% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/TestJdbcClientTokenServices.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/JdbcClientTokenServicesTests.java index 45ac99881..412021911 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/TestJdbcClientTokenServices.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/JdbcClientTokenServicesTests.java @@ -20,7 +20,7 @@ * @author Dave Syer * */ -public class TestJdbcClientTokenServices { +public class JdbcClientTokenServicesTests { private JdbcClientTokenServices tokenStore; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/TestOAuth2AccessTokenSupport.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/OAuth2AccessTokenSupportTests.java similarity index 99% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/TestOAuth2AccessTokenSupport.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/OAuth2AccessTokenSupportTests.java index 9a60b37b7..924f68b78 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/TestOAuth2AccessTokenSupport.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/OAuth2AccessTokenSupportTests.java @@ -49,7 +49,7 @@ * @author Dave Syer * */ -public class TestOAuth2AccessTokenSupport { +public class OAuth2AccessTokenSupportTests { private ClientCredentialsResourceDetails resource = new ClientCredentialsResourceDetails(); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/TestAuthorizationCodeAccessTokenProvider.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/TestAuthorizationCodeAccessTokenProvider.java deleted file mode 100644 index 945d79bc6..000000000 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/TestAuthorizationCodeAccessTokenProvider.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2006-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.client.token.grant.code; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.springframework.http.HttpHeaders; -import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails; -import org.springframework.security.oauth2.client.resource.UserRedirectRequiredException; -import org.springframework.security.oauth2.client.token.AccessTokenRequest; -import org.springframework.security.oauth2.client.token.DefaultAccessTokenRequest; -import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; -import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; - -/** - * @author Dave Syer - * - */ -public class TestAuthorizationCodeAccessTokenProvider { - - @Rule - public ExpectedException expected = ExpectedException.none(); - - private MultiValueMap params = new LinkedMultiValueMap(); - - private AuthorizationCodeAccessTokenProvider provider = new AuthorizationCodeAccessTokenProvider() { - @Override - protected OAuth2AccessToken retrieveToken(AccessTokenRequest request, OAuth2ProtectedResourceDetails resource, - MultiValueMap form, HttpHeaders headers) { - params.putAll(form); - return new DefaultOAuth2AccessToken("FOO"); - } - }; - - private AuthorizationCodeResourceDetails resource = new AuthorizationCodeResourceDetails(); - - @Test - public void testGetAccessToken() throws Exception { - AccessTokenRequest request = new DefaultAccessTokenRequest(); - request.setAuthorizationCode("foo"); - resource.setAccessTokenUri("http://localhost/oauth/token"); - assertEquals("FOO", provider.obtainAccessToken(resource, request).getValue()); - } - - @Test - public void testRedirectToAuthorizationEndpoint() throws Exception { - AccessTokenRequest request = new DefaultAccessTokenRequest(); - request.setCurrentUri("/come/back/soon"); - resource.setUserAuthorizationUri("http://localhost/oauth/authorize"); - try { - provider.obtainAccessToken(resource, request); - fail("Expected UserRedirectRequiredException"); - } - catch (UserRedirectRequiredException e) { - assertEquals("http://localhost/oauth/authorize", e.getRedirectUri()); - assertEquals("/come/back/soon", e.getStateToPreserve()); - } - } - - // A missing redirect just means the server has to deal with it - @Test(expected = UserRedirectRequiredException.class) - public void testRedirectNotSpecified() throws Exception { - AccessTokenRequest request = new DefaultAccessTokenRequest(); - resource.setUserAuthorizationUri("http://localhost/oauth/authorize"); - provider.obtainAccessToken(resource, request); - } - - @Test - public void testGetAccessTokenRequest() throws Exception { - AccessTokenRequest request = new DefaultAccessTokenRequest(); - request.setAuthorizationCode("foo"); - request.setStateKey("bar"); - request.setPreservedState(new Object()); - resource.setAccessTokenUri("http://localhost/oauth/token"); - resource.setPreEstablishedRedirectUri("http://anywhere.com/"); - assertEquals("FOO", provider.obtainAccessToken(resource, request).getValue()); - // System.err.println(params); - assertEquals("authorization_code", params.getFirst("grant_type")); - assertEquals("foo", params.getFirst("code")); - assertEquals("http://anywhere.com/", params.getFirst("redirect_uri")); - // State is not set in token request - assertEquals(null, params.getFirst("state")); - } - -} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/TestAuthorizationCodeAccessTokenProviderWithConversion.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/TestAuthorizationCodeAccessTokenProviderWithConversion.java deleted file mode 100644 index a83e7f13f..000000000 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/TestAuthorizationCodeAccessTokenProviderWithConversion.java +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright 2006-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.client.token.grant.code; - -import static org.hamcrest.CoreMatchers.instanceOf; -import static org.junit.Assert.assertEquals; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.URI; -import java.net.URISyntaxException; - -import org.codehaus.jackson.map.ObjectMapper; -import org.hamcrest.Description; -import org.hamcrest.Matcher; -import org.junit.Rule; -import org.junit.Test; -import org.junit.internal.matchers.TypeSafeMatcher; -import org.junit.rules.ExpectedException; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.client.ClientHttpRequest; -import org.springframework.http.client.ClientHttpRequestFactory; -import org.springframework.http.client.ClientHttpResponse; -import org.springframework.security.oauth2.client.resource.OAuth2AccessDeniedException; -import org.springframework.security.oauth2.client.token.AccessTokenRequest; -import org.springframework.security.oauth2.client.token.DefaultAccessTokenRequest; -import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; -import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.common.exceptions.InvalidClientException; - -/** - * @author Dave Syer - * - */ -public class TestAuthorizationCodeAccessTokenProviderWithConversion { - - private static class StubClientHttpRequest implements ClientHttpRequest { - - private static final HttpHeaders DEFAULT_RESPONSE_HEADERS = new HttpHeaders(); - - private final HttpStatus responseStatus; - - private final HttpHeaders responseHeaders; - - private final String responseBody; - - { - DEFAULT_RESPONSE_HEADERS.setContentType(MediaType.APPLICATION_JSON); - } - - public StubClientHttpRequest(String responseBody) { - this(HttpStatus.OK, DEFAULT_RESPONSE_HEADERS, responseBody); - } - - public StubClientHttpRequest(HttpHeaders responseHeaders, String responseBody) { - this(HttpStatus.OK, responseHeaders, responseBody); - } - - public StubClientHttpRequest(HttpStatus responseStatus, String responseBody) { - this(responseStatus, DEFAULT_RESPONSE_HEADERS, responseBody); - } - - public StubClientHttpRequest(HttpStatus responseStatus, HttpHeaders responseHeaders, String responseBody) { - this.responseStatus = responseStatus; - this.responseHeaders = responseHeaders; - this.responseBody = responseBody; - } - - public OutputStream getBody() throws IOException { - return new ByteArrayOutputStream(); - } - - public HttpHeaders getHeaders() { - return new HttpHeaders(); - } - - public URI getURI() { - try { - return new URI("http://foo.com/"); - } - catch (URISyntaxException e) { - throw new IllegalStateException(e); - } - } - - public HttpMethod getMethod() { - return HttpMethod.POST; - } - - public ClientHttpResponse execute() throws IOException { - return new ClientHttpResponse() { - - public HttpHeaders getHeaders() { - return responseHeaders; - } - - public InputStream getBody() throws IOException { - return new ByteArrayInputStream(responseBody.getBytes("UTF-8")); - } - - public String getStatusText() throws IOException { - return responseStatus.getReasonPhrase(); - } - - public HttpStatus getStatusCode() throws IOException { - return responseStatus; - } - - public void close() { - } - - public int getRawStatusCode() throws IOException { - return responseStatus.value(); - } - }; - } - } - - @Rule - public ExpectedException expected = ExpectedException.none(); - - private ClientHttpRequestFactory requestFactory; - - private AuthorizationCodeAccessTokenProvider provider = new AuthorizationCodeAccessTokenProvider(); - - private AuthorizationCodeResourceDetails resource = new AuthorizationCodeResourceDetails(); - - private void setUpRestTemplate() { - provider.setRequestFactory(requestFactory); - } - - @Test - public void testGetAccessTokenFromJson() throws Exception { - final OAuth2AccessToken token = new DefaultOAuth2AccessToken("FOO"); - requestFactory = new ClientHttpRequestFactory() { - public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException { - return new StubClientHttpRequest(new ObjectMapper().writeValueAsString(token)); - } - }; - AccessTokenRequest request = new DefaultAccessTokenRequest(); - request.setAuthorizationCode("foo"); - resource.setAccessTokenUri("http://localhost/oauth/token"); - setUpRestTemplate(); - assertEquals(token, provider.obtainAccessToken(resource, request)); - } - - @Test - public void testGetErrorFromJson() throws Exception { - final InvalidClientException exception = new InvalidClientException("FOO"); - requestFactory = new ClientHttpRequestFactory() { - public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException { - return new StubClientHttpRequest(HttpStatus.BAD_REQUEST, - new ObjectMapper().writeValueAsString(exception)); - } - }; - AccessTokenRequest request = new DefaultAccessTokenRequest(); - request.setAuthorizationCode("foo"); - resource.setAccessTokenUri("http://localhost/oauth/token"); - expected.expect(OAuth2AccessDeniedException.class); - expected.expect(hasCause(instanceOf(InvalidClientException.class))); - setUpRestTemplate(); - provider.obtainAccessToken(resource, request); - } - - @Test - public void testGetAccessTokenFromForm() throws Exception { - final OAuth2AccessToken token = new DefaultOAuth2AccessToken("FOO"); - final HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - requestFactory = new ClientHttpRequestFactory() { - public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException { - return new StubClientHttpRequest(responseHeaders, "access_token=FOO"); - } - }; - AccessTokenRequest request = new DefaultAccessTokenRequest(); - request.setAuthorizationCode("foo"); - resource.setAccessTokenUri("http://localhost/oauth/token"); - setUpRestTemplate(); - assertEquals(token, provider.obtainAccessToken(resource, request)); - } - - @Test - public void testGetErrorFromForm() throws Exception { - final HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - requestFactory = new ClientHttpRequestFactory() { - public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException { - return new StubClientHttpRequest(HttpStatus.BAD_REQUEST, responseHeaders, - "error=invalid_client&error_description=FOO"); - } - }; - AccessTokenRequest request = new DefaultAccessTokenRequest(); - request.setAuthorizationCode("foo"); - resource.setAccessTokenUri("http://localhost/oauth/token"); - expected.expect(OAuth2AccessDeniedException.class); - expected.expect(hasCause(instanceOf(InvalidClientException.class))); - setUpRestTemplate(); - provider.obtainAccessToken(resource, request); - } - - private Matcher hasCause(final Matcher matcher) { - return new TypeSafeMatcher() { - public void describeTo(Description description) { - description.appendText("exception matching "); - description.appendDescriptionOf(matcher); - } - - @Override - public boolean matchesSafely(Throwable item) { - return matcher.matches(item.getCause()); - } - }; - } - -} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/TestAuthorizationCodeResourceDetails.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/TestAuthorizationCodeResourceDetails.java deleted file mode 100644 index b08eeec98..000000000 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/TestAuthorizationCodeResourceDetails.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2006-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.client.token.grant.code; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; -import org.springframework.security.oauth2.client.token.DefaultAccessTokenRequest; - -/** - * @author Dave Syer - * - */ -public class TestAuthorizationCodeResourceDetails { - - private AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails(); - - @Test - public void testGetDefaultRedirectUri() { - details.setPreEstablishedRedirectUri("http://anywhere.com/"); - DefaultAccessTokenRequest request = new DefaultAccessTokenRequest(); - request.setCurrentUri("http://nowhere.com/"); - assertEquals("http://nowhere.com/", details.getRedirectUri(request)); - } - - @Test - public void testGetOverrideRedirectUri() { - details.setPreEstablishedRedirectUri("http://anywhere.com/"); - details.setUseCurrentUri(false); - DefaultAccessTokenRequest request = new DefaultAccessTokenRequest(); - request.setCurrentUri("http://nowhere.com/"); - assertEquals("http://anywhere.com/", details.getRedirectUri(request)); - } - -} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/implicit/TestImplicitAccessTokenProvider.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/implicit/ImplicitAccessTokenProviderTests.java similarity index 98% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/implicit/TestImplicitAccessTokenProvider.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/implicit/ImplicitAccessTokenProviderTests.java index 7c740fdb5..a23b32aae 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/implicit/TestImplicitAccessTokenProvider.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/implicit/ImplicitAccessTokenProviderTests.java @@ -30,7 +30,7 @@ * @author Dave Syer * */ -public class TestImplicitAccessTokenProvider { +public class ImplicitAccessTokenProviderTests { @Rule public ExpectedException expected = ExpectedException.none(); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/TestDefaultOAuth2SerializationService.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/DefaultOAuth2SerializationServiceTests.java similarity index 97% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/TestDefaultOAuth2SerializationService.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/DefaultOAuth2SerializationServiceTests.java index 26c86e9bf..da50f0930 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/TestDefaultOAuth2SerializationService.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/DefaultOAuth2SerializationServiceTests.java @@ -30,7 +30,7 @@ * @author Dave Syer * */ -public class TestDefaultOAuth2SerializationService { +public class DefaultOAuth2SerializationServiceTests { @Test public void testDefaultDeserialization() throws Exception { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/TestJsonSerialization.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/JsonSerializationTests.java similarity index 99% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/TestJsonSerialization.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/JsonSerializationTests.java index 9d8a40368..9c50fc5ce 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/TestJsonSerialization.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/JsonSerializationTests.java @@ -30,7 +30,7 @@ * @author Dave Syer * */ -public class TestJsonSerialization { +public class JsonSerializationTests { @Test public void testDefaultSerialization() throws Exception { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/TestOAuth2AccessTokenJackson1Deserializer.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson1DeserializerTests.java similarity index 97% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/TestOAuth2AccessTokenJackson1Deserializer.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson1DeserializerTests.java index 20611952c..7d5ca3fc4 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/TestOAuth2AccessTokenJackson1Deserializer.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson1DeserializerTests.java @@ -32,7 +32,7 @@ * @author Rob Winch */ @PrepareForTest(OAuth2AccessTokenJackson1Deserializer.class) -public class TestOAuth2AccessTokenJackson1Deserializer extends BaseOAuth2AccessTokenJacksonTest { +public class OAuth2AccessTokenJackson1DeserializerTests extends BaseOAuth2AccessTokenJacksonTest { protected ObjectMapper mapper; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/TestOAuth2AccessTokenJackson1Serializer.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson1SerializerTests.java similarity index 97% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/TestOAuth2AccessTokenJackson1Serializer.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson1SerializerTests.java index b0923f118..609c2fa3c 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/TestOAuth2AccessTokenJackson1Serializer.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson1SerializerTests.java @@ -17,7 +17,7 @@ * @author Rob Winch */ @PrepareForTest(OAuth2AccessTokenJackson1Serializer.class) -public class TestOAuth2AccessTokenJackson1Serializer extends BaseOAuth2AccessTokenJacksonTest { +public class OAuth2AccessTokenJackson1SerializerTests extends BaseOAuth2AccessTokenJacksonTest { protected ObjectMapper mapper; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/TestOAuth2AccessTokenJackson2Deserializer.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2DeserializerTests.java similarity index 97% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/TestOAuth2AccessTokenJackson2Deserializer.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2DeserializerTests.java index 10dc365fb..7d435dc08 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/TestOAuth2AccessTokenJackson2Deserializer.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2DeserializerTests.java @@ -32,7 +32,7 @@ * @author Rob Winch */ @PrepareForTest(OAuth2AccessTokenJackson2Deserializer.class) -public class TestOAuth2AccessTokenJackson2Deserializer extends BaseOAuth2AccessTokenJacksonTest { +public class OAuth2AccessTokenJackson2DeserializerTests extends BaseOAuth2AccessTokenJacksonTest { protected ObjectMapper mapper; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/TestOAuth2AccessTokenJackson2Serializer.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2SerializerTests.java similarity index 97% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/TestOAuth2AccessTokenJackson2Serializer.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2SerializerTests.java index fed19b806..92836dc34 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/TestOAuth2AccessTokenJackson2Serializer.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2SerializerTests.java @@ -17,7 +17,7 @@ * @author Rob Winch */ @PrepareForTest(OAuth2AccessTokenJackson2Serializer.class) -public class TestOAuth2AccessTokenJackson2Serializer extends BaseOAuth2AccessTokenJacksonTest { +public class OAuth2AccessTokenJackson2SerializerTests extends BaseOAuth2AccessTokenJacksonTest { protected ObjectMapper mapper; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/TestOAuth2ExceptionDeserializer.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/OAuth2ExceptionDeserializerTests.java similarity index 99% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/TestOAuth2ExceptionDeserializer.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/OAuth2ExceptionDeserializerTests.java index eb4b78861..456e7b83d 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/TestOAuth2ExceptionDeserializer.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/OAuth2ExceptionDeserializerTests.java @@ -33,7 +33,7 @@ * @author Rob Winch * */ -public class TestOAuth2ExceptionDeserializer { +public class OAuth2ExceptionDeserializerTests { private static final String DETAILS = "some detail"; private static ObjectMapper mapper; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/TestOAuth2ExceptionSerializer.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/OAuth2ExceptionSerializerTests.java similarity index 99% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/TestOAuth2ExceptionSerializer.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/OAuth2ExceptionSerializerTests.java index 01cf9c375..dc4302d05 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/TestOAuth2ExceptionSerializer.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/OAuth2ExceptionSerializerTests.java @@ -34,7 +34,7 @@ * @author Rob Winch * */ -public class TestOAuth2ExceptionSerializer { +public class OAuth2ExceptionSerializerTests { private static final String DETAILS = "some detail"; private static ObjectMapper mapper; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/TestAuthorizationServerConfiguration.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java similarity index 97% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/TestAuthorizationServerConfiguration.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java index 7375cfbec..d6d448ec4 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/TestAuthorizationServerConfiguration.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java @@ -39,7 +39,7 @@ * */ @RunWith(Parameterized.class) -public class TestAuthorizationServerConfiguration { +public class AuthorizationServerConfigurationTests { private AnnotationConfigWebApplicationContext context; @@ -52,7 +52,7 @@ public static List parameters() { new Object[] { AuthorizationServerExtras.class }, new Object[] { AuthorizationServerTypes.class }); } - public TestAuthorizationServerConfiguration(Class resource) { + public AuthorizationServerConfigurationTests(Class resource) { context = new AnnotationConfigWebApplicationContext(); context.setServletContext(new MockServletContext()); context.register(resource); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/TestClientConfiguration.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ClientConfigurationTests.java similarity index 99% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/TestClientConfiguration.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ClientConfigurationTests.java index 608bff736..3419b272e 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/TestClientConfiguration.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ClientConfigurationTests.java @@ -45,7 +45,7 @@ * @author Dave Syer * */ -public class TestClientConfiguration { +public class ClientConfigurationTests { @Test public void testAuthCodeRedirect() throws Exception { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/TestResourceServerConfiguration.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java similarity index 99% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/TestResourceServerConfiguration.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java index 8aac06643..a588b9884 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/TestResourceServerConfiguration.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java @@ -43,7 +43,7 @@ * @author Dave Syer * */ -public class TestResourceServerConfiguration { +public class ResourceServerConfigurationTests { private static InMemoryTokenStore tokenStore = new InMemoryTokenStore(); private OAuth2AccessToken token; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/TestAuthorizationServerBeanDefinitionParser.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/AuthorizationServerBeanDefinitionParserTests.java similarity index 93% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/TestAuthorizationServerBeanDefinitionParser.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/AuthorizationServerBeanDefinitionParserTests.java index 6b123996f..752cea947 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/TestAuthorizationServerBeanDefinitionParser.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/AuthorizationServerBeanDefinitionParserTests.java @@ -32,7 +32,7 @@ * */ @RunWith(Parameterized.class) -public class TestAuthorizationServerBeanDefinitionParser { +public class AuthorizationServerBeanDefinitionParserTests { private ConfigurableApplicationContext context; @@ -45,7 +45,7 @@ public static List parameters() { new Object[] { "authorization-server-extras" }, new Object[] { "authorization-server-types" }); } - public TestAuthorizationServerBeanDefinitionParser(String resource) { + public AuthorizationServerBeanDefinitionParserTests(String resource) { context = new GenericXmlApplicationContext(getClass(), resource + ".xml"); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/TestAuthorizationServerCustomGrantParser.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/AuthorizationServerCustomGrantParserTests.java similarity index 93% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/TestAuthorizationServerCustomGrantParser.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/AuthorizationServerCustomGrantParserTests.java index f4a54c3e2..e3ab6edee 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/TestAuthorizationServerCustomGrantParser.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/AuthorizationServerCustomGrantParserTests.java @@ -13,7 +13,7 @@ import org.springframework.security.oauth2.provider.TokenGranter; import org.springframework.security.oauth2.provider.TokenRequest; -public class TestAuthorizationServerCustomGrantParser { +public class AuthorizationServerCustomGrantParserTests { private static String RESOURCE_NAME = "authorization-server-custom-grant.xml"; @@ -22,7 +22,7 @@ public class TestAuthorizationServerCustomGrantParser { @Rule public ExpectedException expected = ExpectedException.none(); - public TestAuthorizationServerCustomGrantParser() { + public AuthorizationServerCustomGrantParserTests() { context = new GenericXmlApplicationContext(getClass(), RESOURCE_NAME); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/TestClientDetailsServiceBeanDefinitionParser.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/ClientDetailsServiceBeanDefinitionParserTests.java similarity index 98% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/TestClientDetailsServiceBeanDefinitionParser.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/ClientDetailsServiceBeanDefinitionParserTests.java index 342399945..8e44fb9ab 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/TestClientDetailsServiceBeanDefinitionParser.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/ClientDetailsServiceBeanDefinitionParserTests.java @@ -17,7 +17,7 @@ @ContextConfiguration @RunWith ( SpringJUnit4ClassRunner.class ) -public class TestClientDetailsServiceBeanDefinitionParser { +public class ClientDetailsServiceBeanDefinitionParserTests { @Autowired private ClientDetailsService clientDetailsService; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/TestInvalidResourceBeanDefinitionParser.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/InvalidResourceBeanDefinitionParserTests.java similarity index 98% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/TestInvalidResourceBeanDefinitionParser.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/InvalidResourceBeanDefinitionParserTests.java index a030af1bf..460925c8f 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/TestInvalidResourceBeanDefinitionParser.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/InvalidResourceBeanDefinitionParserTests.java @@ -29,7 +29,7 @@ * @author Dave Syer * */ -public class TestInvalidResourceBeanDefinitionParser { +public class InvalidResourceBeanDefinitionParserTests { private ConfigurableApplicationContext context; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/TestResourceBeanDefinitionParser.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/ResourceBeanDefinitionParserTests.java similarity index 98% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/TestResourceBeanDefinitionParser.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/ResourceBeanDefinitionParserTests.java index 8eaf5890e..5e49eb870 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/TestResourceBeanDefinitionParser.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/ResourceBeanDefinitionParserTests.java @@ -21,7 +21,7 @@ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) -public class TestResourceBeanDefinitionParser { +public class ResourceBeanDefinitionParserTests { @Autowired @Qualifier("one") diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/TestResourceServerBeanDefinitionParser.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/ResourceServerBeanDefinitionParserTests.java similarity index 97% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/TestResourceServerBeanDefinitionParser.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/ResourceServerBeanDefinitionParserTests.java index 8af31f92d..e70a1030a 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/TestResourceServerBeanDefinitionParser.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/ResourceServerBeanDefinitionParserTests.java @@ -26,7 +26,7 @@ * @author Dave Syer * */ -public class TestResourceServerBeanDefinitionParser { +public class ResourceServerBeanDefinitionParserTests { @Test public void testDefaults() { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/TestJaxbOAuth2AccessTokenMessageConverter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2AccessTokenMessageConverterTests.java similarity index 98% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/TestJaxbOAuth2AccessTokenMessageConverter.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2AccessTokenMessageConverterTests.java index 99da1a4ba..9e7b71e21 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/TestJaxbOAuth2AccessTokenMessageConverter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2AccessTokenMessageConverterTests.java @@ -35,7 +35,7 @@ * */ @PrepareForTest(JaxbOAuth2AccessToken.class) -public class TestJaxbOAuth2AccessTokenMessageConverter extends BaseJaxbMessageConverterTest { +public class JaxbOAuth2AccessTokenMessageConverterTests extends BaseJaxbMessageConverterTest { private JaxbOAuth2AccessTokenMessageConverter converter; private DefaultOAuth2AccessToken accessToken; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/TestJaxbOAuth2ExceptionMessageConverter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2ExceptionMessageConverterTests.java similarity index 99% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/TestJaxbOAuth2ExceptionMessageConverter.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2ExceptionMessageConverterTests.java index d72821090..3e4cb555b 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/TestJaxbOAuth2ExceptionMessageConverter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2ExceptionMessageConverterTests.java @@ -42,7 +42,7 @@ */ @RunWith(PowerMockRunner.class) @PrepareForTest({ System.class, JaxbOAuth2AccessToken.class }) -public class TestJaxbOAuth2ExceptionMessageConverter extends BaseJaxbMessageConverterTest { +public class JaxbOAuth2ExceptionMessageConverterTests extends BaseJaxbMessageConverterTest { private JaxbOAuth2ExceptionMessageConverter converter; private static String DETAILS = "some detail"; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationRequest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/AuthorizationRequestTests.java similarity index 99% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationRequest.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/AuthorizationRequestTests.java index 8b2e0601d..507c12285 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestAuthorizationRequest.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/AuthorizationRequestTests.java @@ -40,7 +40,7 @@ * @author Christian Hilmersson * */ -public class TestAuthorizationRequest { +public class AuthorizationRequestTests { private Map parameters; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestBaseClientDetails.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/BaseClientDetailsTests.java similarity index 99% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestBaseClientDetails.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/BaseClientDetailsTests.java index bba845c72..ece15eb88 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestBaseClientDetails.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/BaseClientDetailsTests.java @@ -30,7 +30,7 @@ * @author Dave Syer * */ -public class TestBaseClientDetails { +public class BaseClientDetailsTests { /** * test default constructor diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestDefaultAuthorizationRequestManager.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequestManagerTests.java similarity index 96% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestDefaultAuthorizationRequestManager.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequestManagerTests.java index 58b950674..a8ab98979 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestDefaultAuthorizationRequestManager.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequestManagerTests.java @@ -26,7 +26,7 @@ * @author Dave Syer * */ -public class TestDefaultAuthorizationRequestManager { +public class DefaultAuthorizationRequestManagerTests { private BaseClientDetails client = new BaseClientDetails(); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestDefaultAuthorizationRequest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequestTests.java similarity index 99% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestDefaultAuthorizationRequest.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequestTests.java index 83578ba3a..c75cb40e1 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestDefaultAuthorizationRequest.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequestTests.java @@ -39,7 +39,7 @@ * @author Christian Hilmersson * */ -public class TestDefaultAuthorizationRequest { +public class DefaultAuthorizationRequestTests { private Map parameters; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestJdbcClientDetailsService.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/JdbcClientDetailsServiceTests.java similarity index 99% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestJdbcClientDetailsService.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/JdbcClientDetailsServiceTests.java index 12387945c..f2af3d12f 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestJdbcClientDetailsService.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/JdbcClientDetailsServiceTests.java @@ -20,7 +20,7 @@ import org.springframework.security.core.GrantedAuthority; import org.springframework.security.crypto.password.PasswordEncoder; -public class TestJdbcClientDetailsService { +public class JdbcClientDetailsServiceTests { private JdbcClientDetailsService service; private JdbcTemplate jdbcTemplate; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestOAuth2Authentication.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/OAuth2AuthenticationTests.java similarity index 98% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestOAuth2Authentication.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/OAuth2AuthenticationTests.java index 8a5396dcc..354a37e39 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/TestOAuth2Authentication.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/OAuth2AuthenticationTests.java @@ -13,7 +13,7 @@ import org.springframework.test.annotation.Rollback; import org.springframework.util.SerializationUtils; -public class TestOAuth2Authentication { +public class OAuth2AuthenticationTests { private OAuth2Request request = RequestTokenFactory.createOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null, null); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestApprovalStoreUserApprovalHandler.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandlerTests.java similarity index 99% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestApprovalStoreUserApprovalHandler.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandlerTests.java index 6ce220d86..b5d59741a 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestApprovalStoreUserApprovalHandler.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandlerTests.java @@ -23,7 +23,7 @@ import org.springframework.security.oauth2.provider.DefaultOAuth2RequestFactory; import org.springframework.security.oauth2.provider.InMemoryClientDetailsService; -public class TestApprovalStoreUserApprovalHandler { +public class ApprovalStoreUserApprovalHandlerTests { private ApprovalStoreUserApprovalHandler handler = new ApprovalStoreUserApprovalHandler(); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestDefaultUserApprovalHandler.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/DefaultUserApprovalHandlerTests.java similarity index 97% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestDefaultUserApprovalHandler.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/DefaultUserApprovalHandlerTests.java index 2ca751936..90bfbdf14 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestDefaultUserApprovalHandler.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/DefaultUserApprovalHandlerTests.java @@ -24,7 +24,7 @@ * @author Dave Syer * */ -public class TestDefaultUserApprovalHandler { +public class DefaultUserApprovalHandlerTests { private DefaultUserApprovalHandler handler = new DefaultUserApprovalHandler(); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestInMemoryApprovalStore.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/InMemoryApprovalStoreTests.java similarity index 91% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestInMemoryApprovalStore.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/InMemoryApprovalStoreTests.java index fc4e20b34..af74be060 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestInMemoryApprovalStore.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/InMemoryApprovalStoreTests.java @@ -20,7 +20,7 @@ * @author Dave Syer * */ -public class TestInMemoryApprovalStore extends AbstractTestApprovalStore { +public class InMemoryApprovalStoreTests extends AbstractTestApprovalStore { private ApprovalStore store = new InMemoryApprovalStore(); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestJdbcApprovalStore.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/JdbcApprovalStoreTests.java similarity index 96% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestJdbcApprovalStore.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/JdbcApprovalStoreTests.java index a14576802..a0b6eabeb 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestJdbcApprovalStore.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/JdbcApprovalStoreTests.java @@ -33,7 +33,7 @@ * @author Dave Syer * */ -public class TestJdbcApprovalStore extends AbstractTestApprovalStore { +public class JdbcApprovalStoreTests extends AbstractTestApprovalStore { private JdbcApprovalStore store; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenApprovalStore.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TokenApprovalStoreTests.java similarity index 97% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenApprovalStore.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TokenApprovalStoreTests.java index 95a9ca4b1..e9a634142 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenApprovalStore.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TokenApprovalStoreTests.java @@ -36,7 +36,7 @@ * @author Dave Syer * */ -public class TestTokenApprovalStore extends AbstractTestApprovalStore { +public class TokenApprovalStoreTests extends AbstractTestApprovalStore { private TokenApprovalStore store = new TokenApprovalStore(); private InMemoryTokenStore tokenStore = new InMemoryTokenStore(); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenStoreUserApprovalHandler.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandlerTests.java similarity index 98% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenStoreUserApprovalHandler.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandlerTests.java index 54c6156a5..db0e1290d 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TestTokenStoreUserApprovalHandler.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandlerTests.java @@ -30,7 +30,7 @@ * @author Dave Syer * */ -public class TestTokenStoreUserApprovalHandler { +public class TokenStoreUserApprovalHandlerTests { private TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler(); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationManager.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManagerTests.java similarity index 97% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationManager.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManagerTests.java index aeea4b049..0e56ed5b7 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationManager.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManagerTests.java @@ -29,7 +29,7 @@ * @author Dave Syer * */ -public class TestOAuth2AuthenticationManager { +public class OAuth2AuthenticationManagerTests { private OAuth2AuthenticationManager manager = new OAuth2AuthenticationManager(); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationProcessingFilter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilterTests.java similarity index 97% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationProcessingFilter.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilterTests.java index 82dd73855..1f9255d33 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/TestOAuth2AuthenticationProcessingFilter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilterTests.java @@ -35,7 +35,7 @@ * @author Dave Syer * */ -public class TestOAuth2AuthenticationProcessingFilter { +public class OAuth2AuthenticationProcessingFilterTests { private OAuth2AuthenticationProcessingFilter filter = new OAuth2AuthenticationProcessingFilter(); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/TestClientCredentialsTokenEndpointFilter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenEndpointFilterTests.java similarity index 97% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/TestClientCredentialsTokenEndpointFilter.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenEndpointFilterTests.java index 6a74f9f38..36fe64ed8 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/TestClientCredentialsTokenEndpointFilter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenEndpointFilterTests.java @@ -29,7 +29,7 @@ * @author Dave Syer * */ -public class TestClientCredentialsTokenEndpointFilter { +public class ClientCredentialsTokenEndpointFilterTests { private ClientCredentialsTokenEndpointFilter filter = new ClientCredentialsTokenEndpointFilter(); private AuthenticationManager authenticationManager = Mockito diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeServicesBase.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeServicesBase.java deleted file mode 100644 index f2bcd3429..000000000 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeServicesBase.java +++ /dev/null @@ -1,82 +0,0 @@ -package org.springframework.security.oauth2.provider.code; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; - -import org.junit.Test; -import org.springframework.security.authentication.AbstractAuthenticationToken; -import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; -import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.RequestTokenFactory; -import org.springframework.security.oauth2.provider.OAuth2Request; - -public abstract class TestAuthorizationCodeServicesBase { - - abstract AuthorizationCodeServices getAuthorizationCodeServices(); - - @Test - public void testCreateAuthorizationCode() { - OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null, null); - OAuth2Authentication expectedAuthentication = new OAuth2Authentication( - storedOAuth2Request, new TestAuthentication( - "test2", false)); - String code = getAuthorizationCodeServices().createAuthorizationCode(expectedAuthentication); - assertNotNull(code); - - OAuth2Authentication actualAuthentication = getAuthorizationCodeServices() - .consumeAuthorizationCode(code); - assertEquals(expectedAuthentication, actualAuthentication); - } - - @Test - public void testConsumeRemovesCode() { - OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null, null); - OAuth2Authentication expectedAuthentication = new OAuth2Authentication( - storedOAuth2Request, new TestAuthentication( - "test2", false)); - String code = getAuthorizationCodeServices().createAuthorizationCode(expectedAuthentication); - assertNotNull(code); - - OAuth2Authentication actualAuthentication = getAuthorizationCodeServices() - .consumeAuthorizationCode(code); - assertEquals(expectedAuthentication, actualAuthentication); - - try { - getAuthorizationCodeServices().consumeAuthorizationCode(code); - fail("Should have thrown exception"); - } catch (InvalidGrantException e) { - // good we expected this - } - } - - @Test - public void testConsumeNonExistingCode() { - try { - getAuthorizationCodeServices().consumeAuthorizationCode("doesnt exist"); - fail("Should have thrown exception"); - } catch (InvalidGrantException e) { - // good we expected this - } - } - - protected static class TestAuthentication extends AbstractAuthenticationToken { - - private static final long serialVersionUID = 1L; - private String principal; - public TestAuthentication(String name, boolean authenticated) { - super(null); - setAuthenticated(authenticated); - this.principal = name; - } - - public Object getCredentials() { - return null; - } - - public Object getPrincipal() { - return this.principal; - } - } - -} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeTokenGranter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeTokenGranter.java deleted file mode 100644 index c275107fe..000000000 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestAuthorizationCodeTokenGranter.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright 2006-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.code; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import org.junit.Test; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.AuthorityUtils; -import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; -import org.springframework.security.oauth2.common.exceptions.RedirectMismatchException; -import org.springframework.security.oauth2.common.util.OAuth2Utils; -import org.springframework.security.oauth2.provider.BaseClientDetails; -import org.springframework.security.oauth2.provider.ClientDetails; -import org.springframework.security.oauth2.provider.ClientDetailsService; -import org.springframework.security.oauth2.provider.DefaultOAuth2RequestFactory; -import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.OAuth2Request; -import org.springframework.security.oauth2.provider.OAuth2RequestFactory; -import org.springframework.security.oauth2.provider.RequestTokenFactory; -import org.springframework.security.oauth2.provider.TokenRequest; -import org.springframework.security.oauth2.provider.token.DefaultTokenServices; -import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -/** - * @author Dave Syer - * - */ -public class TestAuthorizationCodeTokenGranter { - - private DefaultTokenServices providerTokenServices = new DefaultTokenServices(); - - private BaseClientDetails client = new BaseClientDetails("foo", "resource", "scope", "authorization_code", - "ROLE_CLIENT"); - - private ClientDetailsService clientDetailsService = new ClientDetailsService() { - public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exception { - return client; - } - }; - - private AuthorizationCodeServices authorizationCodeServices = new InMemoryAuthorizationCodeServices(); - - private OAuth2RequestFactory requestFactory = new DefaultOAuth2RequestFactory(clientDetailsService); - - private Map parameters = new HashMap(); - - public TestAuthorizationCodeTokenGranter() { - providerTokenServices.setTokenStore(new InMemoryTokenStore()); - } - - @Test - public void testAuthorizationCodeGrant() { - - Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala", - AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); - - parameters.clear(); - parameters.put(OAuth2Utils.CLIENT_ID, "foo"); - parameters.put(OAuth2Utils.SCOPE, "scope"); - OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(parameters, "foo", null, true, Collections.singleton("scope"), null, null, null, null); - - String code = authorizationCodeServices.createAuthorizationCode(new OAuth2Authentication( - storedOAuth2Request, userAuthentication)); - parameters.putAll(storedOAuth2Request.getRequestParameters()); - parameters.put("code", code); - - TokenRequest tokenRequest = requestFactory.createTokenRequest(parameters, client); - - AuthorizationCodeTokenGranter granter = new AuthorizationCodeTokenGranter(providerTokenServices, - authorizationCodeServices, clientDetailsService, requestFactory); - OAuth2AccessToken token = granter.grant("authorization_code", tokenRequest); - assertTrue(providerTokenServices.loadAuthentication(token.getValue()).isAuthenticated()); - } - - @Test - public void testAuthorizationParametersPreserved() { - - parameters.clear(); - parameters.put("foo", "bar"); - parameters.put(OAuth2Utils.CLIENT_ID, "foo"); - parameters.put(OAuth2Utils.SCOPE, "scope"); - OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(parameters, "foo", null, true, Collections.singleton("scope"), null, null, null, null); - - Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala", - AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); - String code = authorizationCodeServices.createAuthorizationCode(new OAuth2Authentication( - storedOAuth2Request, userAuthentication)); - - parameters.put("code", code); - TokenRequest tokenRequest = requestFactory.createTokenRequest(parameters, client); - - AuthorizationCodeTokenGranter granter = new AuthorizationCodeTokenGranter(providerTokenServices, - authorizationCodeServices, clientDetailsService, requestFactory); - OAuth2AccessToken token = granter.grant("authorization_code", tokenRequest); - OAuth2Request finalRequest = providerTokenServices.loadAuthentication(token.getValue()) - .getOAuth2Request(); - assertEquals(code, finalRequest.getRequestParameters().get("code")); - assertEquals("bar", finalRequest.getRequestParameters().get("foo")); - } - - @Test - public void testAuthorizationRequestPreserved() { - - parameters.clear(); - parameters.put(OAuth2Utils.CLIENT_ID, "foo"); - parameters.put(OAuth2Utils.SCOPE, "read"); - OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(parameters, "foo", null, true, Collections.singleton("read"), Collections.singleton("resource"), null, null, null); - - Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala", - AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); - String code = authorizationCodeServices.createAuthorizationCode(new OAuth2Authentication( - storedOAuth2Request, userAuthentication)); - - parameters.put("code", code); - // Ensure even if token request asks for more scope they are not granted - parameters.put(OAuth2Utils.SCOPE, "read write"); - TokenRequest tokenRequest = requestFactory.createTokenRequest(parameters, client); - - AuthorizationCodeTokenGranter granter = new AuthorizationCodeTokenGranter(providerTokenServices, - authorizationCodeServices, clientDetailsService, requestFactory); - OAuth2AccessToken token = granter.grant("authorization_code", tokenRequest); - OAuth2Request finalRequest = providerTokenServices.loadAuthentication(token.getValue()) - .getOAuth2Request(); - assertEquals("[read]", finalRequest.getScope().toString()); - assertEquals("[resource]", finalRequest.getResourceIds().toString()); - assertTrue(finalRequest.isApproved()); - } - - @Test - public void testAuthorizationCodeGrantWithNoClientAuthorities() { - - parameters.clear(); - parameters.put(OAuth2Utils.CLIENT_ID, "foo"); - parameters.put(OAuth2Utils.SCOPE, "scope"); - OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(parameters, "foo", Collections. emptySet(), true, Collections.singleton("scope"), null, null, null, null); - - Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala", - AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); - String code = authorizationCodeServices.createAuthorizationCode(new OAuth2Authentication( - storedOAuth2Request, userAuthentication)); - parameters.put("code", code); - TokenRequest tokenRequest = requestFactory.createTokenRequest(parameters, client); - AuthorizationCodeTokenGranter granter = new AuthorizationCodeTokenGranter(providerTokenServices, - authorizationCodeServices, clientDetailsService, requestFactory); - OAuth2AccessToken token = granter.grant("authorization_code", tokenRequest); - assertTrue(providerTokenServices.loadAuthentication(token.getValue()).isAuthenticated()); - } - - @Test - public void testAuthorizationRedirectMismatch() { - Map initialParameters = new HashMap(); - initialParameters.put(OAuth2Utils.REDIRECT_URI, "https://redirectme/"); - //AuthorizationRequest initialRequest = createFromParameters(initialParameters); - // we fake a valid resolvedRedirectUri because without the client would never come this far - //initialRequest.setRedirectUri(initialParameters.get(REDIRECT_URI)); - - parameters.clear(); - parameters.put(OAuth2Utils.REDIRECT_URI, "https://redirectme/"); - parameters.put(OAuth2Utils.CLIENT_ID, "foo"); - OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(parameters, "foo", null, true, null, null, "https://redirectme/", null, null); - - Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala", - AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); - String code = authorizationCodeServices.createAuthorizationCode(new OAuth2Authentication(storedOAuth2Request, - userAuthentication)); - - Map authorizationParameters = new HashMap(); - authorizationParameters.put("code", code); - - //AuthorizationRequest oAuth2Request = createFromParameters(initialParameters); - //oAuth2Request.setRequestParameters(authorizationParameters); - - TokenRequest tokenRequest = requestFactory.createTokenRequest(parameters, client); - tokenRequest.setRequestParameters(authorizationParameters); - - AuthorizationCodeTokenGranter granter = new AuthorizationCodeTokenGranter(providerTokenServices, - authorizationCodeServices, clientDetailsService, requestFactory); - try { - granter.getOAuth2Authentication(client, tokenRequest); - fail("RedirectMismatchException because of null redirect_uri in authorizationRequest"); - } - catch (RedirectMismatchException e) { - } - } - -} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestDefaultRedirectResolver.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestDefaultRedirectResolver.java deleted file mode 100644 index f0ab68de4..000000000 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestDefaultRedirectResolver.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2006-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.code; - -import static org.junit.Assert.assertEquals; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -import org.junit.Test; -import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; -import org.springframework.security.oauth2.common.exceptions.RedirectMismatchException; -import org.springframework.security.oauth2.provider.BaseClientDetails; -import org.springframework.security.oauth2.provider.endpoint.DefaultRedirectResolver; - -/** - * @author Dave Syer - */ -public class TestDefaultRedirectResolver { - - private DefaultRedirectResolver resolver = new DefaultRedirectResolver(); - - private BaseClientDetails client = new BaseClientDetails(); - - { - client.setAuthorizedGrantTypes(Collections.singleton("authorization_code")); - } - - @Test - public void testRedirectMatchesRegisteredValue() throws Exception { - Set redirectUris = new HashSet(Arrays.asList("http://anywhere.com/")); - client.setRegisteredRedirectUri(redirectUris); - String requestedRedirect = "http://anywhere.com/myendpoint"; - assertEquals(requestedRedirect, resolver.resolveRedirect(requestedRedirect, client)); - } - - @Test - public void testRedirectWithNoRegisteredValue() throws Exception { - String requestedRedirect = "http://anywhere.com/myendpoint"; - assertEquals(requestedRedirect, resolver.resolveRedirect(requestedRedirect, client)); - } - - // If only one redirect has been registered, then we should use it - @Test - public void testRedirectWithNoRequestedValue() throws Exception { - Set redirectUris = new HashSet(Arrays.asList("http://anywhere.com/")); - client.setRegisteredRedirectUri(redirectUris); - resolver.resolveRedirect(null, client); - } - - // If multiple redirects registered, then we should get an exception - @Test(expected = RedirectMismatchException.class) - public void testRedirectWithNoRequestedValueAndMultipleRegistered() throws Exception { - Set redirectUris = new HashSet(Arrays.asList("http://anywhere.com/", "http://nowhere.com/")); - client.setRegisteredRedirectUri(redirectUris); - resolver.resolveRedirect(null, client); - } - - @Test(expected = InvalidGrantException.class) - public void testNoGrantType() throws Exception { - Set redirectUris = new HashSet(Arrays.asList("http://anywhere.com/", "http://nowhere.com/")); - client.setRegisteredRedirectUri(redirectUris); - client.setAuthorizedGrantTypes(Collections.emptyList()); - resolver.resolveRedirect(null, client); - } - - @Test(expected = InvalidGrantException.class) - public void testWrongGrantType() throws Exception { - Set redirectUris = new HashSet(Arrays.asList("http://anywhere.com/", "http://nowhere.com/")); - client.setRegisteredRedirectUri(redirectUris); - client.setAuthorizedGrantTypes(Collections.singleton("client_credentials")); - resolver.resolveRedirect(null, client); - } - - @Test(expected = InvalidGrantException.class) - public void testWrongCustomGrantType() throws Exception { - resolver.setRedirectGrantTypes(Collections.singleton("foo")); - Set redirectUris = new HashSet(Arrays.asList("http://anywhere.com/", "http://nowhere.com/")); - client.setRegisteredRedirectUri(redirectUris); - resolver.resolveRedirect(null, client); - } - - @Test(expected = RedirectMismatchException.class) - public void testRedirectNotMatching() throws Exception { - Set redirectUris = new HashSet(Arrays.asList("http://nowhere.com/")); - String requestedRedirect = "http://anywhere.com/myendpoint"; - client.setRegisteredRedirectUri(redirectUris); - assertEquals(redirectUris.iterator().next(), resolver.resolveRedirect(requestedRedirect, client)); - } - -} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestExactMatchRedirectResolver.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestExactMatchRedirectResolver.java deleted file mode 100644 index 7397b6d90..000000000 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestExactMatchRedirectResolver.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2006-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.code; - -import static org.junit.Assert.assertEquals; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -import org.junit.Test; -import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; -import org.springframework.security.oauth2.common.exceptions.RedirectMismatchException; -import org.springframework.security.oauth2.provider.BaseClientDetails; -import org.springframework.security.oauth2.provider.endpoint.ExactMatchRedirectResolver; - -/** - * @author Dave Syer - */ -public class TestExactMatchRedirectResolver { - - private ExactMatchRedirectResolver resolver = new ExactMatchRedirectResolver(); - private BaseClientDetails client = new BaseClientDetails(); - - { - client.setAuthorizedGrantTypes(Collections.singleton("authorization_code")); - } - - @Test ( expected = RedirectMismatchException.class ) - public void testRedirectNotMatching() throws Exception { - Set redirectUris = new HashSet(Arrays.asList("http://anywhere.com/")); - String requestedRedirect = "http://anywhere.com/myendpoint"; - client.setRegisteredRedirectUri(redirectUris); - assertEquals(redirectUris.iterator().next(), resolver.resolveRedirect(requestedRedirect, client)); - } - - @Test - public void testRedirectWithNoRegisteredValue() throws Exception { - String requestedRedirect = "http://anywhere.com/myendpoint"; - assertEquals(requestedRedirect, resolver.resolveRedirect(requestedRedirect, client)); - } - - // As we have one or more registered redirects, the redirect SHOULD be present. - // If not we should expect a Oauth2Exception. - @Test ( expected = OAuth2Exception.class ) - public void testRedirectWithNoRequestedValue() throws Exception { - Set redirectUris = new HashSet(Arrays.asList("http://anywhere.com/", "http://nowhere.com/")); - client.setRegisteredRedirectUri(redirectUris); - resolver.resolveRedirect(null, client); - } - -} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestInMemoryAuthorizationCodeServices.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestInMemoryAuthorizationCodeServices.java deleted file mode 100644 index 15a35ff20..000000000 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestInMemoryAuthorizationCodeServices.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.springframework.security.oauth2.provider.code; - -import org.junit.Before; - -public class TestInMemoryAuthorizationCodeServices extends TestAuthorizationCodeServicesBase { - - private InMemoryAuthorizationCodeServices authorizationCodeServices; - - @Before - public void setUp() throws Exception { - authorizationCodeServices = new InMemoryAuthorizationCodeServices(); - } - - @Override - AuthorizationCodeServices getAuthorizationCodeServices() { - return authorizationCodeServices; - } -} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestJdbcAuthorizationCodeServices.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestJdbcAuthorizationCodeServices.java deleted file mode 100644 index a9eb09e99..000000000 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestJdbcAuthorizationCodeServices.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.springframework.security.oauth2.provider.code; - -import org.junit.After; -import org.junit.Before; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; - -public class TestJdbcAuthorizationCodeServices extends TestAuthorizationCodeServicesBase { - private JdbcAuthorizationCodeServices authorizationCodeServices; - - private EmbeddedDatabase db; - - @Before - public void setUp() throws Exception { - // creates a HSQL in-memory db populated from default scripts classpath:schema.sql and classpath:data.sql - db = new EmbeddedDatabaseBuilder().addDefaultScripts().build(); - authorizationCodeServices = new JdbcAuthorizationCodeServices(db); - } - - @After - public void tearDown() throws Exception { - db.shutdown(); - } - - @Override - AuthorizationCodeServices getAuthorizationCodeServices() { - return authorizationCodeServices; - } -} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestSubdomainRedirectResolver.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestSubdomainRedirectResolver.java deleted file mode 100644 index 79f4e0612..000000000 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/TestSubdomainRedirectResolver.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.springframework.security.oauth2.provider.code; - -import static org.junit.Assert.assertEquals; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -import org.junit.Test; -import org.springframework.security.oauth2.common.exceptions.RedirectMismatchException; -import org.springframework.security.oauth2.provider.BaseClientDetails; -import org.springframework.security.oauth2.provider.endpoint.DefaultRedirectResolver; - -public class TestSubdomainRedirectResolver -{ - private final DefaultRedirectResolver resolver = new DefaultRedirectResolver(); - private final BaseClientDetails client = new BaseClientDetails(); - - { - client.setAuthorizedGrantTypes(Collections.singleton("authorization_code")); - } - - - @Test - public void testRedirectWatchdox() throws Exception - { - Set redirectUris = new HashSet(Arrays.asList("http://watchdox.com/")); - client.setRegisteredRedirectUri(redirectUris); - String requestedRedirect = "http://anywhere.watchdox.com/something"; - assertEquals(requestedRedirect, resolver.resolveRedirect(requestedRedirect, client)); - } - - @Test(expected=RedirectMismatchException.class) - public void testRedirectBadWatchdox() throws Exception - { - Set redirectUris = new HashSet(Arrays.asList("http//watchdox.com")); - client.setRegisteredRedirectUri(redirectUris); - String requestedRedirect = "http://anywhere.google.com/something"; - assertEquals(requestedRedirect, resolver.resolveRedirect(requestedRedirect, client)); - } - -} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestAuthorizationEndpoint.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java similarity index 99% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestAuthorizationEndpoint.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java index 6c11b0a26..c240ce10c 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestAuthorizationEndpoint.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java @@ -55,7 +55,7 @@ * @author Dave Syer * */ -public class TestAuthorizationEndpoint { +public class AuthorizationEndpointTests { private AuthorizationEndpoint endpoint = new AuthorizationEndpoint(); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestTokenEndpointAuthenticationFilter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilterTests.java similarity index 98% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestTokenEndpointAuthenticationFilter.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilterTests.java index 58bdaaf07..58f293e6b 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestTokenEndpointAuthenticationFilter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilterTests.java @@ -43,7 +43,7 @@ * @author Dave Syer * */ -public class TestTokenEndpointAuthenticationFilter { +public class TokenEndpointAuthenticationFilterTests { private MockHttpServletRequest request = new MockHttpServletRequest(); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestTokenEndpoint.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointTests.java similarity index 99% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestTokenEndpoint.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointTests.java index 58092cb68..382f647dd 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestTokenEndpoint.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointTests.java @@ -53,7 +53,7 @@ * @author Rob Winch */ @RunWith(MockitoJUnitRunner.class) -public class TestTokenEndpoint { +public class TokenEndpointTests { @Mock private TokenGranter tokenGranter; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestWhitelabelApprovalEndpoint.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelApprovalEndpointTests.java similarity index 98% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestWhitelabelApprovalEndpoint.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelApprovalEndpointTests.java index 2e2131213..1a9f3789c 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TestWhitelabelApprovalEndpoint.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelApprovalEndpointTests.java @@ -32,7 +32,7 @@ * @author Dave Syer * */ -public class TestWhitelabelApprovalEndpoint { +public class WhitelabelApprovalEndpointTests { private WhitelabelApprovalEndpoint endpoint = new WhitelabelApprovalEndpoint(); private Map parameters = new HashMap(); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/TestOAuth2AccessDeniedHandler.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/OAuth2AccessDeniedHandlerTests.java similarity index 97% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/TestOAuth2AccessDeniedHandler.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/OAuth2AccessDeniedHandlerTests.java index c5dbef733..969c1c8d5 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/TestOAuth2AccessDeniedHandler.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/OAuth2AccessDeniedHandlerTests.java @@ -26,7 +26,7 @@ * @author Dave Syer * */ -public class TestOAuth2AccessDeniedHandler { +public class OAuth2AccessDeniedHandlerTests { private OAuth2AccessDeniedHandler handler = new OAuth2AccessDeniedHandler(); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/TestOAuth2AuthenticationEntryPoint.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/OAuth2AuthenticationEntryPointTests.java similarity index 98% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/TestOAuth2AuthenticationEntryPoint.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/OAuth2AuthenticationEntryPointTests.java index 812ad63a5..7c437cfc6 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/TestOAuth2AuthenticationEntryPoint.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/OAuth2AuthenticationEntryPointTests.java @@ -28,7 +28,7 @@ * @author Dave Syer * */ -public class TestOAuth2AuthenticationEntryPoint { +public class OAuth2AuthenticationEntryPointTests { private OAuth2AuthenticationEntryPoint entryPoint = new OAuth2AuthenticationEntryPoint(); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2MethodSecurityExpressionHandler.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2MethodSecurityExpressionHandlerTests.java similarity index 99% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2MethodSecurityExpressionHandler.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2MethodSecurityExpressionHandlerTests.java index 9f019b122..47bbc5139 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2MethodSecurityExpressionHandler.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2MethodSecurityExpressionHandlerTests.java @@ -41,7 +41,7 @@ * @author Radek Ostrowski * */ -public class TestOAuth2MethodSecurityExpressionHandler { +public class OAuth2MethodSecurityExpressionHandlerTests { private OAuth2MethodSecurityExpressionHandler handler = new OAuth2MethodSecurityExpressionHandler(); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2SecurityExpressionMethods.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethodsTests.java similarity index 99% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2SecurityExpressionMethods.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethodsTests.java index f07bab5d9..e6eaa7ac1 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2SecurityExpressionMethods.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethodsTests.java @@ -36,7 +36,7 @@ * @author Dave Syer * */ -public class TestOAuth2SecurityExpressionMethods { +public class OAuth2SecurityExpressionMethodsTests { @Test public void testOauthClient() throws Exception { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2WebSecurityExpressionHandler.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2WebSecurityExpressionHandlerTests.java similarity index 98% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2WebSecurityExpressionHandler.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2WebSecurityExpressionHandlerTests.java index 8d0ea65e2..257eb67b8 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/TestOAuth2WebSecurityExpressionHandler.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2WebSecurityExpressionHandlerTests.java @@ -36,7 +36,7 @@ * @author Dave Syer * */ -public class TestOAuth2WebSecurityExpressionHandler { +public class OAuth2WebSecurityExpressionHandlerTests { private OAuth2WebSecurityExpressionHandler handler = new OAuth2WebSecurityExpressionHandler(); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/implicit/TestInMemoryImplicitGrantService.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/implicit/InMemoryImplicitGrantServiceTests.java similarity index 97% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/implicit/TestInMemoryImplicitGrantService.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/implicit/InMemoryImplicitGrantServiceTests.java index 2a2d92764..a9744b460 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/implicit/TestInMemoryImplicitGrantService.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/implicit/InMemoryImplicitGrantServiceTests.java @@ -27,7 +27,7 @@ * @author Dave Syer * */ -public class TestInMemoryImplicitGrantService { +public class InMemoryImplicitGrantServiceTests { private InMemoryImplicitGrantService service = new InMemoryImplicitGrantService(); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/TestResourceOwnerPasswordTokenGranter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranterTests.java similarity index 98% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/TestResourceOwnerPasswordTokenGranter.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranterTests.java index 21f850967..d6bbc63c5 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/TestResourceOwnerPasswordTokenGranter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranterTests.java @@ -45,7 +45,7 @@ * @author Dave Syer * */ -public class TestResourceOwnerPasswordTokenGranter { +public class ResourceOwnerPasswordTokenGranterTests { private Authentication validUser = new UsernamePasswordAuthenticationToken( "foo", "bar", @@ -75,7 +75,7 @@ public ClientDetails loadClientByClientId(String clientId) private TokenRequest tokenRequest; - public TestResourceOwnerPasswordTokenGranter() { + public ResourceOwnerPasswordTokenGranterTests() { String clientId = "client"; BaseClientDetails clientDetails = new BaseClientDetails(); clientDetails.setClientId(clientId); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestDefaultTokenServicesWithInMemory.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithInMemoryTests.java similarity index 98% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestDefaultTokenServicesWithInMemory.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithInMemoryTests.java index 659179dd6..fc591b36d 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestDefaultTokenServicesWithInMemory.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithInMemoryTests.java @@ -32,7 +32,7 @@ * @author Dave Syer * */ -public class TestDefaultTokenServicesWithInMemory extends AbstractTestDefaultTokenServices { +public class DefaultTokenServicesWithInMemoryTests extends AbstractTestDefaultTokenServices { private InMemoryTokenStore tokenStore; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestDefaultTokenServicesWithJdbc.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithJdbcTests.java similarity index 90% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestDefaultTokenServicesWithJdbc.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithJdbcTests.java index b5215951f..30cde2d72 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestDefaultTokenServicesWithJdbc.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithJdbcTests.java @@ -9,7 +9,7 @@ * @author Dave Syer * */ -public class TestDefaultTokenServicesWithJdbc extends AbstractTestDefaultTokenServices { +public class DefaultTokenServicesWithJdbcTests extends AbstractTestDefaultTokenServices { private EmbeddedDatabase db; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestInMemoryTokenStore.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStoreTests.java similarity index 97% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestInMemoryTokenStore.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStoreTests.java index ae7b0d22e..ab4bbd37f 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestInMemoryTokenStore.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStoreTests.java @@ -14,7 +14,7 @@ * @author Dave Syer * */ -public class TestInMemoryTokenStore extends TestTokenStoreBase { +public class InMemoryTokenStoreTests extends TokenStoreBaseTests { private InMemoryTokenStore tokenStore; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJdbcTokenStore.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JdbcTokenStoreTests.java similarity index 92% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJdbcTokenStore.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JdbcTokenStoreTests.java index 86d0d0efc..963c41399 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJdbcTokenStore.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JdbcTokenStoreTests.java @@ -9,7 +9,7 @@ * @author Dave Syer * */ -public class TestJdbcTokenStore extends TestTokenStoreBase { +public class JdbcTokenStoreTests extends TokenStoreBaseTests { private JdbcTokenStore tokenStore; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJwtTokenEnhancer.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancerTests.java similarity index 99% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJwtTokenEnhancer.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancerTests.java index 5126e9c9a..39f4d13dd 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJwtTokenEnhancer.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancerTests.java @@ -33,7 +33,7 @@ * @author Dave Syer * @author Luke Taylor */ -public class TestJwtTokenEnhancer { +public class JwtTokenEnhancerTests { private JwtTokenEnhancer tokenEnhancer; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJwtTokenServices.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenServicesTests.java similarity index 99% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJwtTokenServices.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenServicesTests.java index 69866e65c..c45afde09 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestJwtTokenServices.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenServicesTests.java @@ -47,7 +47,7 @@ * @author Dave Syer * */ -public class TestJwtTokenServices { +public class JwtTokenServicesTests { private JwtTokenServices services = new JwtTokenServices(); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestTokenStoreBase.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenStoreBaseTests.java similarity index 99% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestTokenStoreBase.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenStoreBaseTests.java index 8c637b188..f1ef9cb8d 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TestTokenStoreBase.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenStoreBaseTests.java @@ -35,7 +35,7 @@ * @author Dave Syer * */ -public abstract class TestTokenStoreBase { +public abstract class TokenStoreBaseTests { public abstract TokenStore getTokenStore(); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/TestClientScopeVoter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/ClientScopeVoterTests.java similarity index 98% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/TestClientScopeVoter.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/ClientScopeVoterTests.java index 82f6b58c9..c35882a1d 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/TestClientScopeVoter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/ClientScopeVoterTests.java @@ -19,7 +19,7 @@ import org.springframework.security.oauth2.provider.InMemoryClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; -public class TestClientScopeVoter { +public class ClientScopeVoterTests { private ClientScopeVoter voter = new ClientScopeVoter(); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/TestScopeVoter.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/ScopeVoterTests.java similarity index 99% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/TestScopeVoter.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/ScopeVoterTests.java index 19040a812..b551445de 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/TestScopeVoter.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/ScopeVoterTests.java @@ -35,7 +35,7 @@ * @author Dave Syer * */ -public class TestScopeVoter { +public class ScopeVoterTests { private ScopeVoter voter = new ScopeVoter(); diff --git a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/TestClientDetailsServiceBeanDefinitionParser-context.xml b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/ClientDetailsServiceBeanDefinitionParserTests-context.xml similarity index 100% rename from spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/TestClientDetailsServiceBeanDefinitionParser-context.xml rename to spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/ClientDetailsServiceBeanDefinitionParserTests-context.xml diff --git a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/TestResourceBeanDefinitionParser-context.xml b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/ResourceBeanDefinitionParserTests-context.xml similarity index 100% rename from spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/TestResourceBeanDefinitionParser-context.xml rename to spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/ResourceBeanDefinitionParserTests-context.xml diff --git a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-custom-grant.xml b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-custom-grant.xml index 544fd0952..540143a91 100644 --- a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-custom-grant.xml +++ b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-custom-grant.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2%20http://www.springframework.org/schema/security/spring-security-oauth2.xsd%20http://www.springframework.org/schema/beans%20http://www.springframework.org/schema/beans/spring-beans.xsd"> - + From a82c645b119712b33902542410b33a60e53d3b77 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 14 Feb 2014 17:13:23 +0000 Subject: [PATCH 156/831] More care with proxies in @Configuration Apparently the rule of thumb is: if a @Bean uses a configurer to grab one of it's dependencies then it should be a lazy proxy in case it is used before the configurer has initialized. In addition we find that an Application.class that extends OAuth2AuthorizationServerConfigurerAdapter directly is problematic, but if you nest it it works fine. Problems manifest themselves in objects that ought to be proxies not being proxied (i.e. early instantiation going on somewhere). This has no impact on Spring OAuth (yet), but it affects applications that use it. --- ...2AuthorizationServerConfigurerAdapter.java | 179 +++++++++--------- .../endpoint/AuthorizationEndpoint.java | 7 +- 2 files changed, 95 insertions(+), 91 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/OAuth2AuthorizationServerConfigurerAdapter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/OAuth2AuthorizationServerConfigurerAdapter.java index 3c5c2f315..7b1accca6 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/OAuth2AuthorizationServerConfigurerAdapter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/OAuth2AuthorizationServerConfigurerAdapter.java @@ -31,6 +31,7 @@ import org.springframework.security.oauth2.provider.endpoint.FrameworkEndpointHandlerMapping; import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint; import org.springframework.security.oauth2.provider.endpoint.WhitelabelApprovalEndpoint; +import org.springframework.security.oauth2.provider.implicit.ImplicitGrantService; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; import org.springframework.security.oauth2.provider.token.ConsumerTokenServices; import org.springframework.security.oauth2.provider.token.TokenStore; @@ -38,94 +39,102 @@ /** * @author Rob Winch * @author Dave Syer - * + * */ @Configuration public abstract class OAuth2AuthorizationServerConfigurerAdapter extends WebSecurityConfigurerAdapter { - @Bean - public AuthorizationEndpoint authorizationEndpoint() throws Exception { - AuthorizationEndpoint authorizationEndpoint = new AuthorizationEndpoint(); - authorizationEndpoint.setTokenGranter(tokenGranter()); - authorizationEndpoint.setClientDetailsService(clientDetailsService()); - authorizationEndpoint.setAuthorizationCodeServices(authorizationCodeServices()); - authorizationEndpoint.setUserApprovalHandler(userApprovalHandler()); - authorizationEndpoint.setImplicitGrantService(authorizationServerConfigurer().getImplicitGrantService()); - return authorizationEndpoint; - } - - @Bean - @Lazy - @Scope(proxyMode=ScopedProxyMode.INTERFACES) - public ConsumerTokenServices consumerTokenServices() throws Exception { - return authorizationServerConfigurer().getConsumerTokenServices(); - } - - @Bean - public TokenEndpoint tokenEndpoint() throws Exception { - TokenEndpoint tokenEndpoint = new TokenEndpoint(); - tokenEndpoint.setClientDetailsService(clientDetailsService()); - tokenEndpoint.setTokenGranter(tokenGranter()); - return tokenEndpoint; - } - - @Bean - @Lazy - @Scope(proxyMode=ScopedProxyMode.INTERFACES) - public OAuth2RequestFactory oauth2RequestFactory() throws Exception { - return authorizationServerConfigurer().getOAuth2RequestFactory(); - } - - @Bean - @Lazy - @Scope(proxyMode=ScopedProxyMode.INTERFACES) - public TokenStore tokenStore() throws Exception { - return authorizationServerConfigurer().getTokenStore(); - } - - @Bean + @Bean + public AuthorizationEndpoint authorizationEndpoint() throws Exception { + AuthorizationEndpoint authorizationEndpoint = new AuthorizationEndpoint(); + authorizationEndpoint.setTokenGranter(tokenGranter()); + authorizationEndpoint.setClientDetailsService(clientDetailsService()); + authorizationEndpoint.setAuthorizationCodeServices(authorizationCodeServices()); + authorizationEndpoint.setUserApprovalHandler(userApprovalHandler()); + authorizationEndpoint.setImplicitGrantService(getImplicitGrantService()); + return authorizationEndpoint; + } + + @Bean + @Lazy + @Scope(proxyMode = ScopedProxyMode.INTERFACES) + public ImplicitGrantService getImplicitGrantService() throws Exception { + return authorizationServerConfigurer().getImplicitGrantService(); + } + + @Bean + @Lazy + @Scope(proxyMode = ScopedProxyMode.INTERFACES) + public ConsumerTokenServices consumerTokenServices() throws Exception { + return authorizationServerConfigurer().getConsumerTokenServices(); + } + + @Bean + public TokenEndpoint tokenEndpoint() throws Exception { + TokenEndpoint tokenEndpoint = new TokenEndpoint(); + tokenEndpoint.setClientDetailsService(clientDetailsService()); + tokenEndpoint.setTokenGranter(tokenGranter()); + return tokenEndpoint; + } + + @Bean + @Lazy + @Scope(proxyMode = ScopedProxyMode.INTERFACES) + public OAuth2RequestFactory oauth2RequestFactory() throws Exception { + return authorizationServerConfigurer().getOAuth2RequestFactory(); + } + + @Bean + @Lazy + @Scope(proxyMode = ScopedProxyMode.INTERFACES) + public TokenStore tokenStore() throws Exception { + return authorizationServerConfigurer().getTokenStore(); + } + + @Bean @Lazy - @Scope(proxyMode=ScopedProxyMode.INTERFACES) - public UserApprovalHandler userApprovalHandler() throws Exception { - return authorizationServerConfigurer().getUserApprovalHandler(); - } - - protected AuthorizationServerTokenServices tokenServices() throws Exception { - return authorizationServerConfigurer().getTokenServices(); - } - - @Bean - public WhitelabelApprovalEndpoint approvalEndpoint() { - return new WhitelabelApprovalEndpoint(); - } - - @Bean - public FrameworkEndpointHandlerMapping endpointHandlerMapping() { - return new FrameworkEndpointHandlerMapping(); - } - - @Bean - @Lazy - @Scope(proxyMode=ScopedProxyMode.INTERFACES) - public ClientDetailsService clientDetailsService() throws Exception { - return getHttp().getSharedObject(ClientDetailsService.class); - } - - @Bean - @Lazy - @Scope(proxyMode=ScopedProxyMode.INTERFACES) - public AuthorizationCodeServices authorizationCodeServices() throws Exception { - return authorizationServerConfigurer().getAuthorizationCodeServices(); - } - - @Bean - @Lazy - @Scope(proxyMode=ScopedProxyMode.INTERFACES) - public TokenGranter tokenGranter() throws Exception { - return authorizationServerConfigurer().getTokenGranter(); - } - - private OAuth2AuthorizationServerConfigurer authorizationServerConfigurer() throws Exception { - return getHttp().getConfigurer(OAuth2AuthorizationServerConfigurer.class); - } + @Scope(proxyMode = ScopedProxyMode.INTERFACES) + public UserApprovalHandler userApprovalHandler() throws Exception { + return authorizationServerConfigurer().getUserApprovalHandler(); + } + + protected AuthorizationServerTokenServices tokenServices() throws Exception { + return authorizationServerConfigurer().getTokenServices(); + } + + @Bean + public WhitelabelApprovalEndpoint approvalEndpoint() { + return new WhitelabelApprovalEndpoint(); + } + + @Bean + public FrameworkEndpointHandlerMapping endpointHandlerMapping() { + return new FrameworkEndpointHandlerMapping(); + } + + @Bean + @Lazy + @Scope(proxyMode = ScopedProxyMode.INTERFACES) + public ClientDetailsService clientDetailsService() throws Exception { + return getHttp().getSharedObject(ClientDetailsService.class); + } + + @Bean + @Lazy + @Scope(proxyMode = ScopedProxyMode.INTERFACES) + public AuthorizationCodeServices authorizationCodeServices() throws Exception { + return authorizationServerConfigurer().getAuthorizationCodeServices(); + } + + @Bean + @Lazy + @Scope(proxyMode = ScopedProxyMode.INTERFACES) + public TokenGranter tokenGranter() throws Exception { + return authorizationServerConfigurer().getTokenGranter(); + } + + private OAuth2AuthorizationServerConfigurer authorizationServerConfigurer() throws Exception { + return getHttp().getConfigurer(OAuth2AuthorizationServerConfigurer.class); + } + } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java index 0050b957b..47c3211f2 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java @@ -22,7 +22,6 @@ import java.util.Map; import java.util.Set; -import org.springframework.beans.factory.InitializingBean; import org.springframework.http.ResponseEntity; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.authentication.InsufficientAuthenticationException; @@ -89,7 +88,7 @@ @FrameworkEndpoint @SessionAttributes("authorizationRequest") @RequestMapping(value = "/oauth/authorize") -public class AuthorizationEndpoint extends AbstractEndpoint implements InitializingBean { +public class AuthorizationEndpoint extends AbstractEndpoint { private AuthorizationCodeServices authorizationCodeServices = new InMemoryAuthorizationCodeServices(); @@ -107,10 +106,6 @@ public class AuthorizationEndpoint extends AbstractEndpoint implements Initializ private String errorPage = "forward:/oauth/error"; - public void afterPropertiesSet() throws Exception { - super.afterPropertiesSet(); - } - public void setSessionAttributeStore(SessionAttributeStore sessionAttributeStore) { this.sessionAttributeStore = sessionAttributeStore; } From b6d1a60248df785c91c279c682cdbb67dc939db7 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 14 Feb 2014 17:37:44 +0000 Subject: [PATCH 157/831] Fix typo in login.jsp --- samples/oauth2/tonr/src/main/webapp/login.jsp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/oauth2/tonr/src/main/webapp/login.jsp b/samples/oauth2/tonr/src/main/webapp/login.jsp index c7ff47166..b92324b27 100644 --- a/samples/oauth2/tonr/src/main/webapp/login.jsp +++ b/samples/oauth2/tonr/src/main/webapp/login.jsp @@ -53,7 +53,7 @@ for "marissa" is password is "wombat" and for "sam" is password is "kangaroo".

-
" method="post" role="form"> +

Login

From 602e4e3bec8d75e36cd65c1b43c5168ebfac6948 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 14 Feb 2014 17:38:43 +0000 Subject: [PATCH 158/831] Extract /token security into base class --- .../sparklr/config/OAuth2ServerConfig.java | 37 +++++-------- ...2AuthorizationServerConfigurerAdapter.java | 20 +++++++ ...AuthorizationServerConfigurationTests.java | 55 +++---------------- 3 files changed, 42 insertions(+), 70 deletions(-) diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java index 91ed68f4a..f44bd5316 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java @@ -68,14 +68,15 @@ public void configure(WebSecurity builder) throws Exception { ignoring.antMatchers("/oauth/uncache_approvals", "/oauth/cache_approvals"); } - @Bean - public AdminController adminController(TokenStore tokenStore, ConsumerTokenServices tokenServices, SparklrUserApprovalHandler userApprovalHandler) { - AdminController adminController = new AdminController(); - adminController.setTokenStore(tokenStore); - adminController.setTokenServices(tokenServices); - adminController.setUserApprovalHandler(userApprovalHandler); - return adminController; - } + @Bean + public AdminController adminController(TokenStore tokenStore, ConsumerTokenServices tokenServices, + SparklrUserApprovalHandler userApprovalHandler) { + AdminController adminController = new AdminController(); + adminController.setTokenStore(tokenStore); + adminController.setTokenServices(tokenServices); + adminController.setUserApprovalHandler(userApprovalHandler); + return adminController; + } @Override protected void configure(HttpSecurity http) throws Exception { @@ -183,7 +184,7 @@ protected void configure(AuthenticationManagerBuilder auth) throws Exception { @Bean @Override @Lazy - @Scope(proxyMode=ScopedProxyMode.TARGET_CLASS) + @Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) public SparklrUserApprovalHandler userApprovalHandler() throws Exception { SparklrUserApprovalHandler handler = new SparklrUserApprovalHandler(); handler.setApprovalStore(approvalStore()); @@ -201,21 +202,9 @@ public ApprovalStore approvalStore() throws Exception { } @Override - protected void configure(HttpSecurity http) throws Exception { - // @formatter:off - http - .authorizeRequests() - .antMatchers("/oauth/token").fullyAuthenticated() - .and() - .requestMatchers() - .antMatchers("/oauth/token") - .and() - .apply(new OAuth2AuthorizationServerConfigurer()) - .tokenStore(tokenStore) - .userApprovalHandler(userApprovalHandler()) - .authenticationManager(authenticationManager) - .realm("sparklr2/client"); - // @formatter:on + protected void configure(OAuth2AuthorizationServerConfigurer oauthServer) throws Exception { + oauthServer.tokenStore(tokenStore).userApprovalHandler(userApprovalHandler()) + .authenticationManager(authenticationManager).realm("sparklr2/client"); } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/OAuth2AuthorizationServerConfigurerAdapter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/OAuth2AuthorizationServerConfigurerAdapter.java index 7b1accca6..64467785e 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/OAuth2AuthorizationServerConfigurerAdapter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/OAuth2AuthorizationServerConfigurerAdapter.java @@ -20,6 +20,7 @@ import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.ScopedProxyMode; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer; import org.springframework.security.oauth2.provider.ClientDetailsService; @@ -44,6 +45,25 @@ @Configuration public abstract class OAuth2AuthorizationServerConfigurerAdapter extends WebSecurityConfigurerAdapter { + @Override + protected void configure(HttpSecurity http) throws Exception { + configure(// @formatter:off + http + .authorizeRequests() + .antMatchers("/oauth/token").fullyAuthenticated() + .and() + .requestMatchers() + .antMatchers("/oauth/token") + .and() + .apply(new OAuth2AuthorizationServerConfigurer()) + // @formatter:on + ); + } + + protected void configure(OAuth2AuthorizationServerConfigurer oauthServer) throws Exception { + // Default is no-op + } + @Bean public AuthorizationEndpoint authorizationEndpoint() throws Exception { AuthorizationEndpoint authorizationEndpoint = new AuthorizationEndpoint(); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java index d6d448ec4..661077db9 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java @@ -26,7 +26,6 @@ import org.junit.runners.Parameterized.Parameters; import org.springframework.context.annotation.Configuration; import org.springframework.mock.web.MockServletContext; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity; import org.springframework.security.oauth2.config.annotation.web.configuration.OAuth2AuthorizationServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer; @@ -70,69 +69,33 @@ public void close() { public void testDefaults() { assertTrue(context.containsBeanDefinition("authorizationEndpoint")); } - + @Configuration @EnableWebMvcSecurity protected static class AuthorizationServerVanilla extends OAuth2AuthorizationServerConfigurerAdapter { - - @Override - protected void configure(HttpSecurity http) throws Exception { - // @formatter:off - http - .authorizeRequests() - .antMatchers("/oauth/token").fullyAuthenticated() - .and() - .requestMatchers() - .antMatchers("/oauth/token") - .and() - .apply(new OAuth2AuthorizationServerConfigurer()); - // @formatter:on - } - } @Configuration @EnableWebMvcSecurity protected static class AuthorizationServerExtras extends OAuth2AuthorizationServerConfigurerAdapter { - + private TokenStore tokenStore = new InMemoryTokenStore(); @Override - protected void configure(HttpSecurity http) throws Exception { - // @formatter:off - http - .authorizeRequests() - .antMatchers("/oauth/token").fullyAuthenticated() - .and() - .requestMatchers() - .antMatchers("/oauth/token") - .and() - .apply(new OAuth2AuthorizationServerConfigurer()) - .tokenStore(tokenStore) - .authenticationManager(super.authenticationManagerBean()) - .realm("sparklr2/client"); - // @formatter:on + protected void configure(OAuth2AuthorizationServerConfigurer oauthServer) throws Exception { + oauthServer.tokenStore(tokenStore).authenticationManager(super.authenticationManagerBean()) + .realm("sparklr2/client"); } } @Configuration @EnableWebMvcSecurity - protected static class AuthorizationServerTypes extends OAuth2AuthorizationServerConfigurerAdapter { - + protected static class AuthorizationServerTypes extends OAuth2AuthorizationServerConfigurerAdapter { + + // TODO: actually configure a token granter @Override - protected void configure(HttpSecurity http) throws Exception { - // TODO: actually configure a token granter - // @formatter:off - http - .authorizeRequests() - .antMatchers("/oauth/token").fullyAuthenticated() - .and() - .requestMatchers() - .antMatchers("/oauth/token") - .and() - .apply(new OAuth2AuthorizationServerConfigurer()); - // @formatter:on + protected void configure(OAuth2AuthorizationServerConfigurer oauthServer) throws Exception { } } From bfd50b81d02c0c330158ff6c3bcd196045839ba8 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 14 Feb 2014 17:45:42 +0000 Subject: [PATCH 159/831] Fix integration test from command line --- samples/oauth2/tonr/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 8bb3fd757..75055e810 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -63,7 +63,7 @@ ${pom.groupId} - java-sparklr2 + sparklr2 ${pom.version} war tomcat From 34c814d6f96daeba5c5765058b85bf3d095b9696 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 7 Mar 2014 09:36:40 +0000 Subject: [PATCH 160/831] Remove parent directory path traversals in DefaultRedirectResolver To prevent redirect matches in sibling and ancestor resources we need to flatten the path when matching redirects. It's not a major vulnerability especially since most registrations are in the form of a root resource, but worth patching anyway. A similar bug contributed to a publicly revealed hack on Github, but in the workds of the attacker "is not worth much on its own". Fixes gh-155 --- .gitignore | 2 +- .../endpoint/DefaultRedirectResolver.java | 2 +- ...orizationCodeAccessTokenProviderTests.java | 101 ++++++++ ...ccessTokenProviderWithConversionTests.java | 231 ++++++++++++++++++ ...AuthorizationCodeResourceDetailsTests.java | 47 ++++ .../AuthorizationCodeServicesBaseTests.java | 82 +++++++ .../AuthorizationCodeTokenGranterTests.java | 207 ++++++++++++++++ ...nMemoryAuthorizationCodeServicesTests.java | 18 ++ .../JdbcAuthorizationCodeServicesTests.java | 29 +++ .../code/SubdomainRedirectResolverTests.java | 43 ++++ .../DefaultRedirectResolverTests.java | 111 +++++++++ .../ExactMatchRedirectResolverTests.java | 63 +++++ 12 files changed, 934 insertions(+), 2 deletions(-) create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProviderTests.java create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProviderWithConversionTests.java create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeResourceDetailsTests.java create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeServicesBaseTests.java create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranterTests.java create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/InMemoryAuthorizationCodeServicesTests.java create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/JdbcAuthorizationCodeServicesTests.java create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/SubdomainRedirectResolverTests.java create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolverTests.java create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/ExactMatchRedirectResolverTests.java diff --git a/.gitignore b/.gitignore index b360663c6..3cc2e963f 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,6 @@ target/ *.iws *.ipr .idea/ -code/ +./code/ cargo-installs/ atlassian-ide-plugin.xml diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolver.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolver.java index 3fedb78fa..74763eb2f 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolver.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolver.java @@ -115,7 +115,7 @@ protected boolean redirectMatches(String requestedRedirect, String redirectUri) URL reg = new URL(redirectUri); if (reg.getProtocol().equals(req.getProtocol()) && hostMatches(reg.getHost(), req.getHost())) { - return req.getPath().startsWith(reg.getPath()); + return StringUtils.cleanPath(req.getPath()).startsWith(StringUtils.cleanPath(reg.getPath())); } } catch (MalformedURLException e) { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProviderTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProviderTests.java new file mode 100644 index 000000000..8c3c26ca4 --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProviderTests.java @@ -0,0 +1,101 @@ +/* + * Copyright 2006-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.client.token.grant.code; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.springframework.http.HttpHeaders; +import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails; +import org.springframework.security.oauth2.client.resource.UserRedirectRequiredException; +import org.springframework.security.oauth2.client.token.AccessTokenRequest; +import org.springframework.security.oauth2.client.token.DefaultAccessTokenRequest; +import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; + +/** + * @author Dave Syer + * + */ +public class AuthorizationCodeAccessTokenProviderTests { + + @Rule + public ExpectedException expected = ExpectedException.none(); + + private MultiValueMap params = new LinkedMultiValueMap(); + + private AuthorizationCodeAccessTokenProvider provider = new AuthorizationCodeAccessTokenProvider() { + @Override + protected OAuth2AccessToken retrieveToken(AccessTokenRequest request, OAuth2ProtectedResourceDetails resource, + MultiValueMap form, HttpHeaders headers) { + params.putAll(form); + return new DefaultOAuth2AccessToken("FOO"); + } + }; + + private AuthorizationCodeResourceDetails resource = new AuthorizationCodeResourceDetails(); + + @Test + public void testGetAccessToken() throws Exception { + AccessTokenRequest request = new DefaultAccessTokenRequest(); + request.setAuthorizationCode("foo"); + resource.setAccessTokenUri("http://localhost/oauth/token"); + assertEquals("FOO", provider.obtainAccessToken(resource, request).getValue()); + } + + @Test + public void testRedirectToAuthorizationEndpoint() throws Exception { + AccessTokenRequest request = new DefaultAccessTokenRequest(); + request.setCurrentUri("/come/back/soon"); + resource.setUserAuthorizationUri("http://localhost/oauth/authorize"); + try { + provider.obtainAccessToken(resource, request); + fail("Expected UserRedirectRequiredException"); + } + catch (UserRedirectRequiredException e) { + assertEquals("http://localhost/oauth/authorize", e.getRedirectUri()); + assertEquals("/come/back/soon", e.getStateToPreserve()); + } + } + + // A missing redirect just means the server has to deal with it + @Test(expected = UserRedirectRequiredException.class) + public void testRedirectNotSpecified() throws Exception { + AccessTokenRequest request = new DefaultAccessTokenRequest(); + resource.setUserAuthorizationUri("http://localhost/oauth/authorize"); + provider.obtainAccessToken(resource, request); + } + + @Test + public void testGetAccessTokenRequest() throws Exception { + AccessTokenRequest request = new DefaultAccessTokenRequest(); + request.setAuthorizationCode("foo"); + request.setStateKey("bar"); + request.setPreservedState(new Object()); + resource.setAccessTokenUri("http://localhost/oauth/token"); + resource.setPreEstablishedRedirectUri("http://anywhere.com/"); + assertEquals("FOO", provider.obtainAccessToken(resource, request).getValue()); + // System.err.println(params); + assertEquals("authorization_code", params.getFirst("grant_type")); + assertEquals("foo", params.getFirst("code")); + assertEquals("http://anywhere.com/", params.getFirst("redirect_uri")); + // State is not set in token request + assertEquals(null, params.getFirst("state")); + } + +} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProviderWithConversionTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProviderWithConversionTests.java new file mode 100644 index 000000000..34fca6f85 --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProviderWithConversionTests.java @@ -0,0 +1,231 @@ +/* + * Copyright 2006-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.client.token.grant.code; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.junit.Assert.assertEquals; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URI; +import java.net.URISyntaxException; + +import org.codehaus.jackson.map.ObjectMapper; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.client.ClientHttpRequest; +import org.springframework.http.client.ClientHttpRequestFactory; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.security.oauth2.client.resource.OAuth2AccessDeniedException; +import org.springframework.security.oauth2.client.token.AccessTokenRequest; +import org.springframework.security.oauth2.client.token.DefaultAccessTokenRequest; +import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.common.exceptions.InvalidClientException; + +/** + * @author Dave Syer + * + */ +public class AuthorizationCodeAccessTokenProviderWithConversionTests { + + private static class StubClientHttpRequest implements ClientHttpRequest { + + private static final HttpHeaders DEFAULT_RESPONSE_HEADERS = new HttpHeaders(); + + private final HttpStatus responseStatus; + + private final HttpHeaders responseHeaders; + + private final String responseBody; + + { + DEFAULT_RESPONSE_HEADERS.setContentType(MediaType.APPLICATION_JSON); + } + + public StubClientHttpRequest(String responseBody) { + this(HttpStatus.OK, DEFAULT_RESPONSE_HEADERS, responseBody); + } + + public StubClientHttpRequest(HttpHeaders responseHeaders, String responseBody) { + this(HttpStatus.OK, responseHeaders, responseBody); + } + + public StubClientHttpRequest(HttpStatus responseStatus, String responseBody) { + this(responseStatus, DEFAULT_RESPONSE_HEADERS, responseBody); + } + + public StubClientHttpRequest(HttpStatus responseStatus, HttpHeaders responseHeaders, String responseBody) { + this.responseStatus = responseStatus; + this.responseHeaders = responseHeaders; + this.responseBody = responseBody; + } + + public OutputStream getBody() throws IOException { + return new ByteArrayOutputStream(); + } + + public HttpHeaders getHeaders() { + return new HttpHeaders(); + } + + public URI getURI() { + try { + return new URI("http://foo.com/"); + } + catch (URISyntaxException e) { + throw new IllegalStateException(e); + } + } + + public HttpMethod getMethod() { + return HttpMethod.POST; + } + + public ClientHttpResponse execute() throws IOException { + return new ClientHttpResponse() { + + public HttpHeaders getHeaders() { + return responseHeaders; + } + + public InputStream getBody() throws IOException { + return new ByteArrayInputStream(responseBody.getBytes("UTF-8")); + } + + public String getStatusText() throws IOException { + return responseStatus.getReasonPhrase(); + } + + public HttpStatus getStatusCode() throws IOException { + return responseStatus; + } + + public void close() { + } + + public int getRawStatusCode() throws IOException { + return responseStatus.value(); + } + }; + } + } + + @Rule + public ExpectedException expected = ExpectedException.none(); + + private ClientHttpRequestFactory requestFactory; + + private AuthorizationCodeAccessTokenProvider provider = new AuthorizationCodeAccessTokenProvider(); + + private AuthorizationCodeResourceDetails resource = new AuthorizationCodeResourceDetails(); + + private void setUpRestTemplate() { + provider.setRequestFactory(requestFactory); + } + + @Test + public void testGetAccessTokenFromJson() throws Exception { + final OAuth2AccessToken token = new DefaultOAuth2AccessToken("FOO"); + requestFactory = new ClientHttpRequestFactory() { + public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException { + return new StubClientHttpRequest(new ObjectMapper().writeValueAsString(token)); + } + }; + AccessTokenRequest request = new DefaultAccessTokenRequest(); + request.setAuthorizationCode("foo"); + resource.setAccessTokenUri("http://localhost/oauth/token"); + setUpRestTemplate(); + assertEquals(token, provider.obtainAccessToken(resource, request)); + } + + @Test + public void testGetErrorFromJson() throws Exception { + final InvalidClientException exception = new InvalidClientException("FOO"); + requestFactory = new ClientHttpRequestFactory() { + public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException { + return new StubClientHttpRequest(HttpStatus.BAD_REQUEST, + new ObjectMapper().writeValueAsString(exception)); + } + }; + AccessTokenRequest request = new DefaultAccessTokenRequest(); + request.setAuthorizationCode("foo"); + resource.setAccessTokenUri("http://localhost/oauth/token"); + expected.expect(OAuth2AccessDeniedException.class); + expected.expect(hasCause(instanceOf(InvalidClientException.class))); + setUpRestTemplate(); + provider.obtainAccessToken(resource, request); + } + + @Test + public void testGetAccessTokenFromForm() throws Exception { + final OAuth2AccessToken token = new DefaultOAuth2AccessToken("FOO"); + final HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + requestFactory = new ClientHttpRequestFactory() { + public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException { + return new StubClientHttpRequest(responseHeaders, "access_token=FOO"); + } + }; + AccessTokenRequest request = new DefaultAccessTokenRequest(); + request.setAuthorizationCode("foo"); + resource.setAccessTokenUri("http://localhost/oauth/token"); + setUpRestTemplate(); + assertEquals(token, provider.obtainAccessToken(resource, request)); + } + + @Test + public void testGetErrorFromForm() throws Exception { + final HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + requestFactory = new ClientHttpRequestFactory() { + public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException { + return new StubClientHttpRequest(HttpStatus.BAD_REQUEST, responseHeaders, + "error=invalid_client&error_description=FOO"); + } + }; + AccessTokenRequest request = new DefaultAccessTokenRequest(); + request.setAuthorizationCode("foo"); + resource.setAccessTokenUri("http://localhost/oauth/token"); + expected.expect(OAuth2AccessDeniedException.class); + expected.expect(hasCause(instanceOf(InvalidClientException.class))); + setUpRestTemplate(); + provider.obtainAccessToken(resource, request); + } + + private Matcher hasCause(final Matcher matcher) { + return new TypeSafeMatcher() { + public void describeTo(Description description) { + description.appendText("exception matching "); + description.appendDescriptionOf(matcher); + } + + @Override + public boolean matchesSafely(Throwable item) { + return matcher.matches(item.getCause()); + } + }; + } + +} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeResourceDetailsTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeResourceDetailsTests.java new file mode 100644 index 000000000..6bde16be9 --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeResourceDetailsTests.java @@ -0,0 +1,47 @@ +/* + * Copyright 2006-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.client.token.grant.code; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.springframework.security.oauth2.client.token.DefaultAccessTokenRequest; + +/** + * @author Dave Syer + * + */ +public class AuthorizationCodeResourceDetailsTests { + + private AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails(); + + @Test + public void testGetDefaultRedirectUri() { + details.setPreEstablishedRedirectUri("http://anywhere.com/"); + DefaultAccessTokenRequest request = new DefaultAccessTokenRequest(); + request.setCurrentUri("http://nowhere.com/"); + assertEquals("http://nowhere.com/", details.getRedirectUri(request)); + } + + @Test + public void testGetOverrideRedirectUri() { + details.setPreEstablishedRedirectUri("http://anywhere.com/"); + details.setUseCurrentUri(false); + DefaultAccessTokenRequest request = new DefaultAccessTokenRequest(); + request.setCurrentUri("http://nowhere.com/"); + assertEquals("http://anywhere.com/", details.getRedirectUri(request)); + } + +} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeServicesBaseTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeServicesBaseTests.java new file mode 100644 index 000000000..c13dbf6d9 --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeServicesBaseTests.java @@ -0,0 +1,82 @@ +package org.springframework.security.oauth2.provider.code; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +import org.junit.Test; +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.RequestTokenFactory; +import org.springframework.security.oauth2.provider.OAuth2Request; + +public abstract class AuthorizationCodeServicesBaseTests { + + abstract AuthorizationCodeServices getAuthorizationCodeServices(); + + @Test + public void testCreateAuthorizationCode() { + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null, null); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication( + storedOAuth2Request, new TestAuthentication( + "test2", false)); + String code = getAuthorizationCodeServices().createAuthorizationCode(expectedAuthentication); + assertNotNull(code); + + OAuth2Authentication actualAuthentication = getAuthorizationCodeServices() + .consumeAuthorizationCode(code); + assertEquals(expectedAuthentication, actualAuthentication); + } + + @Test + public void testConsumeRemovesCode() { + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null, null); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication( + storedOAuth2Request, new TestAuthentication( + "test2", false)); + String code = getAuthorizationCodeServices().createAuthorizationCode(expectedAuthentication); + assertNotNull(code); + + OAuth2Authentication actualAuthentication = getAuthorizationCodeServices() + .consumeAuthorizationCode(code); + assertEquals(expectedAuthentication, actualAuthentication); + + try { + getAuthorizationCodeServices().consumeAuthorizationCode(code); + fail("Should have thrown exception"); + } catch (InvalidGrantException e) { + // good we expected this + } + } + + @Test + public void testConsumeNonExistingCode() { + try { + getAuthorizationCodeServices().consumeAuthorizationCode("doesnt exist"); + fail("Should have thrown exception"); + } catch (InvalidGrantException e) { + // good we expected this + } + } + + protected static class TestAuthentication extends AbstractAuthenticationToken { + + private static final long serialVersionUID = 1L; + private String principal; + public TestAuthentication(String name, boolean authenticated) { + super(null); + setAuthenticated(authenticated); + this.principal = name; + } + + public Object getCredentials() { + return null; + } + + public Object getPrincipal() { + return this.principal; + } + } + +} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranterTests.java new file mode 100644 index 000000000..0ff03e18e --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranterTests.java @@ -0,0 +1,207 @@ +/* + * Copyright 2006-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.code; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.junit.Test; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; +import org.springframework.security.oauth2.common.exceptions.RedirectMismatchException; +import org.springframework.security.oauth2.common.util.OAuth2Utils; +import org.springframework.security.oauth2.provider.BaseClientDetails; +import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.DefaultOAuth2RequestFactory; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; +import org.springframework.security.oauth2.provider.RequestTokenFactory; +import org.springframework.security.oauth2.provider.TokenRequest; +import org.springframework.security.oauth2.provider.token.DefaultTokenServices; +import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +/** + * @author Dave Syer + * + */ +public class AuthorizationCodeTokenGranterTests { + + private DefaultTokenServices providerTokenServices = new DefaultTokenServices(); + + private BaseClientDetails client = new BaseClientDetails("foo", "resource", "scope", "authorization_code", + "ROLE_CLIENT"); + + private ClientDetailsService clientDetailsService = new ClientDetailsService() { + public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exception { + return client; + } + }; + + private AuthorizationCodeServices authorizationCodeServices = new InMemoryAuthorizationCodeServices(); + + private OAuth2RequestFactory requestFactory = new DefaultOAuth2RequestFactory(clientDetailsService); + + private Map parameters = new HashMap(); + + public AuthorizationCodeTokenGranterTests() { + providerTokenServices.setTokenStore(new InMemoryTokenStore()); + } + + @Test + public void testAuthorizationCodeGrant() { + + Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala", + AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); + + parameters.clear(); + parameters.put(OAuth2Utils.CLIENT_ID, "foo"); + parameters.put(OAuth2Utils.SCOPE, "scope"); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(parameters, "foo", null, true, Collections.singleton("scope"), null, null, null, null); + + String code = authorizationCodeServices.createAuthorizationCode(new OAuth2Authentication( + storedOAuth2Request, userAuthentication)); + parameters.putAll(storedOAuth2Request.getRequestParameters()); + parameters.put("code", code); + + TokenRequest tokenRequest = requestFactory.createTokenRequest(parameters, client); + + AuthorizationCodeTokenGranter granter = new AuthorizationCodeTokenGranter(providerTokenServices, + authorizationCodeServices, clientDetailsService, requestFactory); + OAuth2AccessToken token = granter.grant("authorization_code", tokenRequest); + assertTrue(providerTokenServices.loadAuthentication(token.getValue()).isAuthenticated()); + } + + @Test + public void testAuthorizationParametersPreserved() { + + parameters.clear(); + parameters.put("foo", "bar"); + parameters.put(OAuth2Utils.CLIENT_ID, "foo"); + parameters.put(OAuth2Utils.SCOPE, "scope"); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(parameters, "foo", null, true, Collections.singleton("scope"), null, null, null, null); + + Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala", + AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); + String code = authorizationCodeServices.createAuthorizationCode(new OAuth2Authentication( + storedOAuth2Request, userAuthentication)); + + parameters.put("code", code); + TokenRequest tokenRequest = requestFactory.createTokenRequest(parameters, client); + + AuthorizationCodeTokenGranter granter = new AuthorizationCodeTokenGranter(providerTokenServices, + authorizationCodeServices, clientDetailsService, requestFactory); + OAuth2AccessToken token = granter.grant("authorization_code", tokenRequest); + OAuth2Request finalRequest = providerTokenServices.loadAuthentication(token.getValue()) + .getOAuth2Request(); + assertEquals(code, finalRequest.getRequestParameters().get("code")); + assertEquals("bar", finalRequest.getRequestParameters().get("foo")); + } + + @Test + public void testAuthorizationRequestPreserved() { + + parameters.clear(); + parameters.put(OAuth2Utils.CLIENT_ID, "foo"); + parameters.put(OAuth2Utils.SCOPE, "read"); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(parameters, "foo", null, true, Collections.singleton("read"), Collections.singleton("resource"), null, null, null); + + Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala", + AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); + String code = authorizationCodeServices.createAuthorizationCode(new OAuth2Authentication( + storedOAuth2Request, userAuthentication)); + + parameters.put("code", code); + // Ensure even if token request asks for more scope they are not granted + parameters.put(OAuth2Utils.SCOPE, "read write"); + TokenRequest tokenRequest = requestFactory.createTokenRequest(parameters, client); + + AuthorizationCodeTokenGranter granter = new AuthorizationCodeTokenGranter(providerTokenServices, + authorizationCodeServices, clientDetailsService, requestFactory); + OAuth2AccessToken token = granter.grant("authorization_code", tokenRequest); + OAuth2Request finalRequest = providerTokenServices.loadAuthentication(token.getValue()) + .getOAuth2Request(); + assertEquals("[read]", finalRequest.getScope().toString()); + assertEquals("[resource]", finalRequest.getResourceIds().toString()); + assertTrue(finalRequest.isApproved()); + } + + @Test + public void testAuthorizationCodeGrantWithNoClientAuthorities() { + + parameters.clear(); + parameters.put(OAuth2Utils.CLIENT_ID, "foo"); + parameters.put(OAuth2Utils.SCOPE, "scope"); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(parameters, "foo", Collections. emptySet(), true, Collections.singleton("scope"), null, null, null, null); + + Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala", + AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); + String code = authorizationCodeServices.createAuthorizationCode(new OAuth2Authentication( + storedOAuth2Request, userAuthentication)); + parameters.put("code", code); + TokenRequest tokenRequest = requestFactory.createTokenRequest(parameters, client); + AuthorizationCodeTokenGranter granter = new AuthorizationCodeTokenGranter(providerTokenServices, + authorizationCodeServices, clientDetailsService, requestFactory); + OAuth2AccessToken token = granter.grant("authorization_code", tokenRequest); + assertTrue(providerTokenServices.loadAuthentication(token.getValue()).isAuthenticated()); + } + + @Test + public void testAuthorizationRedirectMismatch() { + Map initialParameters = new HashMap(); + initialParameters.put(OAuth2Utils.REDIRECT_URI, "https://redirectme/"); + //AuthorizationRequest initialRequest = createFromParameters(initialParameters); + // we fake a valid resolvedRedirectUri because without the client would never come this far + //initialRequest.setRedirectUri(initialParameters.get(REDIRECT_URI)); + + parameters.clear(); + parameters.put(OAuth2Utils.REDIRECT_URI, "https://redirectme/"); + parameters.put(OAuth2Utils.CLIENT_ID, "foo"); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(parameters, "foo", null, true, null, null, "https://redirectme/", null, null); + + Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala", + AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); + String code = authorizationCodeServices.createAuthorizationCode(new OAuth2Authentication(storedOAuth2Request, + userAuthentication)); + + Map authorizationParameters = new HashMap(); + authorizationParameters.put("code", code); + + //AuthorizationRequest oAuth2Request = createFromParameters(initialParameters); + //oAuth2Request.setRequestParameters(authorizationParameters); + + TokenRequest tokenRequest = requestFactory.createTokenRequest(parameters, client); + tokenRequest.setRequestParameters(authorizationParameters); + + AuthorizationCodeTokenGranter granter = new AuthorizationCodeTokenGranter(providerTokenServices, + authorizationCodeServices, clientDetailsService, requestFactory); + try { + granter.getOAuth2Authentication(client, tokenRequest); + fail("RedirectMismatchException because of null redirect_uri in authorizationRequest"); + } + catch (RedirectMismatchException e) { + } + } + +} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/InMemoryAuthorizationCodeServicesTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/InMemoryAuthorizationCodeServicesTests.java new file mode 100644 index 000000000..6116332f1 --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/InMemoryAuthorizationCodeServicesTests.java @@ -0,0 +1,18 @@ +package org.springframework.security.oauth2.provider.code; + +import org.junit.Before; + +public class InMemoryAuthorizationCodeServicesTests extends AuthorizationCodeServicesBaseTests { + + private InMemoryAuthorizationCodeServices authorizationCodeServices; + + @Before + public void setUp() throws Exception { + authorizationCodeServices = new InMemoryAuthorizationCodeServices(); + } + + @Override + AuthorizationCodeServices getAuthorizationCodeServices() { + return authorizationCodeServices; + } +} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/JdbcAuthorizationCodeServicesTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/JdbcAuthorizationCodeServicesTests.java new file mode 100644 index 000000000..b58b58d96 --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/JdbcAuthorizationCodeServicesTests.java @@ -0,0 +1,29 @@ +package org.springframework.security.oauth2.provider.code; + +import org.junit.After; +import org.junit.Before; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; + +public class JdbcAuthorizationCodeServicesTests extends AuthorizationCodeServicesBaseTests { + private JdbcAuthorizationCodeServices authorizationCodeServices; + + private EmbeddedDatabase db; + + @Before + public void setUp() throws Exception { + // creates a HSQL in-memory db populated from default scripts classpath:schema.sql and classpath:data.sql + db = new EmbeddedDatabaseBuilder().addDefaultScripts().build(); + authorizationCodeServices = new JdbcAuthorizationCodeServices(db); + } + + @After + public void tearDown() throws Exception { + db.shutdown(); + } + + @Override + AuthorizationCodeServices getAuthorizationCodeServices() { + return authorizationCodeServices; + } +} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/SubdomainRedirectResolverTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/SubdomainRedirectResolverTests.java new file mode 100644 index 000000000..73dff82ad --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/SubdomainRedirectResolverTests.java @@ -0,0 +1,43 @@ +package org.springframework.security.oauth2.provider.code; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.junit.Test; +import org.springframework.security.oauth2.common.exceptions.RedirectMismatchException; +import org.springframework.security.oauth2.provider.BaseClientDetails; +import org.springframework.security.oauth2.provider.endpoint.DefaultRedirectResolver; + +public class SubdomainRedirectResolverTests +{ + private final DefaultRedirectResolver resolver = new DefaultRedirectResolver(); + private final BaseClientDetails client = new BaseClientDetails(); + + { + client.setAuthorizedGrantTypes(Collections.singleton("authorization_code")); + } + + + @Test + public void testRedirectWatchdox() throws Exception + { + Set redirectUris = new HashSet(Arrays.asList("http://watchdox.com/")); + client.setRegisteredRedirectUri(redirectUris); + String requestedRedirect = "http://anywhere.watchdox.com/something"; + assertEquals(requestedRedirect, resolver.resolveRedirect(requestedRedirect, client)); + } + + @Test(expected=RedirectMismatchException.class) + public void testRedirectBadWatchdox() throws Exception + { + Set redirectUris = new HashSet(Arrays.asList("http//watchdox.com")); + client.setRegisteredRedirectUri(redirectUris); + String requestedRedirect = "http://anywhere.google.com/something"; + assertEquals(requestedRedirect, resolver.resolveRedirect(requestedRedirect, client)); + } + +} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolverTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolverTests.java new file mode 100644 index 000000000..52991966b --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolverTests.java @@ -0,0 +1,111 @@ +/* + * Copyright 2006-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.endpoint; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.junit.Test; +import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; +import org.springframework.security.oauth2.common.exceptions.RedirectMismatchException; +import org.springframework.security.oauth2.provider.BaseClientDetails; +import org.springframework.security.oauth2.provider.endpoint.DefaultRedirectResolver; + +/** + * @author Dave Syer + */ +public class DefaultRedirectResolverTests { + + private DefaultRedirectResolver resolver = new DefaultRedirectResolver(); + + private BaseClientDetails client = new BaseClientDetails(); + + { + client.setAuthorizedGrantTypes(Collections.singleton("authorization_code")); + } + + @Test + public void testRedirectMatchesRegisteredValue() throws Exception { + Set redirectUris = new HashSet(Arrays.asList("http://anywhere.com/")); + client.setRegisteredRedirectUri(redirectUris); + String requestedRedirect = "http://anywhere.com/myendpoint"; + assertEquals(requestedRedirect, resolver.resolveRedirect(requestedRedirect, client)); + } + + @Test + public void testRedirectWithNoRegisteredValue() throws Exception { + String requestedRedirect = "http://anywhere.com/myendpoint"; + assertEquals(requestedRedirect, resolver.resolveRedirect(requestedRedirect, client)); + } + + // If only one redirect has been registered, then we should use it + @Test + public void testRedirectWithNoRequestedValue() throws Exception { + Set redirectUris = new HashSet(Arrays.asList("http://anywhere.com/")); + client.setRegisteredRedirectUri(redirectUris); + resolver.resolveRedirect(null, client); + } + + // If multiple redirects registered, then we should get an exception + @Test(expected = RedirectMismatchException.class) + public void testRedirectWithNoRequestedValueAndMultipleRegistered() throws Exception { + Set redirectUris = new HashSet(Arrays.asList("http://anywhere.com/", "http://nowhere.com/")); + client.setRegisteredRedirectUri(redirectUris); + resolver.resolveRedirect(null, client); + } + + @Test(expected = InvalidGrantException.class) + public void testNoGrantType() throws Exception { + Set redirectUris = new HashSet(Arrays.asList("http://anywhere.com/", "http://nowhere.com/")); + client.setRegisteredRedirectUri(redirectUris); + client.setAuthorizedGrantTypes(Collections.emptyList()); + resolver.resolveRedirect(null, client); + } + + @Test(expected = InvalidGrantException.class) + public void testWrongGrantType() throws Exception { + Set redirectUris = new HashSet(Arrays.asList("http://anywhere.com/", "http://nowhere.com/")); + client.setRegisteredRedirectUri(redirectUris); + client.setAuthorizedGrantTypes(Collections.singleton("client_credentials")); + resolver.resolveRedirect(null, client); + } + + @Test(expected = InvalidGrantException.class) + public void testWrongCustomGrantType() throws Exception { + resolver.setRedirectGrantTypes(Collections.singleton("foo")); + Set redirectUris = new HashSet(Arrays.asList("http://anywhere.com/", "http://nowhere.com/")); + client.setRegisteredRedirectUri(redirectUris); + resolver.resolveRedirect(null, client); + } + + @Test(expected = RedirectMismatchException.class) + public void testRedirectNotMatching() throws Exception { + Set redirectUris = new HashSet(Arrays.asList("http://nowhere.com/")); + String requestedRedirect = "http://anywhere.com/myendpoint"; + client.setRegisteredRedirectUri(redirectUris); + assertEquals(redirectUris.iterator().next(), resolver.resolveRedirect(requestedRedirect, client)); + } + + @Test(expected = RedirectMismatchException.class) + public void testRedirectNotMatchingWithTraversal() throws Exception { + Set redirectUris = new HashSet(Arrays.asList("http://anywhere.com/foo")); + String requestedRedirect = "http://anywhere.com/bar"; + client.setRegisteredRedirectUri(redirectUris); + assertEquals(redirectUris.iterator().next(), resolver.resolveRedirect(requestedRedirect, client)); + } + +} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/ExactMatchRedirectResolverTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/ExactMatchRedirectResolverTests.java new file mode 100644 index 000000000..e9fb327df --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/ExactMatchRedirectResolverTests.java @@ -0,0 +1,63 @@ +/* + * Copyright 2006-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.endpoint; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.junit.Test; +import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; +import org.springframework.security.oauth2.common.exceptions.RedirectMismatchException; +import org.springframework.security.oauth2.provider.BaseClientDetails; +import org.springframework.security.oauth2.provider.endpoint.ExactMatchRedirectResolver; + +/** + * @author Dave Syer + */ +public class ExactMatchRedirectResolverTests { + + private ExactMatchRedirectResolver resolver = new ExactMatchRedirectResolver(); + private BaseClientDetails client = new BaseClientDetails(); + + { + client.setAuthorizedGrantTypes(Collections.singleton("authorization_code")); + } + + @Test ( expected = RedirectMismatchException.class ) + public void testRedirectNotMatching() throws Exception { + Set redirectUris = new HashSet(Arrays.asList("http://anywhere.com/")); + String requestedRedirect = "http://anywhere.com/myendpoint"; + client.setRegisteredRedirectUri(redirectUris); + assertEquals(redirectUris.iterator().next(), resolver.resolveRedirect(requestedRedirect, client)); + } + + @Test + public void testRedirectWithNoRegisteredValue() throws Exception { + String requestedRedirect = "http://anywhere.com/myendpoint"; + assertEquals(requestedRedirect, resolver.resolveRedirect(requestedRedirect, client)); + } + + // As we have one or more registered redirects, the redirect SHOULD be present. + // If not we should expect a Oauth2Exception. + @Test ( expected = OAuth2Exception.class ) + public void testRedirectWithNoRequestedValue() throws Exception { + Set redirectUris = new HashSet(Arrays.asList("http://anywhere.com/", "http://nowhere.com/")); + client.setRegisteredRedirectUri(redirectUris); + resolver.resolveRedirect(null, client); + } + +} From e8b45d7ec1604dcc479ccd6399f49a05a1521ee8 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 14 Feb 2014 19:11:10 +0000 Subject: [PATCH 161/831] Add @EnableAuthorizationServer --- .../sparklr/config/OAuth2ServerConfig.java | 25 +++---- .../ClientDetailsServiceBuilder.java} | 44 ++++++------ .../InMemoryClientDetailsServiceBuilder.java | 46 +++++++++++++ .../ClientDetailsServiceConfigurer.java | 63 +++++++++++++++++ ... => AuthorizationServerConfiguration.java} | 37 ++++++++-- .../AuthorizationServerConfigurer.java | 29 ++++++++ .../AuthorizationServerConfigurerAdapter.java | 33 +++++++++ .../AuthorizationServerImportSelector.java | 30 ++++++++ .../EnableAuthorizationServer.java | 34 ++++++++++ ...AuthorizationServerConfigurationTests.java | 68 ++++++++++++++++--- 10 files changed, 353 insertions(+), 56 deletions(-) rename spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/{authentication/configurers/InMemoryClientDetailsServiceConfigurer.java => builders/ClientDetailsServiceBuilder.java} (74%) create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/InMemoryClientDetailsServiceBuilder.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/configurers/ClientDetailsServiceConfigurer.java rename spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/{OAuth2AuthorizationServerConfigurerAdapter.java => AuthorizationServerConfiguration.java} (81%) create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurer.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurerAdapter.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerImportSelector.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableAuthorizationServer.java diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java index f44bd5316..9006aca87 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java @@ -20,13 +20,9 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Lazy; -import org.springframework.context.annotation.Scope; -import org.springframework.context.annotation.ScopedProxyMode; import org.springframework.core.annotation.Order; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity.IgnoredRequestConfigurer; @@ -34,8 +30,9 @@ import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.oauth.examples.sparklr.mvc.AdminController; import org.springframework.security.oauth.examples.sparklr.oauth.SparklrUserApprovalHandler; -import org.springframework.security.oauth2.config.annotation.authentication.configurers.InMemoryClientDetailsServiceConfigurer; -import org.springframework.security.oauth2.config.annotation.web.configuration.OAuth2AuthorizationServerConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; +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.configurers.OAuth2AuthorizationServerConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.OAuth2ResourceServerConfigurer; import org.springframework.security.oauth2.provider.ClientDetailsService; @@ -111,8 +108,8 @@ protected void configure(HttpSecurity http) throws Exception { } @Configuration - @Order(1) - protected static class AuthorizationServerConfiguration extends OAuth2AuthorizationServerConfigurerAdapter { + @EnableAuthorizationServer + protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter { private TokenStore tokenStore = new InMemoryTokenStore(); @@ -130,10 +127,10 @@ protected static class AuthorizationServerConfiguration extends OAuth2Authorizat private String tonrRedirectUri; @Override - protected void configure(AuthenticationManagerBuilder auth) throws Exception { + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { // @formatter:off - auth.apply(new InMemoryClientDetailsServiceConfigurer()) + clients.inMemory() .withClient("tonr") .resourceIds(SPARKLR_RESOURCE_ID) .authorizedGrantTypes("authorization_code", "implicit") @@ -181,11 +178,7 @@ protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:on } - @Bean - @Override - @Lazy - @Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) - public SparklrUserApprovalHandler userApprovalHandler() throws Exception { + private SparklrUserApprovalHandler userApprovalHandler() throws Exception { SparklrUserApprovalHandler handler = new SparklrUserApprovalHandler(); handler.setApprovalStore(approvalStore()); handler.setRequestFactory(requestFactory); @@ -202,7 +195,7 @@ public ApprovalStore approvalStore() throws Exception { } @Override - protected void configure(OAuth2AuthorizationServerConfigurer oauthServer) throws Exception { + public void configure(OAuth2AuthorizationServerConfigurer oauthServer) throws Exception { oauthServer.tokenStore(tokenStore).userApprovalHandler(userApprovalHandler()) .authenticationManager(authenticationManager).realm("sparklr2/client"); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/authentication/configurers/InMemoryClientDetailsServiceConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java similarity index 74% rename from spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/authentication/configurers/InMemoryClientDetailsServiceConfigurer.java rename to spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java index 424f53c5e..036f95091 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/authentication/configurers/InMemoryClientDetailsServiceConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java @@ -13,35 +13,35 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.security.oauth2.config.annotation.authentication.configurers; +package org.springframework.security.oauth2.config.annotation.builders; import java.util.ArrayList; import java.util.Collection; -import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; -import java.util.Map; import java.util.Set; -import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.SecurityBuilder; import org.springframework.security.config.annotation.SecurityConfigurerAdapter; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; -import org.springframework.security.oauth2.provider.InMemoryClientDetailsService; -import org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService; /** - * @author Rob Winch + * @author Dave Syer * */ -public class InMemoryClientDetailsServiceConfigurer extends - SecurityConfigurerAdapter { +public class ClientDetailsServiceBuilder> extends + SecurityConfigurerAdapter implements SecurityBuilder { + private List clientBuilders = new ArrayList(); + public InMemoryClientDetailsServiceBuilder inMemory() throws Exception { + return new InMemoryClientDetailsServiceBuilder(); + } + public ClientBuilder withClient(String clientId) { ClientBuilder clientBuilder = new ClientBuilder(clientId); this.clientBuilders.add(clientBuilder); @@ -49,23 +49,18 @@ public ClientBuilder withClient(String clientId) { } @Override - public void init(AuthenticationManagerBuilder builder) throws Exception { - Map clientDetails = new HashMap(clientBuilders.size()); + public ClientDetailsService build() throws Exception { for (ClientBuilder clientDetailsBldr : clientBuilders) { - clientDetails.put(clientDetailsBldr.clientId, clientDetailsBldr.build()); + addClient(clientDetailsBldr.clientId, clientDetailsBldr.build()); } - InMemoryClientDetailsService clientDetailsService = new InMemoryClientDetailsService(); - clientDetailsService.setClientDetailsStore(clientDetails); - - ClientDetailsUserDetailsService userDetailsService = new ClientDetailsUserDetailsService(clientDetailsService); - builder.userDetailsService(userDetailsService); - - builder.setSharedObject(ClientDetailsService.class, clientDetailsService); + return performBuild(); } - @Override - public void configure(AuthenticationManagerBuilder builder) throws Exception { + protected void addClient(String clientId, ClientDetails build) { + } + protected ClientDetailsService performBuild() { + throw new UnsupportedOperationException("Cannot build client services (maybe use inMemory() or jdbc())."); } public final class ClientBuilder { @@ -170,8 +165,8 @@ public ClientBuilder autoApprove(String... scopes) { return this; } - public InMemoryClientDetailsServiceConfigurer and() { - return InMemoryClientDetailsServiceConfigurer.this; + public ClientDetailsServiceBuilder and() { + return ClientDetailsServiceBuilder.this; } private ClientBuilder(String clientId) { @@ -179,4 +174,5 @@ private ClientBuilder(String clientId) { } } + } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/InMemoryClientDetailsServiceBuilder.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/InMemoryClientDetailsServiceBuilder.java new file mode 100644 index 000000000..ffb58e7b7 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/InMemoryClientDetailsServiceBuilder.java @@ -0,0 +1,46 @@ +/* + * Copyright 2002-2013 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.builders; + +import java.util.HashMap; +import java.util.Map; + +import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.InMemoryClientDetailsService; + +/** + * @author Dave Syer + * + */ +public class InMemoryClientDetailsServiceBuilder extends + ClientDetailsServiceBuilder { + + private Map clientDetails = new HashMap(); + + @Override + protected void addClient(String clientId, ClientDetails value) { + clientDetails.put(clientId, value); + } + + @Override + protected ClientDetailsService performBuild() { + InMemoryClientDetailsService clientDetailsService = new InMemoryClientDetailsService(); + clientDetailsService.setClientDetailsStore(clientDetails); + return clientDetailsService; + } + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/configurers/ClientDetailsServiceConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/configurers/ClientDetailsServiceConfigurer.java new file mode 100644 index 000000000..9db06f582 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/configurers/ClientDetailsServiceConfigurer.java @@ -0,0 +1,63 @@ +/* + * Copyright 2002-2013 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.configurers; + +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.SecurityConfigurerAdapter; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.oauth2.config.annotation.builders.ClientDetailsServiceBuilder; +import org.springframework.security.oauth2.config.annotation.builders.InMemoryClientDetailsServiceBuilder; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService; + +/** + * @author Rob Winch + * + */ +public class ClientDetailsServiceConfigurer extends + SecurityConfigurerAdapter { + + private ClientDetailsService clientDetailsService; + + @SuppressWarnings("rawtypes") + private ClientDetailsServiceBuilder builder = new ClientDetailsServiceBuilder(); + + public AuthenticationManagerBuilder withClientDetails(ClientDetailsService clientDetailsService) { + + this.clientDetailsService = clientDetailsService; + return this.and(); + } + + public InMemoryClientDetailsServiceBuilder inMemory() throws Exception { + InMemoryClientDetailsServiceBuilder next = builder.inMemory(); + this.builder = next; + return next; + } + + @Override + public void init(AuthenticationManagerBuilder builder) throws Exception { + ClientDetailsService clientDetailsService = this.clientDetailsService != null ? this.clientDetailsService + : this.builder.build(); + ClientDetailsUserDetailsService userDetailsService = new ClientDetailsUserDetailsService(clientDetailsService); + builder.userDetailsService(userDetailsService); + builder.setSharedObject(ClientDetailsService.class, clientDetailsService); + } + + @Override + public void configure(AuthenticationManagerBuilder builder) throws Exception { + + } +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/OAuth2AuthorizationServerConfigurerAdapter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java similarity index 81% rename from spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/OAuth2AuthorizationServerConfigurerAdapter.java rename to spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java index 64467785e..5db28a4aa 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/OAuth2AuthorizationServerConfigurerAdapter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java @@ -15,13 +15,19 @@ */ package org.springframework.security.oauth2.config.annotation.web.configuration; +import java.util.Collections; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.ScopedProxyMode; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; @@ -43,11 +49,31 @@ * */ @Configuration -public abstract class OAuth2AuthorizationServerConfigurerAdapter extends WebSecurityConfigurerAdapter { +public class AuthorizationServerConfiguration extends WebSecurityConfigurerAdapter { + + private List configurers = Collections.emptyList(); + + /** + * @param configurers the configurers to set + */ + @Autowired(required = false) + public void setConfigurers(List configurers) { + this.configurers = configurers; + } + + @Autowired + public void configure(AuthenticationManagerBuilder builder) throws Exception { + ClientDetailsServiceConfigurer clients = builder.apply(new ClientDetailsServiceConfigurer()); + for (AuthorizationServerConfigurer configurer : configurers) { + configurer.configure(clients); + } + } @Override protected void configure(HttpSecurity http) throws Exception { - configure(// @formatter:off + OAuth2AuthorizationServerConfigurer configurer = new OAuth2AuthorizationServerConfigurer(); + configure(configurer); + // @formatter:off http .authorizeRequests() .antMatchers("/oauth/token").fullyAuthenticated() @@ -55,13 +81,14 @@ protected void configure(HttpSecurity http) throws Exception { .requestMatchers() .antMatchers("/oauth/token") .and() - .apply(new OAuth2AuthorizationServerConfigurer()) + .apply(configurer); // @formatter:on - ); } protected void configure(OAuth2AuthorizationServerConfigurer oauthServer) throws Exception { - // Default is no-op + for (AuthorizationServerConfigurer configurer : configurers) { + configurer.configure(oauthServer); + } } @Bean diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurer.java new file mode 100644 index 000000000..c085daf96 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurer.java @@ -0,0 +1,29 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.springframework.security.oauth2.config.annotation.web.configuration; + +import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer; + +/** + * @author Dave Syer + * + */ +public interface AuthorizationServerConfigurer { + + void configure(OAuth2AuthorizationServerConfigurer oauthServer) throws Exception; + + void configure(ClientDetailsServiceConfigurer clients) throws Exception; + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurerAdapter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurerAdapter.java new file mode 100644 index 000000000..f08de3ecb --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurerAdapter.java @@ -0,0 +1,33 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.springframework.security.oauth2.config.annotation.web.configuration; + +import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer; + +/** + * @author Dave Syer + * + */ +public class AuthorizationServerConfigurerAdapter implements AuthorizationServerConfigurer { + + @Override + public void configure(OAuth2AuthorizationServerConfigurer oauthServer) throws Exception { + } + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + } + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerImportSelector.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerImportSelector.java new file mode 100644 index 000000000..7f0ad8fd1 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerImportSelector.java @@ -0,0 +1,30 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.springframework.security.oauth2.config.annotation.web.configuration; + +import org.springframework.context.annotation.ImportSelector; +import org.springframework.core.type.AnnotationMetadata; + +/** + * @author Dave Syer + * + */ +public class AuthorizationServerImportSelector implements ImportSelector { + + @Override + public String[] selectImports(AnnotationMetadata importingClassMetadata) { + return new String[] {AuthorizationServerConfiguration.class.getName()}; + } + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableAuthorizationServer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableAuthorizationServer.java new file mode 100644 index 000000000..a1cc685bb --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableAuthorizationServer.java @@ -0,0 +1,34 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.springframework.security.oauth2.config.annotation.web.configuration; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.context.annotation.Import; + +/** + * @author Dave Syer + * + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Import(AuthorizationServerImportSelector.class) +public @interface EnableAuthorizationServer { + +} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java index 661077db9..49c3e2f1d 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java @@ -12,6 +12,7 @@ */ package org.springframework.security.oauth2.config.annotation; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.util.Arrays; @@ -24,11 +25,19 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; +import org.springframework.beans.factory.BeanCreationException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Configuration; import org.springframework.mock.web.MockServletContext; import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity; -import org.springframework.security.oauth2.config.annotation.web.configuration.OAuth2AuthorizationServerConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfiguration; +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.configurers.OAuth2AuthorizationServerConfigurer; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint; import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; @@ -45,17 +54,25 @@ public class AuthorizationServerConfigurationTests { @Rule public ExpectedException expected = ExpectedException.none(); + private Class[] resources; + @Parameters public static List parameters() { - return Arrays.asList(new Object[] { AuthorizationServerVanilla.class }, - new Object[] { AuthorizationServerExtras.class }, new Object[] { AuthorizationServerTypes.class }); + return Arrays.asList(new Object[] { BeanCreationException.class, + new Class[] { AuthorizationServerVanilla.class } }, new Object[] { null, + new Class[] { AuthorizationServerExtras.class, AuthorizationServerVanilla.class } }, new Object[] { + null, new Class[] { AuthorizationServerExtras.class } }, new Object[] { BeanCreationException.class, + new Class[] { AuthorizationServerTypes.class } }); } - public AuthorizationServerConfigurationTests(Class resource) { + public AuthorizationServerConfigurationTests(Class error, Class... resource) { + if (error != null) { + expected.expect(error); + } + this.resources = resource; context = new AnnotationConfigWebApplicationContext(); context.setServletContext(new MockServletContext()); context.register(resource); - context.refresh(); } @After @@ -67,31 +84,60 @@ public void close() { @Test public void testDefaults() { + context.refresh(); assertTrue(context.containsBeanDefinition("authorizationEndpoint")); + assertNotNull(context.getBean("authorizationEndpoint", AuthorizationEndpoint.class)); + for (Class resource : resources) { + if (Runnable.class.isAssignableFrom(resource)) { + ((Runnable) context.getBean(resource)).run(); + } + } } @Configuration @EnableWebMvcSecurity - protected static class AuthorizationServerVanilla extends OAuth2AuthorizationServerConfigurerAdapter { + @EnableAuthorizationServer + protected static class AuthorizationServerVanilla { } @Configuration @EnableWebMvcSecurity - protected static class AuthorizationServerExtras extends OAuth2AuthorizationServerConfigurerAdapter { + @EnableAuthorizationServer + protected static class AuthorizationServerExtras extends AuthorizationServerConfigurerAdapter implements Runnable { private TokenStore tokenStore = new InMemoryTokenStore(); + @Autowired + private ApplicationContext context; + @Override - protected void configure(OAuth2AuthorizationServerConfigurer oauthServer) throws Exception { - oauthServer.tokenStore(tokenStore).authenticationManager(super.authenticationManagerBean()) - .realm("sparklr2/client"); + public void configure(OAuth2AuthorizationServerConfigurer oauthServer) throws Exception { + oauthServer.tokenStore(tokenStore).realm("sparklr2/client"); + } + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + // @formatter:off + clients.inMemory() + .withClient("my-trusted-client") + .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit") + .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") + .scopes("read", "write", "trust") + .accessTokenValiditySeconds(60); + // @formatter:on + } + + @Override + public void run() { + assertNotNull(context.getBean("clientDetailsService", ClientDetailsService.class).loadClientByClientId( + "my-trusted-client")); } } @Configuration @EnableWebMvcSecurity - protected static class AuthorizationServerTypes extends OAuth2AuthorizationServerConfigurerAdapter { + protected static class AuthorizationServerTypes extends AuthorizationServerConfiguration { // TODO: actually configure a token granter @Override From 792988d2869b75bc273a938c94c572e36639fba1 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 27 Feb 2014 15:43:16 +0000 Subject: [PATCH 162/831] Add @EnableResourceServer --- pom.xml | 4 +- .../sparklr/config/OAuth2ServerConfig.java | 110 +++++---- .../sparklr/config/SecurityConfiguration.java | 2 +- .../examples/sparklr/config/WebMvcConfig.java | 16 +- .../src/main/resources/simplelog.properties | 2 +- .../client/test/OAuth2ContextSetup.java | 1 + .../builders/ClientDetailsServiceBuilder.java | 10 + .../ClientDetailsServiceConfiguration.java | 49 ++++ .../ClientDetailsServiceConfigurer.java | 34 +-- .../AuthorizationServerConfiguration.java | 41 ++-- .../configuration/EnableResourceServer.java | 34 +++ .../ResourceServerConfiguration.java | 67 ++++++ .../ResourceServerConfigurer.java | 30 +++ .../ResourceServerConfigurerAdapter.java | 32 +++ .../ResourceServerImportSelector.java | 30 +++ .../OAuth2AuthorizationServerConfigurer.java | 39 +++- .../OAuth2ResourceServerConfigurer.java | 209 +++++++++--------- .../OAuth2AuthenticationManager.java | 3 +- ...AuthorizationServerConfigurationTests.java | 11 +- 19 files changed, 501 insertions(+), 223 deletions(-) create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/configuration/ClientDetailsServiceConfiguration.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableResourceServer.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurer.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurerAdapter.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerImportSelector.java diff --git a/pom.xml b/pom.xml index 0ca951062..982cff903 100644 --- a/pom.xml +++ b/pom.xml @@ -17,9 +17,9 @@ UTF-8 3.2.7.RELEASE - 3.2.0.RELEASE + 3.2.1.RELEASE [3.2.0,5.0.0) - [3.2.0,5.0.0) + [3.2.1,5.0.0) 1.6 diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java index 9006aca87..30fb456dd 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java @@ -24,87 +24,81 @@ import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.builders.WebSecurity; -import org.springframework.security.config.annotation.web.builders.WebSecurity.IgnoredRequestConfigurer; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.config.http.SessionCreationPolicy; -import org.springframework.security.oauth.examples.sparklr.mvc.AdminController; import org.springframework.security.oauth.examples.sparklr.oauth.SparklrUserApprovalHandler; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; 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.config.annotation.web.configuration.ResourceServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.OAuth2ResourceServerConfigurer; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; import org.springframework.security.oauth2.provider.approval.ApprovalStore; import org.springframework.security.oauth2.provider.approval.TokenApprovalStore; -import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler; -import org.springframework.security.oauth2.provider.token.ConsumerTokenServices; import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; import org.springframework.security.oauth2.provider.token.TokenStore; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; /** * @author Rob Winch * */ @Configuration -@Order(3) -public class OAuth2ServerConfig extends WebSecurityConfigurerAdapter { +public class OAuth2ServerConfig { private static final String SPARKLR_RESOURCE_ID = "sparklr"; - @Autowired - private TokenStore tokenStore; - - @Override - public void configure(WebSecurity builder) throws Exception { - IgnoredRequestConfigurer ignoring = builder.ignoring(); - ignoring.antMatchers("/oauth/uncache_approvals", "/oauth/cache_approvals"); + @Configuration + @Order(10) + protected static class UiResourceConfiguration extends WebSecurityConfigurerAdapter { + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http + .authorizeRequests() + .expressionHandler(new OAuth2WebSecurityExpressionHandler()) + .antMatchers("/photos").access("hasRole('ROLE_USER')") + .antMatchers("/photos/trusted/**").access("hasRole('ROLE_USER')") + .antMatchers("/photos/user/**").access("hasRole('ROLE_USER')") + .antMatchers("/photos/**").access("hasRole('ROLE_USER')") + .and() + .requestMatchers().antMatchers("/photos/**"); + // @formatter:on + } } - @Bean - public AdminController adminController(TokenStore tokenStore, ConsumerTokenServices tokenServices, - SparklrUserApprovalHandler userApprovalHandler) { - AdminController adminController = new AdminController(); - adminController.setTokenStore(tokenStore); - adminController.setTokenServices(tokenServices); - adminController.setUserApprovalHandler(userApprovalHandler); - return adminController; - } + @Configuration + @EnableResourceServer + protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { + + @Override + public void configure(OAuth2ResourceServerConfigurer resources) { + resources.resourceId(SPARKLR_RESOURCE_ID); + } + + @Override + public void configure(HttpSecurity http) throws Exception { + // @formatter:off + http + .authorizeRequests() + .expressionHandler(new OAuth2WebSecurityExpressionHandler()) + .antMatchers("/photos").access("#oauth2.hasScope('read')") + .antMatchers("/photos/trusted/**").access("#oauth2.hasScope('trust')") + .antMatchers("/photos/user/**").access("#oauth2.hasScope('trust')") + .antMatchers("/photos/**").access("#oauth2.hasScope('read')") + .regexMatchers(HttpMethod.DELETE, "/oauth/users/([^/].*?)/tokens/.*") + .access("#oauth2.clientHasRole('ROLE_CLIENT') and (hasRole('ROLE_USER') or #oauth2.isClient()) and #oauth2.hasScope('write')") + .regexMatchers(HttpMethod.GET, "/oauth/users/.*") + .access("#oauth2.clientHasRole('ROLE_CLIENT') and (hasRole('ROLE_USER') or #oauth2.isClient()) and #oauth2.hasScope('read')") + .regexMatchers(HttpMethod.GET, "/oauth/clients/.*") + .access("#oauth2.clientHasRole('ROLE_CLIENT') and #oauth2.isClient() and #oauth2.hasScope('read')") + .and() + .requestMatchers().antMatchers("/photos/**", "/oauth/users/**", "/oauth/clients/**"); + // @formatter:on + } - @Override - protected void configure(HttpSecurity http) throws Exception { - // @formatter:off - http - .authorizeRequests() - .expressionHandler(new OAuth2WebSecurityExpressionHandler()) - .antMatchers("/photos").access("#oauth2.denyOAuthClient() and hasRole('ROLE_USER') or #oauth2.hasScope('read')") - .antMatchers("/photos/trusted/**").access("#oauth2.denyOAuthClient() and hasRole('ROLE_USER') or #oauth2.hasScope('trust')") - .antMatchers("/photos/user/**").access("#oauth2.denyOAuthClient() and hasRole('ROLE_USER') or #oauth2.hasScope('trust')") - .antMatchers("/photos/**").access("#oauth2.denyOAuthClient() and hasRole('ROLE_USER') or #oauth2.hasScope('read')") - .regexMatchers(HttpMethod.DELETE, "/oauth/users/([^/].*?)/tokens/.*") - .access("#oauth2.clientHasRole('ROLE_CLIENT') and (hasRole('ROLE_USER') or #oauth2.isClient()) and #oauth2.hasScope('write')") - .regexMatchers(HttpMethod.GET, "/oauth/users/.*") - .access("#oauth2.clientHasRole('ROLE_CLIENT') and (hasRole('ROLE_USER') or #oauth2.isClient()) and #oauth2.hasScope('read')") - .regexMatchers(HttpMethod.GET, "/oauth/clients/.*") - .access("#oauth2.clientHasRole('ROLE_CLIENT') and #oauth2.isClient() and #oauth2.hasScope('read')") - .and() - .requestMatchers() - .antMatchers("/photos/**", "/oauth/users/**", "/oauth/clients/**") - .and() - .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER) - .and() - .exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler()) - .and() - // CSRF protection is awkward for machine clients - .csrf() - .requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/**")).disable() - .apply(new OAuth2ResourceServerConfigurer()).tokenStore(tokenStore) - .resourceId(SPARKLR_RESOURCE_ID); - // @formatter:on } @Configuration @@ -130,8 +124,7 @@ protected static class AuthorizationServerConfiguration extends AuthorizationSer public void configure(ClientDetailsServiceConfigurer clients) throws Exception { // @formatter:off - clients.inMemory() - .withClient("tonr") + clients.inMemory().withClient("tonr") .resourceIds(SPARKLR_RESOURCE_ID) .authorizedGrantTypes("authorization_code", "implicit") .authorities("ROLE_CLIENT") @@ -178,7 +171,8 @@ public void configure(ClientDetailsServiceConfigurer clients) throws Exception { // @formatter:on } - private SparklrUserApprovalHandler userApprovalHandler() throws Exception { + @Bean + public SparklrUserApprovalHandler userApprovalHandler() throws Exception { SparklrUserApprovalHandler handler = new SparklrUserApprovalHandler(); handler.setApprovalStore(approvalStore()); handler.setRequestFactory(requestFactory); diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/SecurityConfiguration.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/SecurityConfiguration.java index a2ce93005..cc845418f 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/SecurityConfiguration.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/SecurityConfiguration.java @@ -22,7 +22,7 @@ protected void configure(AuthenticationManagerBuilder auth) throws Exception { @Override public void configure(WebSecurity web) throws Exception { - web.ignoring().antMatchers("/webjars/**", "/images/**"); + web.ignoring().antMatchers("/webjars/**", "/images/**", "/oauth/uncache_approvals", "/oauth/cache_approvals"); } @Override diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/WebMvcConfig.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/WebMvcConfig.java index b164242c8..b65415129 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/WebMvcConfig.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/WebMvcConfig.java @@ -12,9 +12,13 @@ import org.springframework.security.oauth.examples.sparklr.PhotoService; import org.springframework.security.oauth.examples.sparklr.impl.PhotoServiceImpl; import org.springframework.security.oauth.examples.sparklr.mvc.AccessConfirmationController; +import org.springframework.security.oauth.examples.sparklr.mvc.AdminController; import org.springframework.security.oauth.examples.sparklr.mvc.PhotoController; +import org.springframework.security.oauth.examples.sparklr.oauth.SparklrUserApprovalHandler; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.approval.ApprovalStore; +import org.springframework.security.oauth2.provider.token.ConsumerTokenServices; +import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.web.accept.ContentNegotiationManagerFactoryBean; import org.springframework.web.servlet.View; import org.springframework.web.servlet.ViewResolver; @@ -85,7 +89,17 @@ public PhotoServiceImpl photoServices() { } - private PhotoInfo createPhoto(String id, String userId) { + @Bean + public AdminController adminController(TokenStore tokenStore, ConsumerTokenServices tokenServices, + SparklrUserApprovalHandler userApprovalHandler) { + AdminController adminController = new AdminController(); + adminController.setTokenStore(tokenStore); + adminController.setTokenServices(tokenServices); + adminController.setUserApprovalHandler(userApprovalHandler); + return adminController; + } + + private PhotoInfo createPhoto(String id, String userId) { PhotoInfo photo = new PhotoInfo(); photo.setId(id); photo.setName("photo" + id + ".jpg"); diff --git a/samples/oauth2/sparklr/src/main/resources/simplelog.properties b/samples/oauth2/sparklr/src/main/resources/simplelog.properties index 87854d8d2..62efffc15 100644 --- a/samples/oauth2/sparklr/src/main/resources/simplelog.properties +++ b/samples/oauth2/sparklr/src/main/resources/simplelog.properties @@ -1,6 +1,6 @@ org.apache.commons.logging.simplelog.defaultlog=info org.apache.commons.logging.simplelog.showdatetime=true org.apache.commons.logging.simplelog.dateTimeFormat='sparklr2' HH:mm:ss.SSS -org.apache.commons.logging.simplelog.log.org.springframework.web=debug +#org.apache.commons.logging.simplelog.log.org.springframework.web=debug org.apache.commons.logging.simplelog.log.org.springframework.security=debug org.apache.commons.logging.simplelog.log.org.springframework.security.access.method.DelegatingMethodSecurityMetadataSource=info diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/OAuth2ContextSetup.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/OAuth2ContextSetup.java index 03ad890d6..1d9c58454 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/OAuth2ContextSetup.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/OAuth2ContextSetup.java @@ -84,6 +84,7 @@ * @author Dave Syer * */ +@SuppressWarnings("deprecation") public class OAuth2ContextSetup extends TestWatchman { private static Log logger = LogFactory.getLog(OAuth2ContextSetup.class); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java index 036f95091..1a5c35743 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java @@ -42,6 +42,16 @@ public InMemoryClientDetailsServiceBuilder inMemory() throws Exception { return new InMemoryClientDetailsServiceBuilder(); } + @SuppressWarnings("rawtypes") + public ClientDetailsServiceBuilder clients(final ClientDetailsService clientDetailsService) throws Exception { + return new ClientDetailsServiceBuilder() { + @Override + public ClientDetailsService build() throws Exception { + return clientDetailsService; + } + }; + } + public ClientBuilder withClient(String clientId) { ClientBuilder clientBuilder = new ClientBuilder(clientId); this.clientBuilders.add(clientBuilder); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/configuration/ClientDetailsServiceConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/configuration/ClientDetailsServiceConfiguration.java new file mode 100644 index 000000000..a7319d4d6 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/configuration/ClientDetailsServiceConfiguration.java @@ -0,0 +1,49 @@ +/* + * Copyright 2002-2013 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.configuration; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Lazy; +import org.springframework.context.annotation.Scope; +import org.springframework.context.annotation.ScopedProxyMode; +import org.springframework.security.oauth2.config.annotation.builders.ClientDetailsServiceBuilder; +import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; +import org.springframework.security.oauth2.provider.ClientDetailsService; + +/** + * @author Rob Winch + * + */ +@Configuration +public class ClientDetailsServiceConfiguration { + + @SuppressWarnings("rawtypes") + private ClientDetailsServiceConfigurer configurer = new ClientDetailsServiceConfigurer(new ClientDetailsServiceBuilder()); + + @Bean + public ClientDetailsServiceConfigurer clientDetailsServiceConfigurer() { + return configurer; + } + + @Bean + @Lazy + @Scope(proxyMode=ScopedProxyMode.INTERFACES) + public ClientDetailsService clientDetailsService() throws Exception { + return configurer.and().build(); + } + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/configurers/ClientDetailsServiceConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/configurers/ClientDetailsServiceConfigurer.java index 9db06f582..bee2971b5 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/configurers/ClientDetailsServiceConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/configurers/ClientDetailsServiceConfigurer.java @@ -15,49 +15,39 @@ */ package org.springframework.security.oauth2.config.annotation.configurers; -import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.SecurityConfigurerAdapter; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.oauth2.config.annotation.builders.ClientDetailsServiceBuilder; import org.springframework.security.oauth2.config.annotation.builders.InMemoryClientDetailsServiceBuilder; import org.springframework.security.oauth2.provider.ClientDetailsService; -import org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService; /** * @author Rob Winch * */ public class ClientDetailsServiceConfigurer extends - SecurityConfigurerAdapter { + SecurityConfigurerAdapter> { - private ClientDetailsService clientDetailsService; - - @SuppressWarnings("rawtypes") - private ClientDetailsServiceBuilder builder = new ClientDetailsServiceBuilder(); - - public AuthenticationManagerBuilder withClientDetails(ClientDetailsService clientDetailsService) { + public ClientDetailsServiceConfigurer(ClientDetailsServiceBuilder builder) { + setBuilder(builder); + } - this.clientDetailsService = clientDetailsService; + public ClientDetailsServiceBuilder withClientDetails(ClientDetailsService clientDetailsService) throws Exception { + setBuilder(getBuilder().clients(clientDetailsService)); return this.and(); } public InMemoryClientDetailsServiceBuilder inMemory() throws Exception { - InMemoryClientDetailsServiceBuilder next = builder.inMemory(); - this.builder = next; + InMemoryClientDetailsServiceBuilder next = getBuilder().inMemory(); + setBuilder(next); return next; } - + @Override - public void init(AuthenticationManagerBuilder builder) throws Exception { - ClientDetailsService clientDetailsService = this.clientDetailsService != null ? this.clientDetailsService - : this.builder.build(); - ClientDetailsUserDetailsService userDetailsService = new ClientDetailsUserDetailsService(clientDetailsService); - builder.userDetailsService(userDetailsService); - builder.setSharedObject(ClientDetailsService.class, clientDetailsService); + public void init(ClientDetailsServiceBuilder builder) throws Exception { } @Override - public void configure(AuthenticationManagerBuilder builder) throws Exception { - + public void configure(ClientDetailsServiceBuilder builder) throws Exception { } + } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java index 5db28a4aa..2a21d14d1 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java @@ -21,12 +21,15 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.ScopedProxyMode; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.core.annotation.Order; +import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.configuration.ClientDetailsServiceConfiguration; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer; import org.springframework.security.oauth2.provider.ClientDetailsService; @@ -49,29 +52,33 @@ * */ @Configuration +@Import(ClientDetailsServiceConfiguration.class) +@Order(0) public class AuthorizationServerConfiguration extends WebSecurityConfigurerAdapter { + @Autowired private List configurers = Collections.emptyList(); - /** - * @param configurers the configurers to set - */ - @Autowired(required = false) - public void setConfigurers(List configurers) { - this.configurers = configurers; + @Autowired + private ClientDetailsService clientDetailsService; + + @Configuration + protected static class ClientDetailsAuthenticationManagerConfiguration extends GlobalAuthenticationConfigurerAdapter { + } @Autowired - public void configure(AuthenticationManagerBuilder builder) throws Exception { - ClientDetailsServiceConfigurer clients = builder.apply(new ClientDetailsServiceConfigurer()); + public void configure(ClientDetailsServiceConfigurer clientDetails) + throws Exception { for (AuthorizationServerConfigurer configurer : configurers) { - configurer.configure(clients); + configurer.configure(clientDetails); } } @Override protected void configure(HttpSecurity http) throws Exception { OAuth2AuthorizationServerConfigurer configurer = new OAuth2AuthorizationServerConfigurer(); + configurer.clientDetailsService(clientDetailsService); configure(configurer); // @formatter:off http @@ -82,7 +89,8 @@ protected void configure(HttpSecurity http) throws Exception { .antMatchers("/oauth/token") .and() .apply(configurer); - // @formatter:on + // @formatter:on + http.setSharedObject(ClientDetailsService.class, clientDetailsService); } protected void configure(OAuth2AuthorizationServerConfigurer oauthServer) throws Exception { @@ -95,7 +103,7 @@ protected void configure(OAuth2AuthorizationServerConfigurer oauthServer) throws public AuthorizationEndpoint authorizationEndpoint() throws Exception { AuthorizationEndpoint authorizationEndpoint = new AuthorizationEndpoint(); authorizationEndpoint.setTokenGranter(tokenGranter()); - authorizationEndpoint.setClientDetailsService(clientDetailsService()); + authorizationEndpoint.setClientDetailsService(clientDetailsService); authorizationEndpoint.setAuthorizationCodeServices(authorizationCodeServices()); authorizationEndpoint.setUserApprovalHandler(userApprovalHandler()); authorizationEndpoint.setImplicitGrantService(getImplicitGrantService()); @@ -119,7 +127,7 @@ public ConsumerTokenServices consumerTokenServices() throws Exception { @Bean public TokenEndpoint tokenEndpoint() throws Exception { TokenEndpoint tokenEndpoint = new TokenEndpoint(); - tokenEndpoint.setClientDetailsService(clientDetailsService()); + tokenEndpoint.setClientDetailsService(clientDetailsService); tokenEndpoint.setTokenGranter(tokenGranter()); return tokenEndpoint; } @@ -159,13 +167,6 @@ public FrameworkEndpointHandlerMapping endpointHandlerMapping() { return new FrameworkEndpointHandlerMapping(); } - @Bean - @Lazy - @Scope(proxyMode = ScopedProxyMode.INTERFACES) - public ClientDetailsService clientDetailsService() throws Exception { - return getHttp().getSharedObject(ClientDetailsService.class); - } - @Bean @Lazy @Scope(proxyMode = ScopedProxyMode.INTERFACES) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableResourceServer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableResourceServer.java new file mode 100644 index 000000000..859825e40 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableResourceServer.java @@ -0,0 +1,34 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.springframework.security.oauth2.config.annotation.web.configuration; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.context.annotation.Import; + +/** + * @author Dave Syer + * + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Import(ResourceServerImportSelector.class) +public @interface EnableResourceServer { + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java new file mode 100644 index 000000000..31ce1f691 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java @@ -0,0 +1,67 @@ +/* + * Copyright 2002-2013 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.web.configuration; + +import java.util.Collections; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.Order; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.web.configurers.OAuth2ResourceServerConfigurer; +import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; +import org.springframework.security.oauth2.provider.token.TokenStore; +import org.springframework.security.web.access.AccessDeniedHandler; + +/** + * @author Dave Syer + * + */ +@Configuration +@Order(3) +public class ResourceServerConfiguration extends WebSecurityConfigurerAdapter { + + @Autowired + private TokenStore tokenStore; + + private List configurers = Collections.emptyList(); + + private AccessDeniedHandler accessDeniedHandler = new OAuth2AccessDeniedHandler(); + + /** + * @param configurers the configurers to set + */ + @Autowired(required = false) + public void setConfigurers(List configurers) { + this.configurers = configurers; + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + for (ResourceServerConfigurer configurer : configurers) { + configurer.configure(http); + } + OAuth2ResourceServerConfigurer resources = new OAuth2ResourceServerConfigurer(); + http.apply(resources).and().exceptionHandling().accessDeniedHandler(accessDeniedHandler); + for (ResourceServerConfigurer configurer : configurers) { + configurer.configure(resources); + } + resources.tokenStore(tokenStore); + } + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurer.java new file mode 100644 index 000000000..c6d9a847c --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurer.java @@ -0,0 +1,30 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.springframework.security.oauth2.config.annotation.web.configuration; + +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.oauth2.config.annotation.web.configurers.OAuth2ResourceServerConfigurer; + + +/** + * @author Dave Syer + * + */ +public interface ResourceServerConfigurer { + + void configure(OAuth2ResourceServerConfigurer resources) throws Exception; + + void configure(HttpSecurity http) throws Exception; + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurerAdapter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurerAdapter.java new file mode 100644 index 000000000..7689bb2de --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurerAdapter.java @@ -0,0 +1,32 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.springframework.security.oauth2.config.annotation.web.configuration; + +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.oauth2.config.annotation.web.configurers.OAuth2ResourceServerConfigurer; + +/** + * @author Dave Syer + * + */ +public class ResourceServerConfigurerAdapter implements ResourceServerConfigurer { + + @Override + public void configure(OAuth2ResourceServerConfigurer resources) throws Exception { + } + + @Override + public void configure(HttpSecurity http) throws Exception { + } + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerImportSelector.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerImportSelector.java new file mode 100644 index 000000000..f552efae3 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerImportSelector.java @@ -0,0 +1,30 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.springframework.security.oauth2.config.annotation.web.configuration; + +import org.springframework.context.annotation.ImportSelector; +import org.springframework.core.type.AnnotationMetadata; + +/** + * @author Dave Syer + * + */ +public class ResourceServerImportSelector implements ImportSelector { + + @Override + public String[] selectImports(AnnotationMetadata importingClassMetadata) { + return new String[] {ResourceServerConfiguration.class.getName()}; + } + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java index e85b75e52..916126eb2 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java @@ -27,12 +27,14 @@ import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.CompositeTokenGranter; import org.springframework.security.oauth2.provider.DefaultOAuth2RequestFactory; +import org.springframework.security.oauth2.provider.InMemoryClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; import org.springframework.security.oauth2.provider.TokenGranter; import org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler; import org.springframework.security.oauth2.provider.approval.UserApprovalHandler; import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter; import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenGranter; +import org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService; import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; import org.springframework.security.oauth2.provider.code.AuthorizationCodeTokenGranter; import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices; @@ -89,6 +91,8 @@ public final class OAuth2AuthorizationServerConfigurer extends private AuthenticationManager authenticationManager; + private ClientDetailsService clientDetailsService; + private String realm = "oauth2/client"; private ClientDetailsService clientDetails() { @@ -102,6 +106,10 @@ public AuthorizationServerTokenServices getTokenServices() { public TokenStore getTokenStore() { return tokenStore; } + + public ClientDetailsService getClientDetailsService() { + return clientDetailsService; + } public OAuth2RequestFactory getOAuth2RequestFactory() { return requestFactory; @@ -122,11 +130,12 @@ public OAuth2AuthorizationServerConfigurer userApprovalHandler(UserApprovalHandl } public OAuth2AuthorizationServerConfigurer realm(String realm) { - this.realm = realm; + this.realm = realm; return this; } - public OAuth2AuthorizationServerConfigurer authenticationEntryPoint(AuthenticationEntryPoint authenticationEntryPoint) { + public OAuth2AuthorizationServerConfigurer authenticationEntryPoint( + AuthenticationEntryPoint authenticationEntryPoint) { this.authenticationEntryPoint = authenticationEntryPoint; return this; } @@ -136,11 +145,17 @@ public OAuth2AuthorizationServerConfigurer authenticationManager(AuthenticationM return this; } + public OAuth2AuthorizationServerConfigurer clientDetailsService(ClientDetailsService clientDetailsService) { + this.clientDetailsService = clientDetailsService; + return this; + } + @Override public void init(HttpSecurity http) throws Exception { registerDefaultAuthenticationEntryPoint(http); - http.securityContext().securityContextRepository(new NullSecurityContextRepository()).and().csrf().disable() - .httpBasic().realmName(realm); + http.userDetailsService(new ClientDetailsUserDetailsService(clientDetailsService())).securityContext() + .securityContextRepository(new NullSecurityContextRepository()).and().csrf().disable().httpBasic() + .realmName(realm); } @SuppressWarnings("unchecked") @@ -163,11 +178,9 @@ private void registerDefaultAuthenticationEntryPoint(HttpSecurity http) { } @Override - @SuppressWarnings("unchecked") public void configure(HttpSecurity http) throws Exception { - AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager.class); clientCredentialsTokenEndpointFilter = new ClientCredentialsTokenEndpointFilter(); - clientCredentialsTokenEndpointFilter.setAuthenticationManager(authenticationManager); + clientCredentialsTokenEndpointFilter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class)); clientCredentialsTokenEndpointFilter = postProcess(clientCredentialsTokenEndpointFilter); this.tokenGranter = tokenGranter(http); @@ -177,8 +190,7 @@ public void configure(HttpSecurity http) throws Exception { // @formatter:off http .addFilterBefore(clientCredentialsTokenEndpointFilter, BasicAuthenticationFilter.class) - .getConfigurer(ExceptionHandlingConfigurer.class) - .accessDeniedHandler(accessDeniedHandler); + .exceptionHandling().accessDeniedHandler(accessDeniedHandler); // @formatter:on } @@ -186,7 +198,7 @@ public void configure(HttpSecurity http) throws Exception { public ConsumerTokenServices getConsumerTokenServices() { return consumerTokenServices; } - + public ImplicitGrantService getImplicitGrantService() { return implicitGrantService; } @@ -220,6 +232,13 @@ private TokenStore tokenStore() { return this.tokenStore; } + private ClientDetailsService clientDetailsService() { + if (clientDetailsService == null) { + this.clientDetailsService = new InMemoryClientDetailsService(); + } + return this.clientDetailsService; + } + private UserApprovalHandler userApprovalHandler() { if (userApprovalHandler == null) { TokenStoreUserApprovalHandler userApprovalHandler = new TokenStoreUserApprovalHandler(); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2ResourceServerConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2ResourceServerConfigurer.java index 315d07939..b759208db 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2ResourceServerConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2ResourceServerConfigurer.java @@ -49,107 +49,112 @@ * @since 3.2 */ public final class OAuth2ResourceServerConfigurer extends - SecurityConfigurerAdapter { - - private AuthenticationEntryPoint authenticationEntryPoint = new OAuth2AuthenticationEntryPoint(); - - private AccessDeniedHandler accessDeniedHandler = new OAuth2AccessDeniedHandler(); - - private OAuth2AuthenticationProcessingFilter resourcesServerFilter; - - private ResourceServerTokenServices resourceTokenServices; - - private TokenStore tokenStore = new InMemoryTokenStore(); - - private String resourceId = "oauth2-resource"; - - private SecurityExpressionHandler expressionHandler = new OAuth2WebSecurityExpressionHandler(); - - private ClientDetailsService clientDetails() { - return getBuilder().getSharedObject(ClientDetailsService.class); - } - - public TokenStore getTokenStore() { - return tokenStore; - } - - public OAuth2ResourceServerConfigurer tokenStore(TokenStore tokenStore) { - Assert.state(tokenStore!=null, "TokenStore cannot be null"); - this.tokenStore = tokenStore; - return this; - } - - @Override - public void init(HttpSecurity http) throws Exception { - registerDefaultAuthenticationEntryPoint(http); - } - - @SuppressWarnings("unchecked") - private void registerDefaultAuthenticationEntryPoint(HttpSecurity http) { - ExceptionHandlingConfigurer exceptionHandling = http - .getConfigurer(ExceptionHandlingConfigurer.class); - if (exceptionHandling == null) { - return; - } - ContentNegotiationStrategy contentNegotiationStrategy = http.getSharedObject(ContentNegotiationStrategy.class); - if (contentNegotiationStrategy == null) { - contentNegotiationStrategy = new HeaderContentNegotiationStrategy(); - } - MediaTypeRequestMatcher preferredMatcher = new MediaTypeRequestMatcher(contentNegotiationStrategy, - MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_FORM_URLENCODED, MediaType.APPLICATION_JSON, - MediaType.APPLICATION_OCTET_STREAM, MediaType.APPLICATION_XML, MediaType.MULTIPART_FORM_DATA, - MediaType.TEXT_XML); - preferredMatcher.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL)); - exceptionHandling.defaultAuthenticationEntryPointFor(postProcess(authenticationEntryPoint), preferredMatcher); - } - - public OAuth2ResourceServerConfigurer resourceId(String resourceId) { - this.resourceId = resourceId; - return this; - } - - @Override - @SuppressWarnings("unchecked") - public void configure(HttpSecurity http) throws Exception { - - AuthenticationManager oauthAuthenticationManager = oauthAuthenticationManager(http); - resourcesServerFilter = new OAuth2AuthenticationProcessingFilter(); - resourcesServerFilter.setAuthenticationManager(oauthAuthenticationManager); - resourcesServerFilter = postProcess(resourcesServerFilter); - - http.authorizeRequests().expressionHandler(expressionHandler).and() - .addFilterBefore(resourcesServerFilter, AbstractPreAuthenticatedProcessingFilter.class) - .getConfigurer(ExceptionHandlingConfigurer.class).accessDeniedHandler(accessDeniedHandler); - - } - - private AuthenticationManager oauthAuthenticationManager(HttpSecurity http) { - OAuth2AuthenticationManager oauthAuthenticationManager = new OAuth2AuthenticationManager(); - oauthAuthenticationManager.setResourceId(resourceId); - oauthAuthenticationManager.setTokenServices(resourceTokenServices(http)); - return oauthAuthenticationManager; - } - - private ResourceServerTokenServices resourceTokenServices(HttpSecurity http) { - tokenServices(http); - return this.resourceTokenServices; - } - - private ResourceServerTokenServices tokenServices(HttpSecurity http) { - if (resourceTokenServices != null) { - return resourceTokenServices; - } - DefaultTokenServices tokenServices = new DefaultTokenServices(); - tokenServices.setTokenStore(tokenStore()); - tokenServices.setSupportRefreshToken(true); - tokenServices.setClientDetailsService(clientDetails()); - this.resourceTokenServices = tokenServices; - return tokenServices; - } - - private TokenStore tokenStore() { - Assert.state(tokenStore!=null, "TokenStore cannot be null"); - return this.tokenStore; - } + SecurityConfigurerAdapter { + + private AuthenticationEntryPoint authenticationEntryPoint = new OAuth2AuthenticationEntryPoint(); + + private AccessDeniedHandler accessDeniedHandler = new OAuth2AccessDeniedHandler(); + + private OAuth2AuthenticationProcessingFilter resourcesServerFilter; + + private ResourceServerTokenServices resourceTokenServices; + + private TokenStore tokenStore = new InMemoryTokenStore(); + + private String resourceId = "oauth2-resource"; + + private SecurityExpressionHandler expressionHandler = new OAuth2WebSecurityExpressionHandler(); + + private ClientDetailsService clientDetails() { + return getBuilder().getSharedObject(ClientDetailsService.class); + } + + public TokenStore getTokenStore() { + return tokenStore; + } + + public OAuth2ResourceServerConfigurer tokenStore(TokenStore tokenStore) { + Assert.state(tokenStore != null, "TokenStore cannot be null"); + this.tokenStore = tokenStore; + return this; + } + + @Override + public void init(HttpSecurity http) throws Exception { + registerDefaultAuthenticationEntryPoint(http); + http.csrf().disable(); + } + + @SuppressWarnings("unchecked") + private void registerDefaultAuthenticationEntryPoint(HttpSecurity http) { + ExceptionHandlingConfigurer exceptionHandling = http + .getConfigurer(ExceptionHandlingConfigurer.class); + if (exceptionHandling == null) { + return; + } + ContentNegotiationStrategy contentNegotiationStrategy = http.getSharedObject(ContentNegotiationStrategy.class); + if (contentNegotiationStrategy == null) { + contentNegotiationStrategy = new HeaderContentNegotiationStrategy(); + } + MediaTypeRequestMatcher preferredMatcher = new MediaTypeRequestMatcher(contentNegotiationStrategy, + MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_FORM_URLENCODED, MediaType.APPLICATION_JSON, + MediaType.APPLICATION_OCTET_STREAM, MediaType.APPLICATION_XML, MediaType.MULTIPART_FORM_DATA, + MediaType.TEXT_XML); + preferredMatcher.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL)); + exceptionHandling.defaultAuthenticationEntryPointFor(postProcess(authenticationEntryPoint), preferredMatcher); + } + + public OAuth2ResourceServerConfigurer resourceId(String resourceId) { + this.resourceId = resourceId; + return this; + } + + + + @Override + public void configure(HttpSecurity http) throws Exception { + + AuthenticationManager oauthAuthenticationManager = oauthAuthenticationManager(http); + resourcesServerFilter = new OAuth2AuthenticationProcessingFilter(); + resourcesServerFilter.setAuthenticationManager(oauthAuthenticationManager); + resourcesServerFilter = postProcess(resourcesServerFilter); + + // @formatter:off + http + .authorizeRequests().expressionHandler(expressionHandler) + .and() + .addFilterBefore(resourcesServerFilter, AbstractPreAuthenticatedProcessingFilter.class) + .exceptionHandling().accessDeniedHandler(accessDeniedHandler); + // @formatter:on + } + + private AuthenticationManager oauthAuthenticationManager(HttpSecurity http) { + OAuth2AuthenticationManager oauthAuthenticationManager = new OAuth2AuthenticationManager(); + oauthAuthenticationManager.setResourceId(resourceId); + oauthAuthenticationManager.setTokenServices(resourceTokenServices(http)); + return oauthAuthenticationManager; + } + + private ResourceServerTokenServices resourceTokenServices(HttpSecurity http) { + tokenServices(http); + return this.resourceTokenServices; + } + + private ResourceServerTokenServices tokenServices(HttpSecurity http) { + if (resourceTokenServices != null) { + return resourceTokenServices; + } + DefaultTokenServices tokenServices = new DefaultTokenServices(); + tokenServices.setTokenStore(tokenStore()); + tokenServices.setSupportRefreshToken(true); + tokenServices.setClientDetailsService(clientDetails()); + this.resourceTokenServices = tokenServices; + return tokenServices; + } + + private TokenStore tokenStore() { + Assert.state(tokenStore != null, "TokenStore cannot be null"); + return this.tokenStore; + } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java index 39b628e35..268ff41e9 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java @@ -54,7 +54,7 @@ public void afterPropertiesSet() { /** * Expects the incoming authentication request to have a principal value that is an access token value (e.g. from an - * authorization header) .Loads an authentication from the {@link ResourceServerTokenServices} and checks that the + * authorization header). Loads an authentication from the {@link ResourceServerTokenServices} and checks that the * resource id is contained in the {@link AuthorizationRequest} (if one is specified). Also copies authentication * details over from the input to the output (e.g. typically so that the access token value and request details can * be reported later). @@ -78,6 +78,7 @@ public Authentication authenticate(Authentication authentication) throws Authent } auth.setDetails(authentication.getDetails()); + auth.setAuthenticated(true); return auth; } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java index 49c3e2f1d..625333f85 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java @@ -58,11 +58,12 @@ public class AuthorizationServerConfigurationTests { @Parameters public static List parameters() { - return Arrays.asList(new Object[] { BeanCreationException.class, - new Class[] { AuthorizationServerVanilla.class } }, new Object[] { null, - new Class[] { AuthorizationServerExtras.class, AuthorizationServerVanilla.class } }, new Object[] { - null, new Class[] { AuthorizationServerExtras.class } }, new Object[] { BeanCreationException.class, - new Class[] { AuthorizationServerTypes.class } }); + return Arrays.asList( // @formatter:off + new Object[] { BeanCreationException.class, new Class[] { AuthorizationServerVanilla.class } }, + new Object[] { null, new Class[] { AuthorizationServerExtras.class } }, + new Object[] { BeanCreationException.class, new Class[] { AuthorizationServerTypes.class } } + // @formatter:on +); } public AuthorizationServerConfigurationTests(Class error, Class... resource) { From dcc65b2dd19beb1d766c1bef6fb719a7afcf0288 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 6 Mar 2014 18:02:53 +0000 Subject: [PATCH 163/831] Add @EnableOAuth2Client --- .../oauth/examples/config/SecurityConfig.java | 2 - .../examples/config/ServletInitializer.java | 13 +++- .../oauth/examples/config/WebMvcConfig.java | 5 +- .../AuthorizationServerImportSelector.java | 30 -------- .../EnableAuthorizationServer.java | 18 ++++- .../web/configuration/EnableOAuth2Client.java | 74 +++++++++++++++++++ .../configuration/EnableResourceServer.java | 19 ++++- .../OAuth2ClientConfiguration.java | 9 ++- .../ResourceServerImportSelector.java | 30 -------- 9 files changed, 126 insertions(+), 74 deletions(-) delete mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerImportSelector.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableOAuth2Client.java delete mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerImportSelector.java diff --git a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/SecurityConfig.java b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/SecurityConfig.java index eec85d1d3..6d545e62f 100644 --- a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/SecurityConfig.java +++ b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/SecurityConfig.java @@ -8,7 +8,6 @@ import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter; -import org.springframework.security.web.access.ExceptionTranslationFilter; @Configuration @EnableWebSecurity @@ -38,7 +37,6 @@ protected void configure(HttpSecurity http) throws Exception { .antMatchers("/sparklr/**","/facebook/**").hasRole("USER") .anyRequest().permitAll() .and() - .addFilterAfter(oauth2ClientFilter(), ExceptionTranslationFilter.class) .logout() .logoutSuccessUrl("/login.jsp") .logoutUrl("/logout.do") diff --git a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/ServletInitializer.java b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/ServletInitializer.java index a820d5212..9dfd544eb 100644 --- a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/ServletInitializer.java +++ b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/ServletInitializer.java @@ -43,13 +43,18 @@ protected String[] getServletMappings() { protected WebApplicationContext createRootApplicationContext() { return null; } - + @Override public void onStartup(ServletContext servletContext) throws ServletException { super.onStartup(servletContext); - DelegatingFilterProxy filter = new DelegatingFilterProxy("springSecurityFilterChain"); + registerProxyFilter(servletContext, "springSecurityFilterChain"); + registerProxyFilter(servletContext, "oauth2ClientContextFilter"); + } + + private void registerProxyFilter(ServletContext servletContext, String name) { + DelegatingFilterProxy filter = new DelegatingFilterProxy(name); filter.setContextAttribute("org.springframework.web.servlet.FrameworkServlet.CONTEXT.dispatcher"); - servletContext.addFilter("springSecurityFilterChain", filter).addMappingForUrlPatterns(null, false, "/*"); + servletContext.addFilter(name, filter).addMappingForUrlPatterns(null, false, "/*"); } - + } diff --git a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/WebMvcConfig.java b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/WebMvcConfig.java index d9d41f629..07dbcf772 100644 --- a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/WebMvcConfig.java +++ b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/WebMvcConfig.java @@ -10,7 +10,6 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; import org.springframework.context.annotation.PropertySource; import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.ScopedProxyMode; @@ -33,7 +32,7 @@ import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails; import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails; import org.springframework.security.oauth2.common.AuthenticationScheme; -import org.springframework.security.oauth2.config.annotation.web.configuration.OAuth2ClientConfiguration; +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client; import org.springframework.web.accept.ContentNegotiationManagerFactoryBean; import org.springframework.web.client.RestOperations; import org.springframework.web.servlet.View; @@ -152,7 +151,7 @@ public void configureMessageConverters(List> converters) } @Configuration - @Import(OAuth2ClientConfiguration.class) + @EnableOAuth2Client protected static class ResourceConfiguration { @Value("${accessTokenUri}") diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerImportSelector.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerImportSelector.java deleted file mode 100644 index 7f0ad8fd1..000000000 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerImportSelector.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2013-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ - -package org.springframework.security.oauth2.config.annotation.web.configuration; - -import org.springframework.context.annotation.ImportSelector; -import org.springframework.core.type.AnnotationMetadata; - -/** - * @author Dave Syer - * - */ -public class AuthorizationServerImportSelector implements ImportSelector { - - @Override - public String[] selectImports(AnnotationMetadata importingClassMetadata) { - return new String[] {AuthorizationServerConfiguration.class.getName()}; - } - -} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableAuthorizationServer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableAuthorizationServer.java index a1cc685bb..303757fc2 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableAuthorizationServer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableAuthorizationServer.java @@ -20,15 +20,29 @@ import java.lang.annotation.Target; import org.springframework.context.annotation.Import; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint; +import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint; +import org.springframework.web.servlet.DispatcherServlet; /** + * Convenience annotation for enabling an Authorization Server (i.e. an {@link AuthorizationEndpoint} and a + * {@link TokenEndpoint}) in the current application context, which must be a {@link DispatcherServlet} context. Many + * features of the server can be customized using @Beans of type {@link AuthorizationServerConfigurer} + * (e.g. by extending {@link AuthorizationServerConfigurerAdapter}). The user is responsible for securing the + * Authorization Endpoint (/oauth/authorize) using normal Spring Security features ({@link EnableWebSecurity + * @EnableWebSecurity} etc.), but the Token Endpoint will be automatically secured using HTTP Basic authentication + * on the client's credentials. Clients must be registered by providing a {@link ClientDetailsService} through + * one or more AuthorizationServerConfigurers. + * * @author Dave Syer - * + * */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented -@Import(AuthorizationServerImportSelector.class) +@Import(AuthorizationServerConfiguration.class) public @interface EnableAuthorizationServer { } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableOAuth2Client.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableOAuth2Client.java new file mode 100644 index 000000000..843d5efb3 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableOAuth2Client.java @@ -0,0 +1,74 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.springframework.security.oauth2.config.annotation.web.configuration; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.context.annotation.Import; +import org.springframework.security.oauth2.client.OAuth2RestTemplate; +import org.springframework.security.oauth2.client.token.AccessTokenRequest; +import org.springframework.web.filter.DelegatingFilterProxy; + +/** + * Enable configuration for an OAuth2 client in a web application that uses Spring Security and wants to use the + * Authorization Code Grant from one or more OAuth2 Authorization servers. To take advantage of this feature you need a + * global servlet filter in your application of the {@link DelegatingFilterProxy} that delegates to a bean named + * "oauth2ClientContextFilter". Once that filter is in place your client app can use another bean provided by this + * annotation (an {@link AccessTokenRequest}) to create an {@link OAuth2RestTemplate}, e.g. + * + *
+ * @Configuration
+ * @EnableOAuth2Client
+ * public class RemoteResourceConfiguration {
+ * 
+ * 	@Resource
+ * 	@Qualifier("accessTokenRequest")
+ * 	private AccessTokenRequest accessTokenRequest;
+ * 
+ * 	@Bean
+ * 	public OAuth2ProtectedResourceDetails remote() {
+ * 		AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails();
+ * 		// set up resource details, OAuth2 URLs etc.
+ * 		return details;
+ * 	}
+ * 
+ * 	@Bean
+ * 	@Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)
+ * 	public OAuth2RestOperations restTemplate() {
+ * 		return new OAuth2RestTemplate(remote(), new DefaultOAuth2ClientContext(accessTokenRequest));
+ * 	}
+ * 
+ * }
+ * 
+ * + * Client apps that use client credentials grants do not need the AccessTokenRequest or the scoped RestOperations (the + * state is global for the app), but they should still use the filter to trigger the OAuth2RestOperations to obtain a + * token when necessary. Apps that us password grants need to set the authentication properties in the + * OAuth2ProtectedResourceDetails before using the RestOperations, and this means the resource details themselves also + * have to be per session (assuming there are multiple users in the system). + * + * @author Dave Syer + * + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Import(OAuth2ClientConfiguration.class) +public @interface EnableOAuth2Client { + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableResourceServer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableResourceServer.java index 859825e40..efaa1ce48 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableResourceServer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableResourceServer.java @@ -20,15 +20,30 @@ import java.lang.annotation.Target; import org.springframework.context.annotation.Import; +import org.springframework.core.annotation.Order; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; /** + * Convenient annotation for OAuth2 Resource Servers, enabling a Spring Security filter that authenticates requests via + * an incoming OAuth2 token. Users should add this annotation and provide a @Bean of type + * {@link ResourceServerConfigurer} (e.g. via {@link ResourceServerConfigurerAdapter}) that specifies the details of the + * resource (URL paths and resource id). In order to use this filter you must {@link EnableWebSecurity + * @EnableWebSecurity} somewhere in your application, either in the same place as you use this annotation, or + * somewhere else. + * + *

+ * The annotation creates a {@link WebSecurityConfigurerAdapter} with a hard-coded {@link Order} (of 3). It's not + * possible to change the order right now owing to technical limitations in Spring, so you must avoid using order=3 in + * other WebSecurityConfigurerAdapters in your application (Spring Security will let you know if you forget). + * * @author Dave Syer - * + * */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented -@Import(ResourceServerImportSelector.class) +@Import(ResourceServerConfiguration.class) public @interface EnableResourceServer { } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/OAuth2ClientConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/OAuth2ClientConfiguration.java index e2fe23c46..f8450cbc0 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/OAuth2ClientConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/OAuth2ClientConfiguration.java @@ -20,6 +20,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.ScopedProxyMode; +import org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter; import org.springframework.security.oauth2.client.token.AccessTokenRequest; import org.springframework.security.oauth2.client.token.DefaultAccessTokenRequest; @@ -30,6 +31,12 @@ @Configuration public class OAuth2ClientConfiguration { + @Bean + public OAuth2ClientContextFilter oauth2ClientContextFilter() { + OAuth2ClientContextFilter filter = new OAuth2ClientContextFilter(); + return filter; + } + @Bean @Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES) protected AccessTokenRequest accessTokenRequest(@Value("#{request.parameterMap}") @@ -39,5 +46,5 @@ protected AccessTokenRequest accessTokenRequest(@Value("#{request.parameterMap}" request.setCurrentUri(currentUri); return request; } - + } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerImportSelector.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerImportSelector.java deleted file mode 100644 index f552efae3..000000000 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerImportSelector.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2013-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ - -package org.springframework.security.oauth2.config.annotation.web.configuration; - -import org.springframework.context.annotation.ImportSelector; -import org.springframework.core.type.AnnotationMetadata; - -/** - * @author Dave Syer - * - */ -public class ResourceServerImportSelector implements ImportSelector { - - @Override - public String[] selectImports(AnnotationMetadata importingClassMetadata) { - return new String[] {ResourceServerConfiguration.class.getName()}; - } - -} From 37fe453d3cf423a1cc0cafccb8e5075082adf67f Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 6 Mar 2014 18:17:17 +0000 Subject: [PATCH 164/831] Add JDBC support to @Enabled auth server --- .../builders/ClientDetailsServiceBuilder.java | 4 ++ .../JdbcClientDetailsServiceBuilder.java | 58 +++++++++++++++++++ .../ClientDetailsServiceConfigurer.java | 8 +++ .../EnableAuthorizationServer.java | 6 +- ...AuthorizationServerConfigurationTests.java | 46 +++++++++++++-- .../provider/AuthorizationRequestTests.java | 6 +- .../DefaultAuthorizationRequestTests.java | 6 +- 7 files changed, 119 insertions(+), 15 deletions(-) create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/JdbcClientDetailsServiceBuilder.java diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java index 1a5c35743..8c400f410 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java @@ -42,6 +42,10 @@ public InMemoryClientDetailsServiceBuilder inMemory() throws Exception { return new InMemoryClientDetailsServiceBuilder(); } + public JdbcClientDetailsServiceBuilder jdbc() throws Exception { + return new JdbcClientDetailsServiceBuilder(); + } + @SuppressWarnings("rawtypes") public ClientDetailsServiceBuilder clients(final ClientDetailsService clientDetailsService) throws Exception { return new ClientDetailsServiceBuilder() { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/JdbcClientDetailsServiceBuilder.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/JdbcClientDetailsServiceBuilder.java new file mode 100644 index 000000000..455f67f91 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/JdbcClientDetailsServiceBuilder.java @@ -0,0 +1,58 @@ +/* + * Copyright 2002-2013 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.builders; + +import java.util.HashSet; +import java.util.Set; + +import javax.sql.DataSource; + +import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.JdbcClientDetailsService; +import org.springframework.util.Assert; + +/** + * @author Dave Syer + * + */ +public class JdbcClientDetailsServiceBuilder extends + ClientDetailsServiceBuilder { + + private Set clientDetails = new HashSet(); + private DataSource dataSource; + + public JdbcClientDetailsServiceBuilder dataSource(DataSource dataSource) { + this.dataSource = dataSource; + return this; + } + + @Override + protected void addClient(String clientId, ClientDetails value) { + clientDetails.add(value); + } + + @Override + protected ClientDetailsService performBuild() { + Assert.state(dataSource!=null, "You need to provide a DataSource"); + JdbcClientDetailsService clientDetailsService = new JdbcClientDetailsService(dataSource); + for (ClientDetails client : clientDetails) { + clientDetailsService.addClientDetails(client); + } + return clientDetailsService; + } + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/configurers/ClientDetailsServiceConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/configurers/ClientDetailsServiceConfigurer.java index bee2971b5..398666a4d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/configurers/ClientDetailsServiceConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/configurers/ClientDetailsServiceConfigurer.java @@ -15,9 +15,12 @@ */ package org.springframework.security.oauth2.config.annotation.configurers; +import javax.sql.DataSource; + import org.springframework.security.config.annotation.SecurityConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.builders.ClientDetailsServiceBuilder; import org.springframework.security.oauth2.config.annotation.builders.InMemoryClientDetailsServiceBuilder; +import org.springframework.security.oauth2.config.annotation.builders.JdbcClientDetailsServiceBuilder; import org.springframework.security.oauth2.provider.ClientDetailsService; /** @@ -41,6 +44,11 @@ public InMemoryClientDetailsServiceBuilder inMemory() throws Exception { setBuilder(next); return next; } + public JdbcClientDetailsServiceBuilder jdbc(DataSource dataSource) throws Exception { + JdbcClientDetailsServiceBuilder next = getBuilder().jdbc().dataSource(dataSource); + setBuilder(next); + return next; + } @Override public void init(ClientDetailsServiceBuilder builder) throws Exception { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableAuthorizationServer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableAuthorizationServer.java index 303757fc2..9687a7e57 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableAuthorizationServer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableAuthorizationServer.java @@ -32,9 +32,9 @@ * features of the server can be customized using @Beans of type {@link AuthorizationServerConfigurer} * (e.g. by extending {@link AuthorizationServerConfigurerAdapter}). The user is responsible for securing the * Authorization Endpoint (/oauth/authorize) using normal Spring Security features ({@link EnableWebSecurity - * @EnableWebSecurity} etc.), but the Token Endpoint will be automatically secured using HTTP Basic authentication - * on the client's credentials. Clients must be registered by providing a {@link ClientDetailsService} through - * one or more AuthorizationServerConfigurers. + * @EnableWebSecurity} etc.), but the Token Endpoint (/oauth/token) will be automatically secured using HTTP Basic + * authentication on the client's credentials. Clients must be registered by providing a + * {@link ClientDetailsService} through one or more AuthorizationServerConfigurers. * * @author Dave Syer * diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java index 625333f85..c2364d1a5 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java @@ -18,6 +18,8 @@ import java.util.Arrays; import java.util.List; +import javax.sql.DataSource; + import org.junit.After; import org.junit.Rule; import org.junit.Test; @@ -25,9 +27,11 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; +import org.mockito.Mockito; import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.mock.web.MockServletContext; import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity; @@ -39,6 +43,7 @@ import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint; import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; +import org.springframework.security.oauth2.provider.token.JdbcTokenStore; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; @@ -59,11 +64,12 @@ public class AuthorizationServerConfigurationTests { @Parameters public static List parameters() { return Arrays.asList( // @formatter:off - new Object[] { BeanCreationException.class, new Class[] { AuthorizationServerVanilla.class } }, + new Object[] { BeanCreationException.class, new Class[] { AuthorizationServerUnconfigured.class } }, new Object[] { null, new Class[] { AuthorizationServerExtras.class } }, + new Object[] { null, new Class[] { AuthorizationServerJdbc.class } }, new Object[] { BeanCreationException.class, new Class[] { AuthorizationServerTypes.class } } - // @formatter:on -); + // @formatter:on + ); } public AuthorizationServerConfigurationTests(Class error, Class... resource) { @@ -98,7 +104,7 @@ public void testDefaults() { @Configuration @EnableWebMvcSecurity @EnableAuthorizationServer - protected static class AuthorizationServerVanilla { + protected static class AuthorizationServerUnconfigured { } @Configuration @@ -136,6 +142,38 @@ public void run() { } + @Configuration + @EnableWebMvcSecurity + @EnableAuthorizationServer + protected static class AuthorizationServerJdbc extends AuthorizationServerConfigurerAdapter { + + @Autowired + private ApplicationContext context; + + @Override + public void configure(OAuth2AuthorizationServerConfigurer oauthServer) throws Exception { + oauthServer.tokenStore(new JdbcTokenStore(dataSource())).realm("sparklr2/client"); + } + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + // @formatter:off + clients.jdbc(dataSource()) + .withClient("my-trusted-client") + .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit") + .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") + .scopes("read", "write", "trust") + .accessTokenValiditySeconds(60); + // @formatter:on + } + + @Bean + public DataSource dataSource() { + return Mockito.mock(DataSource.class); + } + + } + @Configuration @EnableWebMvcSecurity protected static class AuthorizationServerTypes extends AuthorizationServerConfiguration { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/AuthorizationRequestTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/AuthorizationRequestTests.java index 507c12285..638f933c9 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/AuthorizationRequestTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/AuthorizationRequestTests.java @@ -27,8 +27,6 @@ import java.util.Set; import java.util.SortedSet; -import junit.framework.Assert; - import org.junit.Before; import org.junit.Test; import org.springframework.security.oauth2.common.util.OAuth2Utils; @@ -144,7 +142,7 @@ public void testScopeSortedOrder() { "AUTHORITY_AV AUTHORITY_AB AUTHORITY_CDA AUTHORITY_ABCD"; // Create correctly sorted scope string Set sortedSet = OAuth2Utils.parseParameterList(scopeString); - Assert.assertTrue(sortedSet instanceof SortedSet); + assertTrue(sortedSet instanceof SortedSet); String sortedScopeString = OAuth2Utils.formatParameterList(sortedSet); parameters.put("scope", scopeString); @@ -155,7 +153,7 @@ public void testScopeSortedOrder() { String fromAR = OAuth2Utils.formatParameterList(authorizationRequest.getScope()); - Assert.assertEquals(sortedScopeString, fromAR); + assertEquals(sortedScopeString, fromAR); } @Test diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequestTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequestTests.java index c75cb40e1..aaa0de253 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequestTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequestTests.java @@ -27,8 +27,6 @@ import java.util.Set; import java.util.SortedSet; -import junit.framework.Assert; - import org.junit.Before; import org.junit.Test; import org.springframework.security.oauth2.common.util.OAuth2Utils; @@ -116,7 +114,7 @@ public void testScopeSortedOrder() { "AUTHORITY_AV AUTHORITY_AB AUTHORITY_CDA AUTHORITY_ABCD"; // Create correctly sorted scope string Set sortedSet = OAuth2Utils.parseParameterList(scopeString); - Assert.assertTrue(sortedSet instanceof SortedSet); + assertTrue(sortedSet instanceof SortedSet); String sortedScopeString = OAuth2Utils.formatParameterList(sortedSet); parameters.put("scope", scopeString); @@ -127,7 +125,7 @@ public void testScopeSortedOrder() { String fromAR = OAuth2Utils.formatParameterList(authorizationRequest.getScope()); - Assert.assertEquals(sortedScopeString, fromAR); + assertEquals(sortedScopeString, fromAR); } @Test From 7e387268170d4b55540993acb2a73a1b6441c453 Mon Sep 17 00:00:00 2001 From: james Date: Thu, 23 Jan 2014 08:54:56 +0100 Subject: [PATCH 165/831] Logout link added to tonr's main page Fixes gh-148 --- samples/oauth2/tonr/src/main/webapp/index.jsp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/samples/oauth2/tonr/src/main/webapp/index.jsp b/samples/oauth2/tonr/src/main/webapp/index.jsp index 7b699e37e..ea6e6383a 100644 --- a/samples/oauth2/tonr/src/main/webapp/index.jsp +++ b/samples/oauth2/tonr/src/main/webapp/index.jsp @@ -29,13 +29,12 @@

@@ -66,6 +65,9 @@ ">View my Sparklr photos

+

+ ">Logout +

From c5632b34454172a5a51fb96680637d88c54b7c53 Mon Sep 17 00:00:00 2001 From: Jochen Schalanda Date: Wed, 22 Jan 2014 17:53:38 +0100 Subject: [PATCH 166/831] Fix broken link to OAuth 2.0 section --- docs/Home.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Home.md b/docs/Home.md index f48f652b6..083edff8f 100644 --- a/docs/Home.md +++ b/docs/Home.md @@ -13,7 +13,7 @@ implementation for Support is provided for the implementation of OAuth providers and OAuth consumers. There is support for [Oauth 1(a)](oauth1.html) (including [two-legged OAuth](twolegged.html), a.k.a. "Signed Fetch") and for -[OAuth 2.0]oauth2.md). +[OAuth 2.0](oauth2.md). Applying security to an application is not for the faint of heart, and OAuth is no exception. Before you get started, you're going to want to make sure you understand OAuth and the problem it's designed to address. There is good From cbd1c65a75bba1791d10628599fb9207f2a91a27 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 7 Mar 2014 10:17:31 +0000 Subject: [PATCH 167/831] [maven-release-plugin] prepare release 2.0.0.M3 --- pom.xml | 4 ++-- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 5 ++--- samples/oauth2/tonr/pom.xml | 5 ++--- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- 8 files changed, 11 insertions(+), 13 deletions(-) diff --git a/pom.xml b/pom.xml index 982cff903..c8a06ff50 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.0.BUILD-SNAPSHOT + 2.0.0.M3 http://static.springframework.org/spring-security/oauth @@ -27,7 +27,7 @@ http://github.com/SpringSource/spring-security-oauth scm:git:git://github.com/SpringSource/spring-security-oauth.git scm:git:ssh://git@github.com/SpringSource/spring-security-oauth.git - HEAD + 2.0.0.M3 JIRA diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index 4ca71dec4..d7759e9c4 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.0.BUILD-SNAPSHOT + 2.0.0.M3 ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index 439d42eca..c519cacde 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.0.BUILD-SNAPSHOT + 2.0.0.M3 ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index c62721eb4..547102a2e 100644 --- a/samples/oauth2/sparklr/pom.xml +++ b/samples/oauth2/sparklr/pom.xml @@ -1,12 +1,11 @@ - + 4.0.0 org.springframework.security.oauth spring-security-oauth-parent - 2.0.0.BUILD-SNAPSHOT + 2.0.0.M3 ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 75055e810..e965a1ed8 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -1,12 +1,11 @@ - + 4.0.0 org.springframework.security.oauth spring-security-oauth-parent - 2.0.0.BUILD-SNAPSHOT + 2.0.0.M3 ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index d88a907a1..37bd65969 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.0.BUILD-SNAPSHOT + 2.0.0.M3 spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index e2e00bca1..7f504546c 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.0.BUILD-SNAPSHOT + 2.0.0.M3 spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 3542e674a..4be4bb70a 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.0.BUILD-SNAPSHOT + 2.0.0.M3 spring-security-oauth2 From 753e6ad7bc8e76abf1a6ac07051b2414e7c66d23 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 7 Mar 2014 10:17:36 +0000 Subject: [PATCH 168/831] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index c8a06ff50..982cff903 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.0.M3 + 2.0.0.BUILD-SNAPSHOT http://static.springframework.org/spring-security/oauth @@ -27,7 +27,7 @@ http://github.com/SpringSource/spring-security-oauth scm:git:git://github.com/SpringSource/spring-security-oauth.git scm:git:ssh://git@github.com/SpringSource/spring-security-oauth.git - 2.0.0.M3 + HEAD JIRA diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index d7759e9c4..4ca71dec4 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.0.M3 + 2.0.0.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index c519cacde..439d42eca 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.0.M3 + 2.0.0.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 547102a2e..1debda092 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.0.M3 + 2.0.0.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index e965a1ed8..28e74a729 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.0.M3 + 2.0.0.BUILD-SNAPSHOT ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index 37bd65969..d88a907a1 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.0.M3 + 2.0.0.BUILD-SNAPSHOT spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index 7f504546c..e2e00bca1 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.0.M3 + 2.0.0.BUILD-SNAPSHOT spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 4be4bb70a..3542e674a 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.0.M3 + 2.0.0.BUILD-SNAPSHOT spring-security-oauth2 From 4b2503302037c3b979af6cf4ef41fa552ce82419 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 10 Mar 2014 11:16:56 +0000 Subject: [PATCH 169/831] Add test for redirect with query params --- .../endpoint/AuthorizationEndpointTests.java | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java index c240ce10c..8b541a466 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java @@ -37,13 +37,14 @@ import org.springframework.security.oauth2.common.exceptions.InvalidScopeException; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.common.util.OAuth2Utils; +import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.TokenGranter; import org.springframework.security.oauth2.provider.TokenRequest; +import org.springframework.security.oauth2.provider.approval.DefaultUserApprovalHandler; import org.springframework.security.oauth2.provider.approval.UserApprovalHandler; import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; import org.springframework.web.bind.support.SimpleSessionStatus; @@ -252,6 +253,27 @@ public boolean isApproved(AuthorizationRequest authorizationRequest, Authenticat assertTrue("Wrong scope: " + result, url.contains("&scope=read")); } + @Test + public void testImplicitWithQueryParam() throws Exception { + endpoint.setTokenGranter(new TokenGranter() { + public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) { + DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken("FOO"); + return token; + } + }); + endpoint.setUserApprovalHandler(new DefaultUserApprovalHandler() { + public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { + return true; + } + }); + AuthorizationRequest authorizationRequest = getAuthorizationRequest("foo", "http://anywhere.com/?foo=bar", "mystate", + "myscope", Collections.singleton("token")); + ModelAndView result = endpoint.authorize(model, authorizationRequest.getRequestParameters(), + sessionStatus, principal); + String url = ((RedirectView) result.getView()).getUrl(); + assertTrue("Wrong url: " + result, url.contains("foo=bar")); + } + @Test public void testImplicitAppendsScopeWhenDefaulting() throws Exception { endpoint.setTokenGranter(new TokenGranter() { From 1c0c6a15cf6d6e9525823501dbd06ea35da7917c Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 10 Mar 2014 12:43:25 +0000 Subject: [PATCH 170/831] Add user approval handler to default configuration Fixes gh-156 --- .../web/configurers/OAuth2AuthorizationServerConfigurer.java | 2 ++ .../annotation/AuthorizationServerConfigurationTests.java | 2 ++ 2 files changed, 4 insertions(+) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java index 916126eb2..925a53669 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java @@ -244,6 +244,8 @@ private UserApprovalHandler userApprovalHandler() { TokenStoreUserApprovalHandler userApprovalHandler = new TokenStoreUserApprovalHandler(); userApprovalHandler.setTokenStore(tokenStore()); userApprovalHandler.setClientDetailsService(clientDetails()); + userApprovalHandler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService())); + this.userApprovalHandler = userApprovalHandler; } return this.userApprovalHandler; } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java index c2364d1a5..46fdeb2b0 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java @@ -45,6 +45,7 @@ import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; import org.springframework.security.oauth2.provider.token.JdbcTokenStore; import org.springframework.security.oauth2.provider.token.TokenStore; +import org.springframework.test.util.ReflectionTestUtils; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; /** @@ -138,6 +139,7 @@ public void configure(ClientDetailsServiceConfigurer clients) throws Exception { public void run() { assertNotNull(context.getBean("clientDetailsService", ClientDetailsService.class).loadClientByClientId( "my-trusted-client")); + assertNotNull(ReflectionTestUtils.getField(context.getBean(AuthorizationEndpoint.class), "userApprovalHandler")); } } From 872a7a5c946db91209c6aa35c7b01687804c8964 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 10 Mar 2014 14:25:52 +0000 Subject: [PATCH 171/831] Add query and fragment encoding to redirect URIs Fixes gh-152 --- .../endpoint/AuthorizationEndpoint.java | 151 ++++++++---------- .../endpoint/AuthorizationEndpointTests.java | 40 +++++ 2 files changed, 106 insertions(+), 85 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java index 47c3211f2..99550d4b2 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java @@ -13,12 +13,11 @@ package org.springframework.security.oauth2.provider.endpoint; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; import java.security.Principal; import java.util.Collections; import java.util.Date; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; @@ -66,6 +65,7 @@ import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.View; import org.springframework.web.servlet.view.RedirectView; +import org.springframework.web.util.UriComponentsBuilder; import org.springframework.web.util.UriTemplate; /** @@ -97,9 +97,9 @@ public class AuthorizationEndpoint extends AbstractEndpoint { private UserApprovalHandler userApprovalHandler = new DefaultUserApprovalHandler(); private SessionAttributeStore sessionAttributeStore = new DefaultSessionAttributeStore(); - + private OAuth2RequestValidator oAuth2RequestValidator = new DefaultOAuth2RequestValidator(); - + private ImplicitGrantService implicitGrantService = new InMemoryImplicitGrantService(); private String userApprovalPage = "forward:/oauth/confirm_access"; @@ -115,12 +115,12 @@ public void setErrorPage(String errorPage) { } @RequestMapping - public ModelAndView authorize(Map model, @RequestParam Map parameters, - SessionStatus sessionStatus, Principal principal) { + public ModelAndView authorize(Map model, @RequestParam + Map parameters, SessionStatus sessionStatus, Principal principal) { - //Pull out the authorization request first, using the OAuth2RequestFactory. All further logic should - //query off of the authorization request instead of referring back to the parameters map. The contents of the - //parameters map will be stored without change in the AuthorizationRequest object once it is created. + // Pull out the authorization request first, using the OAuth2RequestFactory. All further logic should + // query off of the authorization request instead of referring back to the parameters map. The contents of the + // parameters map will be stored without change in the AuthorizationRequest object once it is created. AuthorizationRequest authorizationRequest = getOAuth2RequestFactory().createAuthorizationRequest(parameters); Set responseTypes = authorizationRequest.getResponseTypes(); @@ -132,14 +132,14 @@ public ModelAndView authorize(Map model, @RequestParam Map model, @RequestParam Map model, @RequestParam Map approvalParameters, Map model, - SessionStatus sessionStatus, Principal principal) { + public View approveOrDeny(@RequestParam + Map approvalParameters, Map model, SessionStatus sessionStatus, Principal principal) { if (!(principal instanceof Authentication)) { sessionStatus.setComplete(); @@ -209,7 +211,8 @@ public View approveOrDeny(@RequestParam Map approvalParameters, Set responseTypes = authorizationRequest.getResponseTypes(); authorizationRequest.setApprovalParameters(approvalParameters); - authorizationRequest = userApprovalHandler.updateAfterApproval(authorizationRequest, (Authentication) principal); + authorizationRequest = userApprovalHandler.updateAfterApproval(authorizationRequest, + (Authentication) principal); boolean approved = userApprovalHandler.isApproved(authorizationRequest, (Authentication) principal); authorizationRequest.setApproved(approved); @@ -217,10 +220,11 @@ public View approveOrDeny(@RequestParam Map approvalParameters, sessionStatus.setComplete(); throw new InvalidRequestException("Cannot approve request when no redirect URI is provided."); } - + if (!authorizationRequest.isApproved()) { - return new RedirectView(getUnsuccessfulRedirect(authorizationRequest, new UserDeniedAuthorizationException( - "User denied access"), responseTypes.contains("token")), false, true, false); + return new RedirectView(getUnsuccessfulRedirect(authorizationRequest, + new UserDeniedAuthorizationException("User denied access"), responseTypes.contains("token")), + false, true, false); } if (responseTypes.contains("token")) { @@ -254,10 +258,12 @@ private ModelAndView getImplicitGrantResponse(AuthorizationRequest authorization if (accessToken == null) { throw new UnsupportedResponseTypeException("Unsupported response type: token"); } - return new ModelAndView(new RedirectView(appendAccessToken(authorizationRequest, accessToken), false, true, false)); + return new ModelAndView(new RedirectView(appendAccessToken(authorizationRequest, accessToken), false, true, + false)); } catch (OAuth2Exception e) { - return new ModelAndView(new RedirectView(getUnsuccessfulRedirect(authorizationRequest, e, true), false, true, false)); + return new ModelAndView(new RedirectView(getUnsuccessfulRedirect(authorizationRequest, e, true), false, + true, false)); } } @@ -270,11 +276,11 @@ private View getAuthorizationCodeResponse(AuthorizationRequest authorizationRequ return new RedirectView(getUnsuccessfulRedirect(authorizationRequest, e, false), false, true, false); } } - + private String appendAccessToken(AuthorizationRequest authorizationRequest, OAuth2AccessToken accessToken) { - - Map vars = new HashMap(); - + + Map vars = new HashMap(); + String requestedRedirect = authorizationRequest.getRedirectUri(); if (accessToken == null) { throw new InvalidRequestException("An implicit grant could not be made"); @@ -292,7 +298,7 @@ private String appendAccessToken(AuthorizationRequest authorizationRequest, OAut vars.put("access_token", accessToken.getValue()); vars.put("token_type", accessToken.getTokenType()); String state = authorizationRequest.getState(); - + if (state != null) { url.append("&state={state}"); vars.put("state", state); @@ -304,7 +310,7 @@ private String appendAccessToken(AuthorizationRequest authorizationRequest, OAut vars.put("expires_in", expires_in); } String originalScope = authorizationRequest.getRequestParameters().get(OAuth2Utils.SCOPE); - if (originalScope==null || !OAuth2Utils.parseParameterList(originalScope).equals(accessToken.getScope())) { + if (originalScope == null || !OAuth2Utils.parseParameterList(originalScope).equals(accessToken.getScope())) { url.append("&" + OAuth2Utils.SCOPE + "={scope}"); vars.put("scope", OAuth2Utils.formatParameterList(accessToken.getScope())); } @@ -325,11 +331,10 @@ private String generateCode(AuthorizationRequest authorizationRequest, Authentic throws AuthenticationException { try { - + OAuth2Request storedOAuth2Request = getOAuth2RequestFactory().createOAuth2Request(authorizationRequest); - - OAuth2Authentication combinedAuth = new OAuth2Authentication(storedOAuth2Request, - authentication); + + OAuth2Authentication combinedAuth = new OAuth2Authentication(storedOAuth2Request, authentication); String code = authorizationCodeServices.createAuthorizationCode(combinedAuth); return code; @@ -352,28 +357,15 @@ private String getSuccessfulRedirect(AuthorizationRequest authorizationRequest, throw new IllegalStateException("No authorization code found in the current request scope."); } - String requestedRedirect = authorizationRequest.getRedirectUri(); - String[] fragments = requestedRedirect.split("#"); - String state = authorizationRequest.getState(); - - StringBuilder url = new StringBuilder(fragments[0]); - if (requestedRedirect.indexOf('?') < 0) { - url.append('?'); - } - else { - url.append('&'); - } - url.append("code=").append(authorizationCode); + UriComponentsBuilder template = UriComponentsBuilder.fromUriString(authorizationRequest.getRedirectUri()); + template.queryParam("code", authorizationCode); + String state = authorizationRequest.getState(); if (state != null) { - url.append("&state=").append(state); - } - - if (fragments.length > 1) { - url.append("#" + fragments[1]); + template.queryParam("state", state); } - return url.toString(); + return template.build().encode().toUriString(); } private String getUnsuccessfulRedirect(AuthorizationRequest authorizationRequest, OAuth2Exception failure, @@ -384,46 +376,35 @@ private String getUnsuccessfulRedirect(AuthorizationRequest authorizationRequest throw new UnapprovedClientAuthenticationException("Authorization failure, and no redirect URI.", failure); } - String redirectUri = authorizationRequest.getRedirectUri(); + UriComponentsBuilder template = UriComponentsBuilder.fromUriString(authorizationRequest.getRedirectUri()); + Map query = new LinkedHashMap(); + StringBuilder values = new StringBuilder(); - // extract existing fragments if any - String[] fragments = redirectUri.split("#"); + values.append("error={error}"); + query.put("error", failure.getOAuth2ErrorCode()); - StringBuilder url = new StringBuilder(fragment ? redirectUri : fragments[0]); + values.append("&error_description={error_description}"); + query.put("error_description", failure.getMessage()); - char separator = fragment ? '#' : '?'; - if (redirectUri.indexOf(separator) < 0) { - url.append(separator); + if (authorizationRequest.getState() != null) { + values.append("&state={state}"); + query.put("state", authorizationRequest.getState()); } - else { - url.append('&'); - } - url.append("error=").append(failure.getOAuth2ErrorCode()); - try { - - url.append("&error_description=").append(URLEncoder.encode(failure.getMessage(), "UTF-8")); - if (authorizationRequest.getState() != null) { - url.append('&').append("state=").append(authorizationRequest.getState()); + if (failure.getAdditionalInformation() != null) { + for (Map.Entry additionalInfo : failure.getAdditionalInformation().entrySet()) { + values.append("&" + additionalInfo.getKey() + "={" + additionalInfo.getKey() + "}"); + query.put(additionalInfo.getKey(), additionalInfo.getValue()); } - - if (failure.getAdditionalInformation() != null) { - for (Map.Entry additionalInfo : failure.getAdditionalInformation().entrySet()) { - url.append('&').append(additionalInfo.getKey()).append('=') - .append(URLEncoder.encode(additionalInfo.getValue(), "UTF-8")); - } - } - } - catch (UnsupportedEncodingException e) { - throw new IllegalStateException(e); - } - - if (!fragment && fragments.length > 1) { - url.append("#" + fragments[1]); + + if (fragment) { + template.fragment(values.toString()); + } else { + template.query(values.toString()); } - return url.toString(); + return template.build().expand(query).encode().toUriString(); } @@ -446,7 +427,7 @@ public void setUserApprovalHandler(UserApprovalHandler userApprovalHandler) { public void setoAuth2RequestValidator(OAuth2RequestValidator oAuth2RequestValidator) { this.oAuth2RequestValidator = oAuth2RequestValidator; } - + public void setImplicitGrantService(ImplicitGrantService implicitGrantService) { this.implicitGrantService = implicitGrantService; } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java index 8b541a466..03b921782 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java @@ -144,6 +144,46 @@ public void testAuthorizationCodeWithFragment() throws Exception { assertEquals("http://anywhere.com/?code=thecode#bar", ((RedirectView) result).getUrl()); } + @Test + public void testAuthorizationCodeWithQueryParams() throws Exception { + endpoint.setAuthorizationCodeServices(new StubAuthorizationCodeServices()); + model.put("authorizationRequest", getAuthorizationRequest("foo", "http://anywhere.com/?foo=bar", null, null, Collections.singleton("code"))); + View result = endpoint.approveOrDeny( + Collections.singletonMap(OAuth2Utils.USER_OAUTH_APPROVAL, "true"), model, sessionStatus, + principal); + assertEquals("http://anywhere.com/?foo=bar&code=thecode", ((RedirectView) result).getUrl()); + } + + @Test + public void testAuthorizationCodeWithTrickyState() throws Exception { + endpoint.setAuthorizationCodeServices(new StubAuthorizationCodeServices()); + model.put("authorizationRequest", getAuthorizationRequest("foo", "http://anywhere.com/", " =?s", null, Collections.singleton("code"))); + View result = endpoint.approveOrDeny( + Collections.singletonMap(OAuth2Utils.USER_OAUTH_APPROVAL, "true"), model, sessionStatus, + principal); + assertEquals("http://anywhere.com/?code=thecode&state=%20%3D?s", ((RedirectView) result).getUrl()); + } + + @Test + public void testAuthorizationCodeWithMultipleQueryParams() throws Exception { + endpoint.setAuthorizationCodeServices(new StubAuthorizationCodeServices()); + model.put("authorizationRequest", getAuthorizationRequest("foo", "http://anywhere.com/?foo=bar&bar=foo", null, null, Collections.singleton("code"))); + View result = endpoint.approveOrDeny( + Collections.singletonMap(OAuth2Utils.USER_OAUTH_APPROVAL, "true"), model, sessionStatus, + principal); + assertEquals("http://anywhere.com/?foo=bar&bar=foo&code=thecode", ((RedirectView) result).getUrl()); + } + + @Test + public void testAuthorizationCodeWithTrickyQueryParams() throws Exception { + endpoint.setAuthorizationCodeServices(new StubAuthorizationCodeServices()); + model.put("authorizationRequest", getAuthorizationRequest("foo", "http://anywhere.com/?foo=b%20=&bar=f%20$", null, null, Collections.singleton("code"))); + View result = endpoint.approveOrDeny( + Collections.singletonMap(OAuth2Utils.USER_OAUTH_APPROVAL, "true"), model, sessionStatus, + principal); + assertEquals("http://anywhere.com/?foo=b%20%3D&bar=f%20http://anywhere.com?foo=b%20%3D&bar=f%20$&code=thecodecode=thecode", ((RedirectView) result).getUrl()); + } + @Test public void testAuthorizationCodeError() throws Exception { endpoint.setUserApprovalHandler(new UserApprovalHandler() { From 32fb5d8df1b3ab464f3b926e10b64aa6a49a52d2 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 10 Mar 2014 14:54:41 +0000 Subject: [PATCH 172/831] Rename frameworkEndpointMapping Fixes gh-158 --- .../web/configuration/AuthorizationServerConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java index 2a21d14d1..db6fc30fe 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java @@ -163,7 +163,7 @@ public WhitelabelApprovalEndpoint approvalEndpoint() { } @Bean - public FrameworkEndpointHandlerMapping endpointHandlerMapping() { + public FrameworkEndpointHandlerMapping oauth2EndpointHandlerMapping() { return new FrameworkEndpointHandlerMapping(); } From 0918c904d8818b0c76d88241a6fe21ee0337d915 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 11 Mar 2014 18:00:13 +0000 Subject: [PATCH 173/831] Support for custom headers in AccessTokenRequest --- .../client/token/AccessTokenRequest.java | 7 +++ .../token/DefaultAccessTokenRequest.java | 10 +++++ .../token/OAuth2AccessTokenSupport.java | 15 ++++++- .../AuthorizationCodeAccessTokenProvider.java | 43 +++++++++++++------ .../implicit/ImplicitAccessTokenProvider.java | 1 + 5 files changed, 62 insertions(+), 14 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/AccessTokenRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/AccessTokenRequest.java index 7993411a7..cd7ead483 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/AccessTokenRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/AccessTokenRequest.java @@ -15,6 +15,9 @@ */ package org.springframework.security.oauth2.client.token; +import java.util.List; +import java.util.Map; + import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.util.MultiValueMap; @@ -45,5 +48,9 @@ public interface AccessTokenRequest extends MultiValueMap { void setCookie(String cookie); String getCookie(); + + void setHeaders(Map> headers); + + Map> getHeaders(); } \ No newline at end of file diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/DefaultAccessTokenRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/DefaultAccessTokenRequest.java index 9e3347725..559e02e9c 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/DefaultAccessTokenRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/DefaultAccessTokenRequest.java @@ -47,6 +47,8 @@ public class DefaultAccessTokenRequest implements AccessTokenRequest, Serializab private String cookie; + private Map> headers = new LinkedMultiValueMap(); + public DefaultAccessTokenRequest() { } @@ -112,6 +114,14 @@ public void setCookie(String cookie) { public String getCookie() { return cookie; } + + public void setHeaders(Map> headers) { + this.headers = headers; + } + + public Map> getHeaders() { + return headers; + } public void setExistingToken(OAuth2AccessToken existingToken) { this.existingToken = existingToken; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/OAuth2AccessTokenSupport.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/OAuth2AccessTokenSupport.java index 24eebc549..eaf3653ed 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/OAuth2AccessTokenSupport.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/OAuth2AccessTokenSupport.java @@ -121,9 +121,20 @@ protected OAuth2AccessToken retrieveToken(AccessTokenRequest request, OAuth2Prot authenticationHandler.authenticateTokenRequest(resource, form, headers); // Opportunity to customize form and headers tokenRequestEnhancer.enhance(request, resource, form, headers); - + final AccessTokenRequest copy = request; + + final ResponseExtractor delegate = getResponseExtractor(); + ResponseExtractor extractor = new ResponseExtractor() { + @Override + public OAuth2AccessToken extractData(ClientHttpResponse response) throws IOException { + if (response.getHeaders().containsKey("Set-Cookie")) { + copy.setCookie(response.getHeaders().getFirst("Set-Cookie")); + } + return delegate.extractData(response); + } + }; return getRestTemplate().execute(getAccessTokenUri(resource, form), getHttpMethod(), - getRequestCallback(resource, form, headers), getResponseExtractor(), form.toSingleValueMap()); + getRequestCallback(resource, form, headers), extractor , form.toSingleValueMap()); } catch (OAuth2Exception oe) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProvider.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProvider.java index 7a551dfd2..866cdb2ad 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProvider.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProvider.java @@ -72,11 +72,11 @@ public class AuthorizationCodeAccessTokenProvider extends OAuth2AccessTokenSupport implements AccessTokenProvider { private StateKeyGenerator stateKeyGenerator = new DefaultStateKeyGenerator(); - + private String scopePrefix = OAuth2Utils.SCOPE_PREFIX; - + private RequestEnhancer authorizationRequestEnhancer = new DefaultRequestEnhancer(); - + /** * A custom enhancer for the authorization request * @param authorizationRequestEnhancer @@ -84,7 +84,7 @@ public class AuthorizationCodeAccessTokenProvider extends OAuth2AccessTokenSuppo public void setAuthorizationRequestEnhancer(RequestEnhancer authorizationRequestEnhancer) { this.authorizationRequestEnhancer = authorizationRequestEnhancer; } - + /** * Prefix for scope approval parameters. * @@ -116,11 +116,10 @@ public String obtainAuthorizationCode(OAuth2ProtectedResourceDetails details, Ac AuthorizationCodeResourceDetails resource = (AuthorizationCodeResourceDetails) details; - HttpHeaders headers = getHeadersForTokenRequest(request); + HttpHeaders headers = getHeadersForAuthorizationRequest(request); MultiValueMap form = new LinkedMultiValueMap(); if (request.containsKey(OAuth2Utils.USER_OAUTH_APPROVAL)) { - form.set(OAuth2Utils.USER_OAUTH_APPROVAL, - request.getFirst(OAuth2Utils.USER_OAUTH_APPROVAL)); + form.set(OAuth2Utils.USER_OAUTH_APPROVAL, request.getFirst(OAuth2Utils.USER_OAUTH_APPROVAL)); for (String scope : details.getScope()) { form.set(scopePrefix + scope, request.getFirst(OAuth2Utils.USER_OAUTH_APPROVAL)); } @@ -129,12 +128,22 @@ public String obtainAuthorizationCode(OAuth2ProtectedResourceDetails details, Ac form.putAll(getParametersForAuthorizeRequest(resource, request)); } authorizationRequestEnhancer.enhance(request, resource, form, headers); + final AccessTokenRequest copy = request; + final ResponseExtractor> delegate = getAuthorizationResponseExtractor(); + ResponseExtractor> extractor = new ResponseExtractor>() { + @Override + public ResponseEntity extractData(ClientHttpResponse response) throws IOException { + if (response.getHeaders().containsKey("Set-Cookie")) { + copy.setCookie(response.getHeaders().getFirst("Set-Cookie")); + } + return delegate.extractData(response); + } + }; // Instead of using restTemplate.exchange we use an explicit response extractor here so it can be overridden by // subclasses ResponseEntity response = getRestTemplate().execute(resource.getUserAuthorizationUri(), HttpMethod.POST, - getRequestCallback(resource, form, headers), getAuthorizationResponseExtractor(), - form.toSingleValueMap()); + getRequestCallback(resource, form, headers), extractor, form.toSingleValueMap()); if (response.getStatusCode() == HttpStatus.OK) { // Need to re-submit with approval... @@ -186,8 +195,8 @@ public OAuth2AccessToken obtainAccessToken(OAuth2ProtectedResourceDetails detail } obtainAuthorizationCode(resource, request); } - return retrieveToken(request, resource, - getParametersForTokenRequest(resource, request), getHeadersForTokenRequest(request)); + return retrieveToken(request, resource, getParametersForTokenRequest(resource, request), + getHeadersForTokenRequest(request)); } @@ -213,6 +222,15 @@ private HttpHeaders getHeadersForTokenRequest(AccessTokenRequest request) { return headers; } + private HttpHeaders getHeadersForAuthorizationRequest(AccessTokenRequest request) { + HttpHeaders headers = new HttpHeaders(); + headers.putAll(request.getHeaders()); + if (request.getCookie() != null) { + headers.set("Cookie", request.getCookie()); + } + return headers; + } + private MultiValueMap getParametersForTokenRequest(AuthorizationCodeResourceDetails resource, AccessTokenRequest request) { @@ -238,7 +256,8 @@ private MultiValueMap getParametersForTokenRequest(Authorization // Use the preserved state in preference if it is there // TODO: treat redirect URI as a special kind of state (this is a historical mini hack) redirectUri = String.valueOf(preservedState); - } else { + } + else { redirectUri = resource.getRedirectUri(request); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/implicit/ImplicitAccessTokenProvider.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/implicit/ImplicitAccessTokenProvider.java index d548bc26e..664de42d4 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/implicit/ImplicitAccessTokenProvider.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/implicit/ImplicitAccessTokenProvider.java @@ -80,6 +80,7 @@ protected ResponseExtractor getResponseExtractor() { private HttpHeaders getHeadersForTokenRequest(AccessTokenRequest request) { HttpHeaders headers = new HttpHeaders(); + headers.putAll(request.getHeaders()); if (request.getCookie() != null) { headers.set("Cookie", request.getCookie()); } From 0ecba434ba02ed544961550d035cf30918f38d97 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 12 Mar 2014 14:40:16 +0000 Subject: [PATCH 174/831] Delegate to DefaultResponseErrorHandler in OAuth2ContextSetup OAuth2 requests in tests can fail in a number of ways, and the reason a custom error handler is used in the OAuth2ContextSetup is so that errors can be asserted (e.g. from status codes) and not just blow up in the user's face. The problem with the old implementation was that the custom error handler never threw an exception, so it would cause the RestTemplate that wraps it to drop down to attempt to extract a response body, even if it has aleady been done (to construct the OAuth2Exception from the resource server), leading to a new RestClientException that essentially masks the original problem. The solution is to delegate to the DefaultResponseErrorHandler which always throws an exception as the last resort (instead of simply doing nothing). --- .../security/oauth2/client/test/OAuth2ContextSetup.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/OAuth2ContextSetup.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/OAuth2ContextSetup.java index 1d9c58454..3dad19eff 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/OAuth2ContextSetup.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/OAuth2ContextSetup.java @@ -44,7 +44,7 @@ import org.springframework.security.oauth2.client.token.DefaultAccessTokenRequest; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.util.ClassUtils; -import org.springframework.web.client.ResponseErrorHandler; +import org.springframework.web.client.DefaultResponseErrorHandler; import org.springframework.web.client.RestOperations; /** @@ -334,14 +334,11 @@ protected void prepareConnection(HttpURLConnection connection, String httpMethod connection.setInstanceFollowRedirects(false); } }); - client.setErrorHandler(new ResponseErrorHandler() { + client.setErrorHandler(new DefaultResponseErrorHandler() { // Pass errors through in response entity for status code analysis public boolean hasError(ClientHttpResponse response) throws IOException { return false; } - - public void handleError(ClientHttpResponse response) throws IOException { - } }); if (accessTokenProvider != null) { client.setAccessTokenProvider(accessTokenProvider); From 35e9dc285f01d0225e3d512d0a6f7c255a500cec Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 12 Mar 2014 16:52:18 +0000 Subject: [PATCH 175/831] Add default request matcher to ResourceServerConfiguration All resources apart from /oauth/** are protected by default. User can override by extending ResourceServerConfigurerAdapter. --- .../sparklr/config/OAuth2ServerConfig.java | 3 -- .../ResourceServerConfiguration.java | 36 ++++++++++++++++++- .../ResourceServerConfigurer.java | 24 +++++++++++-- 3 files changed, 57 insertions(+), 6 deletions(-) diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java index 30fb456dd..b358e54bc 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java @@ -37,7 +37,6 @@ import org.springframework.security.oauth2.provider.OAuth2RequestFactory; import org.springframework.security.oauth2.provider.approval.ApprovalStore; import org.springframework.security.oauth2.provider.approval.TokenApprovalStore; -import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler; import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; import org.springframework.security.oauth2.provider.token.TokenStore; @@ -58,7 +57,6 @@ protected void configure(HttpSecurity http) throws Exception { // @formatter:off http .authorizeRequests() - .expressionHandler(new OAuth2WebSecurityExpressionHandler()) .antMatchers("/photos").access("hasRole('ROLE_USER')") .antMatchers("/photos/trusted/**").access("hasRole('ROLE_USER')") .antMatchers("/photos/user/**").access("hasRole('ROLE_USER')") @@ -83,7 +81,6 @@ public void configure(HttpSecurity http) throws Exception { // @formatter:off http .authorizeRequests() - .expressionHandler(new OAuth2WebSecurityExpressionHandler()) .antMatchers("/photos").access("#oauth2.hasScope('read')") .antMatchers("/photos/trusted/**").access("#oauth2.hasScope('trust')") .antMatchers("/photos/user/**").access("#oauth2.hasScope('trust')") diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java index 31ce1f691..ffa787910 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java @@ -18,15 +18,20 @@ import java.util.Collections; import java.util.List; +import javax.servlet.http.HttpServletRequest; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity.RequestMatcherConfigurer; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configurers.OAuth2ResourceServerConfigurer; import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; +import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.web.access.AccessDeniedHandler; +import org.springframework.security.web.util.matcher.RequestMatcher; /** * @author Dave Syer @@ -51,13 +56,42 @@ public void setConfigurers(List configurers) { this.configurers = configurers; } + private static class NotOAuthRequstMatcher implements RequestMatcher { + + @Override + public boolean matches(HttpServletRequest request) { + return !getRequestPath(request).startsWith("/oauth/"); + } + + private String getRequestPath(HttpServletRequest request) { + String url = request.getServletPath(); + + if (request.getPathInfo() != null) { + url += request.getPathInfo(); + } + + return url; + } + + } + @Override protected void configure(HttpSecurity http) throws Exception { + RequestMatcherConfigurer requests = http.requestMatchers(); + requests.requestMatchers(new NotOAuthRequstMatcher()); + // @formatter:off + http + .authorizeRequests().expressionHandler(new OAuth2WebSecurityExpressionHandler()) + .and() + .exceptionHandling().accessDeniedHandler(accessDeniedHandler) + .and() + .csrf().disable(); + // @formatter:on for (ResourceServerConfigurer configurer : configurers) { configurer.configure(http); } OAuth2ResourceServerConfigurer resources = new OAuth2ResourceServerConfigurer(); - http.apply(resources).and().exceptionHandling().accessDeniedHandler(accessDeniedHandler); + http.apply(resources); for (ResourceServerConfigurer configurer : configurers) { configurer.configure(resources); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurer.java index c6d9a847c..b345a0133 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurer.java @@ -13,18 +13,38 @@ package org.springframework.security.oauth2.config.annotation.web.configuration; +import org.springframework.core.annotation.Order; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.oauth2.config.annotation.web.configurers.OAuth2ResourceServerConfigurer; - +import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler; /** + * Configurer interface for @EnableResourceServer classes. Implement this interface to adjust the access + * rules and paths that are protected by OAuth2 security. APplications may provide multiple instances of this interface, + * and in general (like with other Security configurers), if more than one configures the same preoperty, then the last + * one wins. The configurers are sorted by {@link Order} before being applied. + * * @author Dave Syer - * + * */ public interface ResourceServerConfigurer { + /** + * Add resource-server specific properties (like a resource id). + * + * @param resources configurer for the resource server + * @throws Exception if there is a problem + */ void configure(OAuth2ResourceServerConfigurer resources) throws Exception; + /** + * Use this to configure the access rules for secure resources. By default all resources not in "/oauth/**" + * are protected (but no specific rules about scopes are given, for instance). You also get an + * {@link OAuth2WebSecurityExpressionHandler} by default. + * + * @param http the current http filter configuration + * @throws Exception if there is a problem + */ void configure(HttpSecurity http) throws Exception; } From a68fda3871618ffc3b28dd41386d64b60f746ea7 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 13 Mar 2014 14:26:07 +0000 Subject: [PATCH 176/831] Add tokenServices() to OAuth2*Configurers Fixes gh-154 --- .../AuthorizationServerConfiguration.java | 4 +-- .../OAuth2AuthorizationServerConfigurer.java | 5 +++ .../OAuth2ResourceServerConfigurer.java | 6 ++++ .../provider/token/JwtTokenEnhancer.java | 4 +-- .../provider/token/JwtTokenServices.java | 2 +- ...AuthorizationServerConfigurationTests.java | 31 +++++++++++++++++++ 6 files changed, 47 insertions(+), 5 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java index db6fc30fe..d2d26c7d6 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java @@ -106,14 +106,14 @@ public AuthorizationEndpoint authorizationEndpoint() throws Exception { authorizationEndpoint.setClientDetailsService(clientDetailsService); authorizationEndpoint.setAuthorizationCodeServices(authorizationCodeServices()); authorizationEndpoint.setUserApprovalHandler(userApprovalHandler()); - authorizationEndpoint.setImplicitGrantService(getImplicitGrantService()); + authorizationEndpoint.setImplicitGrantService(implicitGrantService()); return authorizationEndpoint; } @Bean @Lazy @Scope(proxyMode = ScopedProxyMode.INTERFACES) - public ImplicitGrantService getImplicitGrantService() throws Exception { + public ImplicitGrantService implicitGrantService() throws Exception { return authorizationServerConfigurer().getImplicitGrantService(); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java index 925a53669..c4798a78c 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java @@ -124,6 +124,11 @@ public OAuth2AuthorizationServerConfigurer tokenStore(TokenStore tokenStore) { return this; } + public OAuth2AuthorizationServerConfigurer tokenService(AuthorizationServerTokenServices tokenServices) { + this.tokenServices = tokenServices; + return this; + } + public OAuth2AuthorizationServerConfigurer userApprovalHandler(UserApprovalHandler approvalHandler) { this.userApprovalHandler = approvalHandler; return this; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2ResourceServerConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2ResourceServerConfigurer.java index b759208db..85c0740a3 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2ResourceServerConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2ResourceServerConfigurer.java @@ -79,6 +79,12 @@ public OAuth2ResourceServerConfigurer tokenStore(TokenStore tokenStore) { return this; } + public OAuth2ResourceServerConfigurer tokenServices(ResourceServerTokenServices tokenServices) { + Assert.state(tokenServices != null, "ResourceServerTokenServices cannot be null"); + this.resourceTokenServices = tokenServices; + return this; + } + @Override public void init(HttpSecurity http) throws Exception { registerDefaultAuthenticationEntryPoint(http); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancer.java index 75d5c447e..3026dca8f 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancer.java @@ -148,9 +148,9 @@ protected String encode(OAuth2AccessToken accessToken, OAuth2Authentication auth } protected Map decode(String token) { - Jwt jwt = JwtHelper.decodeAndVerify(token, verifier); - String content = jwt.getClaims(); try { + Jwt jwt = JwtHelper.decodeAndVerify(token, verifier); + String content = jwt.getClaims(); @SuppressWarnings("unchecked") Map map = objectMapper.readValue(content, Map.class); return map; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenServices.java index 5c42b0b01..b9c326623 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenServices.java @@ -86,7 +86,7 @@ public void setReuseRefreshToken(boolean reuseRefreshToken) { } /** - * An access token enhancer that will be applied to a new token before it is saved in the token store. + * An access token enhancer that will be applied to a new token before it is issued. * * @param accessTokenEnhancer the access token enhancer to set */ diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java index 46fdeb2b0..80eccfd7c 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java @@ -44,6 +44,7 @@ import org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint; import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; import org.springframework.security.oauth2.provider.token.JdbcTokenStore; +import org.springframework.security.oauth2.provider.token.JwtTokenServices; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; @@ -68,6 +69,7 @@ public static List parameters() { new Object[] { BeanCreationException.class, new Class[] { AuthorizationServerUnconfigured.class } }, new Object[] { null, new Class[] { AuthorizationServerExtras.class } }, new Object[] { null, new Class[] { AuthorizationServerJdbc.class } }, + new Object[] { null, new Class[] { AuthorizationServerJwt.class } }, new Object[] { BeanCreationException.class, new Class[] { AuthorizationServerTypes.class } } // @formatter:on ); @@ -176,6 +178,35 @@ public DataSource dataSource() { } + @Configuration + @EnableWebMvcSecurity + @EnableAuthorizationServer + protected static class AuthorizationServerJwt extends AuthorizationServerConfigurerAdapter { + + @Autowired + private ApplicationContext context; + + private JwtTokenServices tokenServices = new JwtTokenServices(); + + @Override + public void configure(OAuth2AuthorizationServerConfigurer oauthServer) throws Exception { + oauthServer.tokenService(tokenServices).realm("sparklr2/client"); + } + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + // @formatter:off + clients.inMemory() + .withClient("my-trusted-client") + .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit") + .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") + .scopes("read", "write", "trust") + .accessTokenValiditySeconds(60); + // @formatter:on + } + + } + @Configuration @EnableWebMvcSecurity protected static class AuthorizationServerTypes extends AuthorizationServerConfiguration { From 797bedcbbd41d56f4768c8682ac4ffca613a323c Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 13 Mar 2014 14:47:44 +0000 Subject: [PATCH 177/831] Support refresh token by default --- .../security/oauth2/provider/token/JwtTokenServices.java | 2 +- .../security/oauth2/provider/token/JwtTokenServicesTests.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenServices.java index b9c326623..c200659d9 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenServices.java @@ -61,7 +61,7 @@ public class JwtTokenServices implements AuthorizationServerTokenServices, Resou private int accessTokenValiditySeconds = 60 * 60 * 12; // default 12 hours. - private boolean supportRefreshToken = false; + private boolean supportRefreshToken = true; private boolean reuseRefreshToken = true; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenServicesTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenServicesTests.java index c45afde09..7aca786cb 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenServicesTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenServicesTests.java @@ -59,7 +59,6 @@ public void init() throws Exception { services.setSigningKey("FOO"); services.afterPropertiesSet(); enhancer = (JwtTokenEnhancer) ReflectionTestUtils.getField(services, "jwtTokenEnhancer"); - services.setSupportRefreshToken(true); } @Test From f78c87ea15be96bf9917da6d0e70c0cdf18bb658 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 14 Mar 2014 11:49:35 +0000 Subject: [PATCH 178/831] Integrate endpoint mappings with @Configuration helpers Users can now easily change the endpoint paths from their defaults, e.g. /oauth/token->/token. --- .../AuthorizationServerConfiguration.java | 28 +++++++++++------- .../ResourceServerConfiguration.java | 24 +++++++++++++-- .../OAuth2AuthorizationServerConfigurer.java | 18 +++++++++++- .../FrameworkEndpointHandlerMapping.java | 29 ++++++++++++++----- 4 files changed, 79 insertions(+), 20 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java index d2d26c7d6..96729d263 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java @@ -61,15 +61,18 @@ public class AuthorizationServerConfiguration extends WebSecurityConfigurerAdapt @Autowired private ClientDetailsService clientDetailsService; + + @Autowired + private AuthorizationEndpoint authorizationEndpoint; @Configuration - protected static class ClientDetailsAuthenticationManagerConfiguration extends GlobalAuthenticationConfigurerAdapter { - + protected static class ClientDetailsAuthenticationManagerConfiguration extends + GlobalAuthenticationConfigurerAdapter { + } @Autowired - public void configure(ClientDetailsServiceConfigurer clientDetails) - throws Exception { + public void configure(ClientDetailsServiceConfigurer clientDetails) throws Exception { for (AuthorizationServerConfigurer configurer : configurers) { configurer.configure(clientDetails); } @@ -80,15 +83,15 @@ protected void configure(HttpSecurity http) throws Exception { OAuth2AuthorizationServerConfigurer configurer = new OAuth2AuthorizationServerConfigurer(); configurer.clientDetailsService(clientDetailsService); configure(configurer); + http.apply(configurer); + String tokenEndpointPath = oauth2EndpointHandlerMapping().getPath("/oauth/token"); // @formatter:off http .authorizeRequests() - .antMatchers("/oauth/token").fullyAuthenticated() + .antMatchers(tokenEndpointPath).fullyAuthenticated() .and() .requestMatchers() - .antMatchers("/oauth/token") - .and() - .apply(configurer); + .antMatchers(tokenEndpointPath); // @formatter:on http.setSharedObject(ClientDetailsService.class, clientDetailsService); } @@ -163,8 +166,13 @@ public WhitelabelApprovalEndpoint approvalEndpoint() { } @Bean - public FrameworkEndpointHandlerMapping oauth2EndpointHandlerMapping() { - return new FrameworkEndpointHandlerMapping(); + @Lazy + @Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) + public FrameworkEndpointHandlerMapping oauth2EndpointHandlerMapping() throws Exception { + FrameworkEndpointHandlerMapping mapping = authorizationServerConfigurer().getFrameworkEndpointHandlerMapping(); + authorizationEndpoint.setUserApprovalPage(mapping.getPath("/oauth/confirm_access")); + authorizationEndpoint.setErrorPage(mapping.getPath("/oauth/error")); + return mapping; } @Bean diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java index ffa787910..bdbcc95bf 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java @@ -27,6 +27,7 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity.RequestMatcherConfigurer; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configurers.OAuth2ResourceServerConfigurer; +import org.springframework.security.oauth2.provider.endpoint.FrameworkEndpointHandlerMapping; import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler; import org.springframework.security.oauth2.provider.token.TokenStore; @@ -44,6 +45,9 @@ public class ResourceServerConfiguration extends WebSecurityConfigurerAdapter { @Autowired private TokenStore tokenStore; + @Autowired(required = false) + private FrameworkEndpointHandlerMapping frameworkEndpointHandlerMapping; + private List configurers = Collections.emptyList(); private AccessDeniedHandler accessDeniedHandler = new OAuth2AccessDeniedHandler(); @@ -58,9 +62,21 @@ public void setConfigurers(List configurers) { private static class NotOAuthRequstMatcher implements RequestMatcher { + private FrameworkEndpointHandlerMapping mapping; + + public NotOAuthRequstMatcher(FrameworkEndpointHandlerMapping mapping) { + this.mapping = mapping; + } + @Override public boolean matches(HttpServletRequest request) { - return !getRequestPath(request).startsWith("/oauth/"); + String requestPath = getRequestPath(request); + for (String path : mapping.getPaths()) { + if (requestPath.startsWith(path)) { + return false; + } + } + return true; } private String getRequestPath(HttpServletRequest request) { @@ -78,10 +94,14 @@ private String getRequestPath(HttpServletRequest request) { @Override protected void configure(HttpSecurity http) throws Exception { RequestMatcherConfigurer requests = http.requestMatchers(); - requests.requestMatchers(new NotOAuthRequstMatcher()); + if (frameworkEndpointHandlerMapping != null) { + // Assume we are in an Authorization Server + requests.requestMatchers(new NotOAuthRequstMatcher(frameworkEndpointHandlerMapping)); + } // @formatter:off http .authorizeRequests().expressionHandler(new OAuth2WebSecurityExpressionHandler()) + .anyRequest().authenticated() .and() .exceptionHandling().accessDeniedHandler(accessDeniedHandler) .and() diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java index c4798a78c..91229e5ff 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java @@ -17,7 +17,9 @@ import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.springframework.http.MediaType; import org.springframework.security.authentication.AuthenticationManager; @@ -38,6 +40,7 @@ import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; import org.springframework.security.oauth2.provider.code.AuthorizationCodeTokenGranter; import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices; +import org.springframework.security.oauth2.provider.endpoint.FrameworkEndpointHandlerMapping; import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint; import org.springframework.security.oauth2.provider.implicit.ImplicitGrantService; @@ -95,6 +98,8 @@ public final class OAuth2AuthorizationServerConfigurer extends private String realm = "oauth2/client"; + private Map patternMap = new HashMap(); + private ClientDetailsService clientDetails() { return getBuilder().getSharedObject(ClientDetailsService.class); } @@ -139,6 +144,11 @@ public OAuth2AuthorizationServerConfigurer realm(String realm) { return this; } + public OAuth2AuthorizationServerConfigurer pathMapping(String defaultPath, String customPath) { + this.patternMap.put(defaultPath, customPath); + return this; + } + public OAuth2AuthorizationServerConfigurer authenticationEntryPoint( AuthenticationEntryPoint authenticationEntryPoint) { this.authenticationEntryPoint = authenticationEntryPoint; @@ -184,7 +194,7 @@ private void registerDefaultAuthenticationEntryPoint(HttpSecurity http) { @Override public void configure(HttpSecurity http) throws Exception { - clientCredentialsTokenEndpointFilter = new ClientCredentialsTokenEndpointFilter(); + clientCredentialsTokenEndpointFilter = new ClientCredentialsTokenEndpointFilter(getFrameworkEndpointHandlerMapping().getPath("/oauth/token")); clientCredentialsTokenEndpointFilter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class)); clientCredentialsTokenEndpointFilter = postProcess(clientCredentialsTokenEndpointFilter); @@ -301,4 +311,10 @@ private TokenGranter tokenGranter(HttpSecurity http) throws Exception { } return tokenGranter; } + + public FrameworkEndpointHandlerMapping getFrameworkEndpointHandlerMapping() { + FrameworkEndpointHandlerMapping mapping = new FrameworkEndpointHandlerMapping(); + mapping.setMappings(patternMap); + return mapping; + } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java index adcb4865c..3227b4067 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java @@ -15,6 +15,7 @@ import java.lang.reflect.Method; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -40,6 +41,8 @@ public class FrameworkEndpointHandlerMapping extends RequestMappingHandlerMappin private String approvalParameter = OAuth2Utils.USER_OAUTH_APPROVAL; + private Set paths = new HashSet(); + /** * Custom mappings for framework endpoint paths. The keys in the map are the default framework endpoint path, e.g. * "/oauth/authorize", and the values are the desired runtime paths. @@ -50,6 +53,20 @@ public void setMappings(Map patternMap) { this.mappings = patternMap; } + /** + * @return the mapping from default endpoint paths to custom ones (or the default if no customization is known) + */ + public String getPath(String defaultPath) { + if (mappings.containsKey(defaultPath)) { + return mappings.get(defaultPath); + } + return defaultPath; + } + + public Set getPaths() { + return paths ; + } + /** * The name of the request parameter that distinguishes a call to approve an authorization. Default is * {@link AuthorizationRequest#USER_OAUTH_APPROVAL}. @@ -88,17 +105,14 @@ protected RequestMappingInfo getMappingForMethod(Method method, Class handler int i = 0; for (String pattern : defaultPatterns) { - patterns[i] = pattern; - if (mappings.containsKey(pattern)) { - patterns[i] = mappings.get(pattern); - } + patterns[i] = getPath(pattern); + paths.add(pattern); i++; } PatternsRequestCondition patternsInfo = new PatternsRequestCondition(patterns); ParamsRequestCondition paramsInfo = defaultMapping.getParamsCondition(); - if (!approvalParameter.equals(OAuth2Utils.USER_OAUTH_APPROVAL) - && defaultPatterns.contains("/oauth/authorize")) { + if (!approvalParameter.equals(OAuth2Utils.USER_OAUTH_APPROVAL) && defaultPatterns.contains("/oauth/authorize")) { String[] params = new String[paramsInfo.getExpressions().size()]; Set> expressions = paramsInfo.getExpressions(); i = 0; @@ -106,7 +120,8 @@ protected RequestMappingInfo getMappingForMethod(Method method, Class handler String param = expression.toString(); if (OAuth2Utils.USER_OAUTH_APPROVAL.equals(param)) { params[i] = approvalParameter; - } else { + } + else { params[i] = param; } i++; From c824b9fa098a8738f7a12f2cc2e92dbbafb8f6b5 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 14 Mar 2014 14:27:38 +0000 Subject: [PATCH 179/831] Make form authentication for clients optional --- .../ClientCredentialsProviderTests.java | 49 ------------------ .../provider/RefreshTokenSupportTests.java | 15 +++++- .../oauth2/provider/ServerRunning.java | 22 ++++---- .../OAuth2AuthorizationServerConfigurer.java | 50 +++++++++++++------ 4 files changed, 61 insertions(+), 75 deletions(-) diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ClientCredentialsProviderTests.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ClientCredentialsProviderTests.java index a062d1f1c..d99218e9a 100644 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ClientCredentialsProviderTests.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ClientCredentialsProviderTests.java @@ -18,7 +18,6 @@ import org.springframework.security.oauth2.client.test.OAuth2ContextSetup; import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsAccessTokenProvider; import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails; -import org.springframework.security.oauth2.common.AuthenticationScheme; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.web.client.DefaultResponseErrorHandler; import org.springframework.web.client.ResponseErrorHandler; @@ -35,8 +34,6 @@ public class ClientCredentialsProviderTests { @Rule public OAuth2ContextSetup context = OAuth2ContextSetup.standard(serverRunning); - private ClientCredentialsResourceDetails resource; - private HttpHeaders responseHeaders; private HttpStatus responseStatus; @@ -51,16 +48,6 @@ public void testPostForToken() throws Exception { assertNull(token.getRefreshToken()); } - /** - * tests the basic provider - */ - @Test - @OAuth2ContextConfiguration(FormClientCredentials.class) - public void testPostForTokenWithForm() throws Exception { - OAuth2AccessToken token = context.getAccessToken(); - assertNull(token.getRefreshToken()); - } - /** * tests that the registered scopes are used as defaults */ @@ -98,34 +85,6 @@ public void handleError(ClientHttpResponse response) throws IOException { assertEquals(HttpStatus.UNAUTHORIZED, responseStatus); } - @Test - @OAuth2ContextConfiguration(resource = InvalidClientCredentials.class, initialize = false) - public void testInvalidCredentialsWithFormAuthentication() throws Exception { - resource.setClientAuthenticationScheme(AuthenticationScheme.form); - context.setAccessTokenProvider(new ClientCredentialsAccessTokenProvider() { - @Override - protected ResponseErrorHandler getResponseErrorHandler() { - return new DefaultResponseErrorHandler() { - public void handleError(ClientHttpResponse response) throws IOException { - responseHeaders = response.getHeaders(); - responseStatus = response.getStatusCode(); - } - }; - } - }); - try { - context.getAccessToken(); - fail("Expected ResourceAccessException"); - } - catch (Exception e) { - // ignore - } - // System.err.println(responseHeaders); - String header = responseHeaders.getFirst("WWW-Authenticate"); - assertTrue("Wrong header: " + header, header.contains("Form realm")); - assertEquals(HttpStatus.UNAUTHORIZED, responseStatus); - } - static class ClientCredentials extends ClientCredentialsResourceDetails { public ClientCredentials(Object target) { setClientId("my-client-with-registered-redirect"); @@ -133,14 +92,6 @@ public ClientCredentials(Object target) { setId(getClientId()); ClientCredentialsProviderTests test = (ClientCredentialsProviderTests) target; setAccessTokenUri(test.serverRunning.getUrl("/sparklr2/oauth/token")); - test.resource = this; - } - } - - static class FormClientCredentials extends ClientCredentials { - public FormClientCredentials(Object target) { - super(target); - setClientAuthenticationScheme(AuthenticationScheme.form); } } diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/RefreshTokenSupportTests.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/RefreshTokenSupportTests.java index 96298c881..bd63a1994 100644 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/RefreshTokenSupportTests.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/RefreshTokenSupportTests.java @@ -12,6 +12,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.crypto.codec.Base64; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.util.LinkedMultiValueMap; @@ -58,9 +59,10 @@ private OAuth2AccessToken refreshAccessToken(String refreshToken) { formData.add("grant_type", "refresh_token"); formData.add("client_id", "my-trusted-client"); formData.add("refresh_token", refreshToken); + HttpHeaders headers = getTokenHeaders("my-trusted-client"); @SuppressWarnings("rawtypes") - ResponseEntity response = serverRunning.postForMap("/sparklr2/oauth/token", formData); + ResponseEntity response = serverRunning.postForMap("/sparklr2/oauth/token", headers, formData); assertEquals(HttpStatus.OK, response.getStatusCode()); assertTrue("Wrong cache control: " + response.getHeaders().getFirst("Cache-Control"), response.getHeaders().getFirst("Cache-Control").contains("no-store")); @SuppressWarnings("unchecked") @@ -71,9 +73,10 @@ private OAuth2AccessToken refreshAccessToken(String refreshToken) { private OAuth2AccessToken getAccessToken(String scope, String clientId) throws Exception { MultiValueMap formData = getTokenFormData(scope, clientId); + HttpHeaders headers = getTokenHeaders(clientId); @SuppressWarnings("rawtypes") - ResponseEntity response = serverRunning.postForMap("/sparklr2/oauth/token", formData); + ResponseEntity response = serverRunning.postForMap("/sparklr2/oauth/token", headers, formData); assertEquals(HttpStatus.OK, response.getStatusCode()); assertTrue("Wrong cache control: " + response.getHeaders().getFirst("Cache-Control"), response.getHeaders().getFirst("Cache-Control").contains("no-store")); @@ -82,6 +85,14 @@ private OAuth2AccessToken getAccessToken(String scope, String clientId) throws E return accessToken; } + private HttpHeaders getTokenHeaders(String clientId) { + HttpHeaders headers = new HttpHeaders(); + if (clientId != null) { + headers.set("Authorization", "Basic " + new String(Base64.encode((clientId + ":").getBytes()))); + } + return headers ; + } + private MultiValueMap getTokenFormData(String scope, String clientId) { MultiValueMap formData = new LinkedMultiValueMap(); formData.add("grant_type", "password"); diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ServerRunning.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ServerRunning.java index 03a20984f..5a8919268 100644 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ServerRunning.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ServerRunning.java @@ -11,9 +11,11 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.http.client.HttpClient; -import org.apache.http.client.params.ClientPNames; -import org.apache.http.client.params.CookiePolicy; +import org.apache.http.client.config.CookieSpecs; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.config.RequestConfig.Builder; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.protocol.HttpContext; import org.junit.Assume; import org.junit.internal.AssumptionViolatedException; import org.junit.rules.MethodRule; @@ -59,7 +61,6 @@ * @author Dave Syer * */ -@SuppressWarnings("deprecation") public class ServerRunning implements MethodRule, RestTemplateHolder { private static Log logger = LogFactory.getLog(ServerRunning.class); @@ -309,12 +310,13 @@ public RestOperations createRestTemplate() { RestTemplate client = new RestTemplate(); client.setRequestFactory(new HttpComponentsClientHttpRequestFactory() { @Override - public HttpClient getHttpClient() { - HttpClient client = super.getHttpClient(); - client.getParams().setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, false); - client.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.IGNORE_COOKIES); - client.getParams().setBooleanParameter(ClientPNames.HANDLE_AUTHENTICATION, false); - return client; + protected HttpContext createHttpContext(HttpMethod httpMethod, URI uri) { + HttpClientContext context = HttpClientContext.create(); + Builder builder = RequestConfig.custom() + .setCookieSpec(CookieSpecs.IGNORE_COOKIES) + .setAuthenticationEnabled(false).setRedirectsEnabled(false); + context.setRequestConfig(builder.build()); + return context; } }); client.setErrorHandler(new ResponseErrorHandler() { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java index 91229e5ff..a65c98771 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java @@ -74,8 +74,6 @@ public final class OAuth2AuthorizationServerConfigurer extends private AccessDeniedHandler accessDeniedHandler = new OAuth2AccessDeniedHandler(); - private ClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilter; - private AuthorizationServerTokenServices tokenServices; private ConsumerTokenServices consumerTokenServices; @@ -100,6 +98,10 @@ public final class OAuth2AuthorizationServerConfigurer extends private Map patternMap = new HashMap(); + private FrameworkEndpointHandlerMapping frameworkEndpointHandlerMapping; + + private boolean allowFormAuthenticationForClients = false; + private ClientDetailsService clientDetails() { return getBuilder().getSharedObject(ClientDetailsService.class); } @@ -111,7 +113,7 @@ public AuthorizationServerTokenServices getTokenServices() { public TokenStore getTokenStore() { return tokenStore; } - + public ClientDetailsService getClientDetailsService() { return clientDetailsService; } @@ -124,6 +126,11 @@ public UserApprovalHandler getUserApprovalHandler() { return userApprovalHandler; } + public OAuth2AuthorizationServerConfigurer allowFormAuthenticationForClients() { + this.allowFormAuthenticationForClients = true; + return this; + } + public OAuth2AuthorizationServerConfigurer tokenStore(TokenStore tokenStore) { this.tokenStore = tokenStore; return this; @@ -194,20 +201,29 @@ private void registerDefaultAuthenticationEntryPoint(HttpSecurity http) { @Override public void configure(HttpSecurity http) throws Exception { - clientCredentialsTokenEndpointFilter = new ClientCredentialsTokenEndpointFilter(getFrameworkEndpointHandlerMapping().getPath("/oauth/token")); - clientCredentialsTokenEndpointFilter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class)); - clientCredentialsTokenEndpointFilter = postProcess(clientCredentialsTokenEndpointFilter); this.tokenGranter = tokenGranter(http); this.consumerTokenServices = consumerTokenServices(http); this.userApprovalHandler = userApprovalHandler(); - // @formatter:off - http - .addFilterBefore(clientCredentialsTokenEndpointFilter, BasicAuthenticationFilter.class) - .exceptionHandling().accessDeniedHandler(accessDeniedHandler); - // @formatter:on + // ensure this is initialized + frameworkEndpointHandlerMapping(); + if (allowFormAuthenticationForClients) { + clientCredentialsTokenEndpointFilter(http); + } + + http.exceptionHandling().accessDeniedHandler(accessDeniedHandler); + + } + private ClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilter(HttpSecurity http) { + ClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilter = new ClientCredentialsTokenEndpointFilter( + frameworkEndpointHandlerMapping().getPath("/oauth/token")); + clientCredentialsTokenEndpointFilter + .setAuthenticationManager(http.getSharedObject(AuthenticationManager.class)); + clientCredentialsTokenEndpointFilter = postProcess(clientCredentialsTokenEndpointFilter); + http.addFilterBefore(clientCredentialsTokenEndpointFilter, BasicAuthenticationFilter.class); + return clientCredentialsTokenEndpointFilter; } public ConsumerTokenServices getConsumerTokenServices() { @@ -313,8 +329,14 @@ private TokenGranter tokenGranter(HttpSecurity http) throws Exception { } public FrameworkEndpointHandlerMapping getFrameworkEndpointHandlerMapping() { - FrameworkEndpointHandlerMapping mapping = new FrameworkEndpointHandlerMapping(); - mapping.setMappings(patternMap); - return mapping; + return frameworkEndpointHandlerMapping(); + } + + private FrameworkEndpointHandlerMapping frameworkEndpointHandlerMapping() { + if (frameworkEndpointHandlerMapping == null) { + frameworkEndpointHandlerMapping = new FrameworkEndpointHandlerMapping(); + frameworkEndpointHandlerMapping.setMappings(patternMap); + } + return frameworkEndpointHandlerMapping; } } From a1a10205e34e550c005734d1e98c2f3374158ddb Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 14 Mar 2014 17:33:56 +0000 Subject: [PATCH 180/831] Fix forward: prefix on custom approval endpoints --- samples/oauth2/sparklr/pom.xml | 2 +- .../oauth2/provider/ServerRunning.java | 22 +++++++++---------- .../AuthorizationServerConfiguration.java | 12 ++++++++-- .../ResourceServerConfiguration.java | 2 +- .../endpoint/AuthorizationEndpoint.java | 5 ++--- .../provider/endpoint/TokenEndpoint.java | 3 +-- 6 files changed, 25 insertions(+), 21 deletions(-) diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 1debda092..05229b8af 100644 --- a/samples/oauth2/sparklr/pom.xml +++ b/samples/oauth2/sparklr/pom.xml @@ -192,7 +192,7 @@ org.apache.httpcomponents httpclient - 4.3.1 + 4.3.2 test diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ServerRunning.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ServerRunning.java index 5a8919268..03a20984f 100644 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ServerRunning.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ServerRunning.java @@ -11,11 +11,9 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.http.client.config.CookieSpecs; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.config.RequestConfig.Builder; -import org.apache.http.client.protocol.HttpClientContext; -import org.apache.http.protocol.HttpContext; +import org.apache.http.client.HttpClient; +import org.apache.http.client.params.ClientPNames; +import org.apache.http.client.params.CookiePolicy; import org.junit.Assume; import org.junit.internal.AssumptionViolatedException; import org.junit.rules.MethodRule; @@ -61,6 +59,7 @@ * @author Dave Syer * */ +@SuppressWarnings("deprecation") public class ServerRunning implements MethodRule, RestTemplateHolder { private static Log logger = LogFactory.getLog(ServerRunning.class); @@ -310,13 +309,12 @@ public RestOperations createRestTemplate() { RestTemplate client = new RestTemplate(); client.setRequestFactory(new HttpComponentsClientHttpRequestFactory() { @Override - protected HttpContext createHttpContext(HttpMethod httpMethod, URI uri) { - HttpClientContext context = HttpClientContext.create(); - Builder builder = RequestConfig.custom() - .setCookieSpec(CookieSpecs.IGNORE_COOKIES) - .setAuthenticationEnabled(false).setRedirectsEnabled(false); - context.setRequestConfig(builder.build()); - return context; + public HttpClient getHttpClient() { + HttpClient client = super.getHttpClient(); + client.getParams().setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, false); + client.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.IGNORE_COOKIES); + client.getParams().setBooleanParameter(ClientPNames.HANDLE_AUTHENTICATION, false); + return client; } }); client.setErrorHandler(new ResponseErrorHandler() { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java index 96729d263..9a05bbbc7 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java @@ -170,11 +170,19 @@ public WhitelabelApprovalEndpoint approvalEndpoint() { @Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) public FrameworkEndpointHandlerMapping oauth2EndpointHandlerMapping() throws Exception { FrameworkEndpointHandlerMapping mapping = authorizationServerConfigurer().getFrameworkEndpointHandlerMapping(); - authorizationEndpoint.setUserApprovalPage(mapping.getPath("/oauth/confirm_access")); - authorizationEndpoint.setErrorPage(mapping.getPath("/oauth/error")); + authorizationEndpoint.setUserApprovalPage(extractPath(mapping, "/oauth/confirm_access")); + authorizationEndpoint.setErrorPage(extractPath(mapping, "/oauth/error")); return mapping; } + private String extractPath(FrameworkEndpointHandlerMapping mapping, String page) { + String path = mapping.getPath(page); + if (path.contains(":")) { + return path; + } + return "forward:" + path; + } + @Bean @Lazy @Scope(proxyMode = ScopedProxyMode.INTERFACES) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java index bdbcc95bf..493ccca86 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java @@ -101,7 +101,7 @@ protected void configure(HttpSecurity http) throws Exception { // @formatter:off http .authorizeRequests().expressionHandler(new OAuth2WebSecurityExpressionHandler()) - .anyRequest().authenticated() + // .anyRequest().authenticated() .and() .exceptionHandling().accessDeniedHandler(accessDeniedHandler) .and() diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java index 99550d4b2..a202e6495 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java @@ -87,7 +87,6 @@ */ @FrameworkEndpoint @SessionAttributes("authorizationRequest") -@RequestMapping(value = "/oauth/authorize") public class AuthorizationEndpoint extends AbstractEndpoint { private AuthorizationCodeServices authorizationCodeServices = new InMemoryAuthorizationCodeServices(); @@ -114,7 +113,7 @@ public void setErrorPage(String errorPage) { this.errorPage = errorPage; } - @RequestMapping + @RequestMapping(value = "/oauth/authorize") public ModelAndView authorize(Map model, @RequestParam Map parameters, SessionStatus sessionStatus, Principal principal) { @@ -190,7 +189,7 @@ public ModelAndView authorize(Map model, @RequestParam } - @RequestMapping(method = RequestMethod.POST, params = OAuth2Utils.USER_OAUTH_APPROVAL) + @RequestMapping(value = "/oauth/authorize", method = RequestMethod.POST, params = OAuth2Utils.USER_OAUTH_APPROVAL) public View approveOrDeny(@RequestParam Map approvalParameters, Map model, SessionStatus sessionStatus, Principal principal) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java index 9442a15ac..34847f66a 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java @@ -62,12 +62,11 @@ * */ @FrameworkEndpoint -@RequestMapping(value = "/oauth/token") public class TokenEndpoint extends AbstractEndpoint { private OAuth2RequestValidator oAuth2RequestValidator = new DefaultOAuth2RequestValidator(); - @RequestMapping + @RequestMapping(value = "/oauth/token") public ResponseEntity getAccessToken(Principal principal, @RequestParam Map parameters) { From 9bb1e12f41f50c283ff13159a8b5d3efe80aa386 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 14 Mar 2014 18:24:14 +0000 Subject: [PATCH 181/831] Fix integration tests (not working in mvn yet) --- pom.xml | 9 +++++++-- samples/oauth2/sparklr/pom.xml | 8 ++++---- .../sparklr/config/OAuth2ServerConfig.java | 14 +++++++------- samples/oauth2/tonr/pom.xml | 8 ++++---- .../configuration/ResourceServerConfiguration.java | 8 +++++--- .../OAuth2ResourceServerConfigurer.java | 2 -- 6 files changed, 27 insertions(+), 22 deletions(-) diff --git a/pom.xml b/pom.xml index 982cff903..965b0641c 100644 --- a/pom.xml +++ b/pom.xml @@ -16,8 +16,8 @@ UTF-8 - 3.2.7.RELEASE - 3.2.1.RELEASE + 3.2.8.RELEASE + 3.2.2.RELEASE [3.2.0,5.0.0) [3.2.1,5.0.0) 1.6 @@ -275,6 +275,11 @@ + org.apache.tomcat.maven + tomcat7-maven-plugin + 2.2 + + maven-jar-plugin diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 05229b8af..0ef4adb91 100644 --- a/samples/oauth2/sparklr/pom.xml +++ b/samples/oauth2/sparklr/pom.xml @@ -41,10 +41,9 @@ - org.codehaus.mojo - tomcat-maven-plugin - 1.1 - + org.apache.tomcat.maven + tomcat7-maven-plugin + start-tomcat pre-integration-test @@ -52,6 +51,7 @@ run + /sparklr2 true diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java index b358e54bc..07bbf40c6 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java @@ -56,13 +56,13 @@ protected static class UiResourceConfiguration extends WebSecurityConfigurerAdap protected void configure(HttpSecurity http) throws Exception { // @formatter:off http - .authorizeRequests() + .requestMatchers().antMatchers("/photos/**") + .and() + .authorizeRequests() .antMatchers("/photos").access("hasRole('ROLE_USER')") .antMatchers("/photos/trusted/**").access("hasRole('ROLE_USER')") .antMatchers("/photos/user/**").access("hasRole('ROLE_USER')") - .antMatchers("/photos/**").access("hasRole('ROLE_USER')") - .and() - .requestMatchers().antMatchers("/photos/**"); + .antMatchers("/photos/**").access("hasRole('ROLE_USER')"); // @formatter:on } } @@ -80,6 +80,8 @@ public void configure(OAuth2ResourceServerConfigurer resources) { public void configure(HttpSecurity http) throws Exception { // @formatter:off http + .requestMatchers().antMatchers("/photos/**", "/oauth/users/**", "/oauth/clients/**") + .and() .authorizeRequests() .antMatchers("/photos").access("#oauth2.hasScope('read')") .antMatchers("/photos/trusted/**").access("#oauth2.hasScope('trust')") @@ -90,9 +92,7 @@ public void configure(HttpSecurity http) throws Exception { .regexMatchers(HttpMethod.GET, "/oauth/users/.*") .access("#oauth2.clientHasRole('ROLE_CLIENT') and (hasRole('ROLE_USER') or #oauth2.isClient()) and #oauth2.hasScope('read')") .regexMatchers(HttpMethod.GET, "/oauth/clients/.*") - .access("#oauth2.clientHasRole('ROLE_CLIENT') and #oauth2.isClient() and #oauth2.hasScope('read')") - .and() - .requestMatchers().antMatchers("/photos/**", "/oauth/users/**", "/oauth/clients/**"); + .access("#oauth2.clientHasRole('ROLE_CLIENT') and #oauth2.isClient() and #oauth2.hasScope('read')"); // @formatter:on } diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 28e74a729..feff66793 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -41,9 +41,8 @@ - org.codehaus.mojo - tomcat-maven-plugin - 1.1 + org.apache.tomcat.maven + tomcat7-maven-plugin start-tomcat @@ -53,8 +52,9 @@ true + true - + diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java index 493ccca86..1eeec426b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java @@ -100,16 +100,18 @@ protected void configure(HttpSecurity http) throws Exception { } // @formatter:off http - .authorizeRequests().expressionHandler(new OAuth2WebSecurityExpressionHandler()) - // .anyRequest().authenticated() - .and() .exceptionHandling().accessDeniedHandler(accessDeniedHandler) .and() .csrf().disable(); // @formatter:on for (ResourceServerConfigurer configurer : configurers) { + // Delegates can add authorizeRequests() here configurer.configure(http); } + // Add anyRequest() last as a fall back + http.authorizeRequests().anyRequest().authenticated(); + // And set the default expression handler in case one isn't explicit elsewhere + http.authorizeRequests().expressionHandler(new OAuth2WebSecurityExpressionHandler()); OAuth2ResourceServerConfigurer resources = new OAuth2ResourceServerConfigurer(); http.apply(resources); for (ResourceServerConfigurer configurer : configurers) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2ResourceServerConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2ResourceServerConfigurer.java index 85c0740a3..3deb163e4 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2ResourceServerConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2ResourceServerConfigurer.java @@ -115,8 +115,6 @@ public OAuth2ResourceServerConfigurer resourceId(String resourceId) { return this; } - - @Override public void configure(HttpSecurity http) throws Exception { From c837bdaab697a46baeaf545cdc486ecfe0c109f3 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Sat, 15 Mar 2014 12:08:14 +0000 Subject: [PATCH 182/831] Fix tonr integration test in Maven --- samples/oauth2/tonr/pom.xml | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index feff66793..de384531c 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -1,4 +1,5 @@ - + 4.0.0 @@ -41,8 +42,8 @@ - org.apache.tomcat.maven - tomcat7-maven-plugin + org.apache.tomcat.maven + tomcat7-maven-plugin start-tomcat @@ -52,22 +53,23 @@ true - true + true + + + /sparklr2 + ${pom.groupId} + sparklr2 + ${pom.version} + war + true + + - + - - - ${pom.groupId} - sparklr2 - ${pom.version} - war - tomcat - - From 2717e7fae7464ed976f1d75caa091d7796ff448b Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Sat, 15 Mar 2014 12:32:13 +0000 Subject: [PATCH 183/831] Change logic of resource server fallback access rule Spring Security keeps access rules in a map from request mapping to rule, so if the user has already added an anyRequest().access(...) it would have been overwritten by the framework before this change. Ideally we would have an API from Spring Security to interrogate existing mappings but in the absence of that, this seems like the best compromise. --- .../web/configuration/ResourceServerConfiguration.java | 7 +++++-- .../expression/OAuth2SecurityExpressionMethods.java | 9 +++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java index 1eeec426b..01661c782 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java @@ -108,8 +108,11 @@ protected void configure(HttpSecurity http) throws Exception { // Delegates can add authorizeRequests() here configurer.configure(http); } - // Add anyRequest() last as a fall back - http.authorizeRequests().anyRequest().authenticated(); + if (configurers.isEmpty()) { + // Add anyRequest() last as a fall back. Spring Security would replace an existing anyRequest() matcher + // with this one, so to avoid that we only add it if the user hasn't configured anything. + http.authorizeRequests().anyRequest().authenticated(); + } // And set the default expression handler in case one isn't explicit elsewhere http.authorizeRequests().expressionHandler(new OAuth2WebSecurityExpressionHandler()); OAuth2ResourceServerConfigurer resources = new OAuth2ResourceServerConfigurer(); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethods.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethods.java index 0307c5066..d9bb325a6 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethods.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethods.java @@ -159,6 +159,15 @@ public boolean denyOAuthClient() { return !OAuth2ExpressionUtils.isOAuth(authentication); } + /** + * Permit access to oauth requests, so used for example to only allow machine clients to access a resource. + * + * @return true if the current authentication is not an OAuth2 type + */ + public boolean isOAuth() { + return OAuth2ExpressionUtils.isOAuth(authentication); + } + /** * Check if the current authentication is acting on behalf of an authenticated user. * From 769d61431e1517f242f9843ea20f671504791223 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Sat, 15 Mar 2014 12:45:37 +0000 Subject: [PATCH 184/831] Updgrade Jackson to 2.3.1 --- spring-security-oauth2/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 3542e674a..cd0f1acde 100644 --- a/spring-security-oauth2/pom.xml +++ b/spring-security-oauth2/pom.xml @@ -14,8 +14,8 @@ 1.9.2 - 2.1.1 - 1.0.0.RELEASE + 2.3.1 + 1.0.1.RELEASE From f8691a9c4073c5612d17bf4872c1bca506f59bcf Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Sat, 15 Mar 2014 12:49:26 +0000 Subject: [PATCH 185/831] [maven-release-plugin] prepare release 2.0.0.M4 --- pom.xml | 4 ++-- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 5 ++--- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- 8 files changed, 10 insertions(+), 11 deletions(-) diff --git a/pom.xml b/pom.xml index 965b0641c..bc6ccc51c 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.0.BUILD-SNAPSHOT + 2.0.0.M4 http://static.springframework.org/spring-security/oauth @@ -27,7 +27,7 @@ http://github.com/SpringSource/spring-security-oauth scm:git:git://github.com/SpringSource/spring-security-oauth.git scm:git:ssh://git@github.com/SpringSource/spring-security-oauth.git - HEAD + 2.0.0.M4 JIRA diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index 4ca71dec4..e8137ad64 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.0.BUILD-SNAPSHOT + 2.0.0.M4 ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index 439d42eca..c2596809a 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.0.BUILD-SNAPSHOT + 2.0.0.M4 ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 0ef4adb91..8372949ff 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.0.BUILD-SNAPSHOT + 2.0.0.M4 ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index de384531c..8d84f47fe 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -1,12 +1,11 @@ - + 4.0.0 org.springframework.security.oauth spring-security-oauth-parent - 2.0.0.BUILD-SNAPSHOT + 2.0.0.M4 ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index d88a907a1..3b39d7e1b 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.0.BUILD-SNAPSHOT + 2.0.0.M4 spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index e2e00bca1..29c21cafd 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.0.BUILD-SNAPSHOT + 2.0.0.M4 spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index cd0f1acde..b3f4a63c1 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.0.BUILD-SNAPSHOT + 2.0.0.M4 spring-security-oauth2 From cdf91fe013171c991e91e963ecc727c7a8753b86 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Sat, 15 Mar 2014 12:49:31 +0000 Subject: [PATCH 186/831] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index bc6ccc51c..965b0641c 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.0.M4 + 2.0.0.BUILD-SNAPSHOT http://static.springframework.org/spring-security/oauth @@ -27,7 +27,7 @@ http://github.com/SpringSource/spring-security-oauth scm:git:git://github.com/SpringSource/spring-security-oauth.git scm:git:ssh://git@github.com/SpringSource/spring-security-oauth.git - 2.0.0.M4 + HEAD JIRA diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index e8137ad64..4ca71dec4 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.0.M4 + 2.0.0.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index c2596809a..439d42eca 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.0.M4 + 2.0.0.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 8372949ff..0ef4adb91 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.0.M4 + 2.0.0.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 8d84f47fe..b69b0ca7b 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.0.M4 + 2.0.0.BUILD-SNAPSHOT ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index 3b39d7e1b..d88a907a1 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.0.M4 + 2.0.0.BUILD-SNAPSHOT spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index 29c21cafd..e2e00bca1 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.0.M4 + 2.0.0.BUILD-SNAPSHOT spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index b3f4a63c1..cd0f1acde 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.0.M4 + 2.0.0.BUILD-SNAPSHOT spring-security-oauth2 From 22b4be814443543957177535961ae8e227bc5576 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 17 Mar 2014 11:24:20 +0000 Subject: [PATCH 187/831] Allow additional customizations of authentication and request processing Several changes here: 1. Allows explicit injection of an AuthenticationManager into a Resource Server 2. Allows aligning of user roles with scopes via flag in DefaultOAuth2RequestFactory 3. Allows user to inject OAuth2Request{Factory,Validator} 4. Re-org of top-level provider package to put concrete implementations of some interfaces in sub-packages. Fixes gh-161 --- .../oauth/examples/config/SecurityConfig.java | 8 - .../client/http/OAuth2ErrorHandler.java | 2 + .../util/DefaultSecurityContextAccessor.java | 60 ++++++++ .../common/util/JsonDateDeserializer.java | 4 +- .../common/util/JsonDateSerializer.java | 6 +- .../common/util/SecurityContextAccessor.java | 38 +++++ .../builders/ClientDetailsServiceBuilder.java | 2 +- .../InMemoryClientDetailsServiceBuilder.java | 2 +- .../JdbcClientDetailsServiceBuilder.java | 2 +- .../AuthorizationServerConfiguration.java | 12 ++ .../OAuth2AuthorizationServerConfigurer.java | 37 ++++- .../OAuth2ResourceServerConfigurer.java | 15 ++ ...thorizationServerBeanDefinitionParser.java | 4 +- ...entDetailsServiceBeanDefinitionParser.java | 4 +- .../oauth2/provider/SaltedClientSecret.java | 14 -- .../{ => client}/BaseClientDetails.java | 23 ++- .../InMemoryClientDetailsService.java | 5 +- .../JdbcClientDetailsService.java | 7 +- .../provider/endpoint/AbstractEndpoint.java | 2 +- .../endpoint/AuthorizationEndpoint.java | 10 +- .../provider/endpoint/TokenEndpoint.java | 10 +- .../endpoint/WhitelabelApprovalEndpoint.java | 16 +- .../DefaultOAuth2RequestFactory.java | 86 +++++++++-- .../DefaultOAuth2RequestValidator.java | 10 +- .../provider/token/JwtTokenEnhancer.java | 2 +- .../ResourceServerConfigurationTests.java | 2 +- .../DefaultAuthorizationRequestTests.java | 143 ------------------ ...ApprovalStoreUserApprovalHandlerTests.java | 6 +- .../TokenStoreUserApprovalHandlerTests.java | 2 +- .../{ => client}/BaseClientDetailsTests.java | 3 +- .../JdbcClientDetailsServiceTests.java | 7 +- .../AuthorizationCodeTokenGranterTests.java | 4 +- .../code/SubdomainRedirectResolverTests.java | 2 +- .../endpoint/AuthorizationEndpointTests.java | 11 +- .../DefaultRedirectResolverTests.java | 2 +- .../ExactMatchRedirectResolverTests.java | 2 +- ...okenEndpointAuthenticationFilterTests.java | 4 +- .../provider/endpoint/TokenEndpointTests.java | 3 +- .../WhitelabelApprovalEndpointTests.java | 2 +- ...2MethodSecurityExpressionHandlerTests.java | 2 +- .../OAuth2SecurityExpressionMethodsTests.java | 2 +- ...uth2WebSecurityExpressionHandlerTests.java | 2 +- .../InMemoryImplicitGrantServiceTests.java | 2 +- ...esourceOwnerPasswordTokenGranterTests.java | 4 +- ...faultAuthorizationRequestManagerTests.java | 43 +++++- .../DefaultOAuth2RequestValidatorTests.java | 79 ++++++++++ .../AbstractTestDefaultTokenServices.java | 2 +- ...DefaultTokenServicesWithInMemoryTests.java | 2 +- .../provider/token/JwtTokenServicesTests.java | 2 +- .../provider/vote/ClientScopeVoterTests.java | 4 +- .../xml/authorization-server-extras.xml | 4 +- 51 files changed, 462 insertions(+), 260 deletions(-) create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/DefaultSecurityContextAccessor.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/SecurityContextAccessor.java delete mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/SaltedClientSecret.java rename spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/{ => client}/BaseClientDetails.java (95%) rename spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/{ => client}/InMemoryClientDetailsService.java (84%) rename spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/{ => client}/JdbcClientDetailsService.java (95%) rename spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/{ => request}/DefaultOAuth2RequestFactory.java (60%) rename spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/{ => request}/DefaultOAuth2RequestValidator.java (66%) delete mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequestTests.java rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/{ => client}/BaseClientDetailsTests.java (97%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/{ => client}/JdbcClientDetailsServiceTests.java (96%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/{ => request}/DefaultAuthorizationRequestManagerTests.java (51%) create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/request/DefaultOAuth2RequestValidatorTests.java diff --git a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/SecurityConfig.java b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/SecurityConfig.java index 6d545e62f..6e2b3c5fe 100644 --- a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/SecurityConfig.java +++ b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/SecurityConfig.java @@ -1,24 +1,16 @@ package org.springframework.security.oauth.examples.config; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter; @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { - @Bean - public OAuth2ClientContextFilter oauth2ClientFilter() { - OAuth2ClientContextFilter filter = new OAuth2ClientContextFilter(); - return filter; - } - @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().withUser("marissa").password("wombat").roles("USER").and().withUser("sam") diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandler.java index f1aa8352e..ebf17fd6f 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandler.java @@ -96,6 +96,8 @@ public synchronized InputStream getBody() throws IOException { InputStream bodyStream = response.getBody(); if (bodyStream != null) { lazyBody = FileCopyUtils.copyToByteArray(bodyStream); + } else { + lazyBody = new byte[0]; } } return new ByteArrayInputStream(lazyBody); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/DefaultSecurityContextAccessor.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/DefaultSecurityContextAccessor.java new file mode 100644 index 000000000..d53cea568 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/DefaultSecurityContextAccessor.java @@ -0,0 +1,60 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.springframework.security.oauth2.common.util; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.oauth2.provider.OAuth2Authentication; + +/** + * Strategy for accessing useful information about the current security context. + * + * @author Dave Syer + * + */ +public class DefaultSecurityContextAccessor implements SecurityContextAccessor { + + @Override + public boolean isUser() { + Authentication authentication = getUserAuthentication(); + return authentication != null; + } + + @Override + public Set getAuthorities() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + if (authentication == null) { + return Collections.emptySet(); + } + return Collections.unmodifiableSet(new HashSet(authentication.getAuthorities())); + } + + private Authentication getUserAuthentication() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + if (authentication == null) { + return null; + } + if (authentication instanceof OAuth2Authentication) { + OAuth2Authentication oauth = (OAuth2Authentication) authentication; + return oauth.getUserAuthentication(); + } + return authentication; + } + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JsonDateDeserializer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JsonDateDeserializer.java index 81a614334..c17125c7d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JsonDateDeserializer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JsonDateDeserializer.java @@ -36,7 +36,9 @@ public class JsonDateDeserializer extends JsonDeserializer { @Override public Date deserialize(JsonParser parser, DeserializationContext context) throws IOException, JsonProcessingException { try { - return dateFormat.parse(parser.getText()); + synchronized (dateFormat) { + return dateFormat.parse(parser.getText()); + } } catch (ParseException e) { throw new JsonParseException("Could not parse date", parser.getCurrentLocation(), e); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JsonDateSerializer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JsonDateSerializer.java index 41843ffc2..d4df5c793 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JsonDateSerializer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JsonDateSerializer.java @@ -34,8 +34,10 @@ public class JsonDateSerializer extends JsonSerializer { @Override public void serialize(Date date, JsonGenerator generator, SerializerProvider provider) throws IOException, JsonProcessingException { - String formatted = dateFormat.format(date); - generator.writeString(formatted); + synchronized (dateFormat) { + String formatted = dateFormat.format(date); + generator.writeString(formatted); + } } } \ No newline at end of file diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/SecurityContextAccessor.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/SecurityContextAccessor.java new file mode 100644 index 000000000..5c0a885c0 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/SecurityContextAccessor.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.springframework.security.oauth2.common.util; + +import java.util.Set; + +import org.springframework.security.core.GrantedAuthority; + +/** + * Strategy for accessing useful information about the current security context. + * + * @author Dave Syer + * + */ +public interface SecurityContextAccessor { + + /** + * @return true if the current context represents a user + */ + boolean isUser(); + + /** + * Get the current granted authorities (never null) + */ + Set getAuthorities(); + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java index 8c400f410..91e229e10 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java @@ -25,9 +25,9 @@ import org.springframework.security.config.annotation.SecurityBuilder; import org.springframework.security.config.annotation.SecurityConfigurerAdapter; import org.springframework.security.core.authority.AuthorityUtils; -import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.client.BaseClientDetails; /** * @author Dave Syer diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/InMemoryClientDetailsServiceBuilder.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/InMemoryClientDetailsServiceBuilder.java index ffb58e7b7..da19dde33 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/InMemoryClientDetailsServiceBuilder.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/InMemoryClientDetailsServiceBuilder.java @@ -20,7 +20,7 @@ import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; -import org.springframework.security.oauth2.provider.InMemoryClientDetailsService; +import org.springframework.security.oauth2.provider.client.InMemoryClientDetailsService; /** * @author Dave Syer diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/JdbcClientDetailsServiceBuilder.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/JdbcClientDetailsServiceBuilder.java index 455f67f91..6458b0a58 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/JdbcClientDetailsServiceBuilder.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/JdbcClientDetailsServiceBuilder.java @@ -22,7 +22,7 @@ import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; -import org.springframework.security.oauth2.provider.JdbcClientDetailsService; +import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService; import org.springframework.util.Assert; /** diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java index 9a05bbbc7..01937cd25 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java @@ -34,6 +34,7 @@ import org.springframework.security.oauth2.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer; import org.springframework.security.oauth2.provider.ClientDetailsService; 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.approval.UserApprovalHandler; import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; @@ -108,6 +109,8 @@ public AuthorizationEndpoint authorizationEndpoint() throws Exception { authorizationEndpoint.setTokenGranter(tokenGranter()); authorizationEndpoint.setClientDetailsService(clientDetailsService); authorizationEndpoint.setAuthorizationCodeServices(authorizationCodeServices()); + authorizationEndpoint.setOAuth2RequestFactory(oauth2RequestFactory()); + authorizationEndpoint.setOAuth2RequestValidator(oauth2RequestValidator()); authorizationEndpoint.setUserApprovalHandler(userApprovalHandler()); authorizationEndpoint.setImplicitGrantService(implicitGrantService()); return authorizationEndpoint; @@ -132,6 +135,8 @@ public TokenEndpoint tokenEndpoint() throws Exception { TokenEndpoint tokenEndpoint = new TokenEndpoint(); tokenEndpoint.setClientDetailsService(clientDetailsService); tokenEndpoint.setTokenGranter(tokenGranter()); + tokenEndpoint.setOAuth2RequestFactory(oauth2RequestFactory()); + tokenEndpoint.setOAuth2RequestValidator(oauth2RequestValidator()); return tokenEndpoint; } @@ -142,6 +147,13 @@ public OAuth2RequestFactory oauth2RequestFactory() throws Exception { return authorizationServerConfigurer().getOAuth2RequestFactory(); } + @Bean + @Lazy + @Scope(proxyMode = ScopedProxyMode.INTERFACES) + public OAuth2RequestValidator oauth2RequestValidator() throws Exception { + return authorizationServerConfigurer().getOAuth2RequestValidator(); + } + @Bean @Lazy @Scope(proxyMode = ScopedProxyMode.INTERFACES) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java index a65c98771..685bd945b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java @@ -28,15 +28,15 @@ import org.springframework.security.config.annotation.web.configurers.ExceptionHandlingConfigurer; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.CompositeTokenGranter; -import org.springframework.security.oauth2.provider.DefaultOAuth2RequestFactory; -import org.springframework.security.oauth2.provider.InMemoryClientDetailsService; 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.approval.TokenStoreUserApprovalHandler; import org.springframework.security.oauth2.provider.approval.UserApprovalHandler; import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter; import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenGranter; import org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService; +import org.springframework.security.oauth2.provider.client.InMemoryClientDetailsService; import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; import org.springframework.security.oauth2.provider.code.AuthorizationCodeTokenGranter; import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices; @@ -48,6 +48,8 @@ import org.springframework.security.oauth2.provider.implicit.InMemoryImplicitGrantService; 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.AuthorizationServerTokenServices; import org.springframework.security.oauth2.provider.token.ConsumerTokenServices; import org.springframework.security.oauth2.provider.token.DefaultTokenServices; @@ -88,6 +90,8 @@ public final class OAuth2AuthorizationServerConfigurer extends private OAuth2RequestFactory requestFactory; + private OAuth2RequestValidator requestValidator; + private UserApprovalHandler userApprovalHandler; private AuthenticationManager authenticationManager; @@ -122,6 +126,10 @@ public OAuth2RequestFactory getOAuth2RequestFactory() { return requestFactory; } + public OAuth2RequestValidator getOAuth2RequestValidator() { + return requestValidator; + } + public UserApprovalHandler getUserApprovalHandler() { return userApprovalHandler; } @@ -172,6 +180,16 @@ public OAuth2AuthorizationServerConfigurer clientDetailsService(ClientDetailsSer return this; } + public OAuth2AuthorizationServerConfigurer requestFactory(OAuth2RequestFactory requestFactory) { + this.requestFactory = requestFactory; + return this; + } + + public OAuth2AuthorizationServerConfigurer requestValidator(OAuth2RequestValidator requestValidator) { + this.requestValidator = requestValidator; + return this; + } + @Override public void init(HttpSecurity http) throws Exception { registerDefaultAuthenticationEntryPoint(http); @@ -204,13 +222,14 @@ public void configure(HttpSecurity http) throws Exception { this.tokenGranter = tokenGranter(http); this.consumerTokenServices = consumerTokenServices(http); - this.userApprovalHandler = userApprovalHandler(); + this.userApprovalHandler = userApprovalHandler(http); // ensure this is initialized frameworkEndpointHandlerMapping(); if (allowFormAuthenticationForClients) { clientCredentialsTokenEndpointFilter(http); } + requestValidator(http); http.exceptionHandling().accessDeniedHandler(accessDeniedHandler); @@ -270,12 +289,12 @@ private ClientDetailsService clientDetailsService() { return this.clientDetailsService; } - private UserApprovalHandler userApprovalHandler() { + private UserApprovalHandler userApprovalHandler(HttpSecurity http) { if (userApprovalHandler == null) { TokenStoreUserApprovalHandler userApprovalHandler = new TokenStoreUserApprovalHandler(); userApprovalHandler.setTokenStore(tokenStore()); userApprovalHandler.setClientDetailsService(clientDetails()); - userApprovalHandler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService())); + userApprovalHandler.setRequestFactory(requestFactory(http)); this.userApprovalHandler = userApprovalHandler; } return this.userApprovalHandler; @@ -300,6 +319,14 @@ private OAuth2RequestFactory requestFactory(HttpSecurity http) { return requestFactory; } + private OAuth2RequestValidator requestValidator(HttpSecurity http) { + if (requestValidator != null) { + return requestValidator; + } + requestValidator = new DefaultOAuth2RequestValidator(); + return requestValidator; + } + public TokenGranter getTokenGranter() { return tokenGranter; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2ResourceServerConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2ResourceServerConfigurer.java index 3deb163e4..cd7a3cb06 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2ResourceServerConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2ResourceServerConfigurer.java @@ -57,6 +57,8 @@ public final class OAuth2ResourceServerConfigurer extends private OAuth2AuthenticationProcessingFilter resourcesServerFilter; + private AuthenticationManager authenticationManager; + private ResourceServerTokenServices resourceTokenServices; private TokenStore tokenStore = new InMemoryTokenStore(); @@ -79,6 +81,12 @@ public OAuth2ResourceServerConfigurer tokenStore(TokenStore tokenStore) { return this; } + public OAuth2ResourceServerConfigurer authenticationManager(AuthenticationManager authenticationManager) { + Assert.state(authenticationManager != null, "AuthenticationManager cannot be null"); + this.authenticationManager = authenticationManager; + return this; + } + public OAuth2ResourceServerConfigurer tokenServices(ResourceServerTokenServices tokenServices) { Assert.state(tokenServices != null, "ResourceServerTokenServices cannot be null"); this.resourceTokenServices = tokenServices; @@ -134,6 +142,13 @@ public void configure(HttpSecurity http) throws Exception { private AuthenticationManager oauthAuthenticationManager(HttpSecurity http) { OAuth2AuthenticationManager oauthAuthenticationManager = new OAuth2AuthenticationManager(); + if (authenticationManager!=null) { + if (authenticationManager instanceof OAuth2AuthenticationManager) { + oauthAuthenticationManager = (OAuth2AuthenticationManager) authenticationManager; + } else { + return authenticationManager; + } + } oauthAuthenticationManager.setResourceId(resourceId); oauthAuthenticationManager.setTokenServices(resourceTokenServices(http)); return oauthAuthenticationManager; 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 2455b32bb..5ab2595ab 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 @@ -25,8 +25,6 @@ import org.springframework.beans.factory.xml.ParserContext; import org.springframework.security.config.BeanIds; import org.springframework.security.oauth2.provider.CompositeTokenGranter; -import org.springframework.security.oauth2.provider.DefaultOAuth2RequestFactory; -import org.springframework.security.oauth2.provider.DefaultOAuth2RequestValidator; import org.springframework.security.oauth2.provider.approval.DefaultUserApprovalHandler; import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenGranter; import org.springframework.security.oauth2.provider.code.AuthorizationCodeTokenGranter; @@ -39,6 +37,8 @@ import org.springframework.security.oauth2.provider.implicit.InMemoryImplicitGrantService; 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.util.StringUtils; import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ClientDetailsServiceBeanDefinitionParser.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ClientDetailsServiceBeanDefinitionParser.java index 0ba434a03..5d9ec4af8 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ClientDetailsServiceBeanDefinitionParser.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ClientDetailsServiceBeanDefinitionParser.java @@ -23,8 +23,8 @@ import org.springframework.beans.factory.support.ManagedMap; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; -import org.springframework.security.oauth2.provider.BaseClientDetails; -import org.springframework.security.oauth2.provider.InMemoryClientDetailsService; +import org.springframework.security.oauth2.provider.client.BaseClientDetails; +import org.springframework.security.oauth2.provider.client.InMemoryClientDetailsService; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/SaltedClientSecret.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/SaltedClientSecret.java deleted file mode 100644 index 7ac3dc4b7..000000000 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/SaltedClientSecret.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.springframework.security.oauth2.provider; - -/** - * Marker interface for indicating that a client details secret has some salt. - */ -public interface SaltedClientSecret { - - /** - * Returns the salt to use for this client secret. - * - * @return the salt to use for this client secret. - */ - Object getSalt(); -} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseClientDetails.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/BaseClientDetails.java similarity index 95% rename from spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseClientDetails.java rename to spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/BaseClientDetails.java index b08277500..83539591e 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseClientDetails.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/BaseClientDetails.java @@ -1,4 +1,4 @@ -package org.springframework.security.oauth2.provider; +package org.springframework.security.oauth2.provider.client; import java.io.IOException; import java.util.ArrayList; @@ -30,6 +30,7 @@ import org.codehaus.jackson.type.TypeReference; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.util.StringUtils; /** @@ -320,10 +321,22 @@ public boolean equals(Object obj) { if (getClass() != obj.getClass()) return false; BaseClientDetails other = (BaseClientDetails) obj; - if (accessTokenValiditySeconds != other.accessTokenValiditySeconds) - return false; - if (refreshTokenValiditySeconds != other.refreshTokenValiditySeconds) - return false; + if (accessTokenValiditySeconds == null) { + if (other.accessTokenValiditySeconds != null) { + return false; + } + } + else { + return accessTokenValiditySeconds.equals(other.accessTokenValiditySeconds); + } + if (refreshTokenValiditySeconds == null) { + if (other.refreshTokenValiditySeconds != null) { + return false; + } + } + else { + return refreshTokenValiditySeconds.equals(other.refreshTokenValiditySeconds); + } if (authorities == null) { if (other.authorities != null) return false; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/InMemoryClientDetailsService.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/InMemoryClientDetailsService.java similarity index 84% rename from spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/InMemoryClientDetailsService.java rename to spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/InMemoryClientDetailsService.java index 476d830a7..0055b116e 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/InMemoryClientDetailsService.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/InMemoryClientDetailsService.java @@ -14,12 +14,15 @@ * limitations under the License. */ -package org.springframework.security.oauth2.provider; +package org.springframework.security.oauth2.provider.client; import java.util.HashMap; import java.util.Map; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; +import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.NoSuchClientException; /** * Basic, in-memory implementation of the client details service. diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/JdbcClientDetailsService.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/JdbcClientDetailsService.java similarity index 95% rename from spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/JdbcClientDetailsService.java rename to spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/JdbcClientDetailsService.java index c7ff1ac7d..2d3b3b199 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/JdbcClientDetailsService.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/JdbcClientDetailsService.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.security.oauth2.provider; +package org.springframework.security.oauth2.provider.client; import java.sql.ResultSet; import java.sql.SQLException; @@ -39,6 +39,11 @@ import org.springframework.security.oauth2.common.exceptions.InvalidClientException; import org.springframework.security.oauth2.common.util.DefaultJdbcListFactory; import org.springframework.security.oauth2.common.util.JdbcListFactory; +import org.springframework.security.oauth2.provider.ClientAlreadyExistsException; +import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.ClientRegistrationService; +import org.springframework.security.oauth2.provider.NoSuchClientException; import org.springframework.util.Assert; import org.springframework.util.StringUtils; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AbstractEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AbstractEndpoint.java index 95e8f59f0..e8ad7f931 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AbstractEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AbstractEndpoint.java @@ -21,10 +21,10 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; import org.springframework.security.oauth2.provider.ClientDetailsService; -import org.springframework.security.oauth2.provider.DefaultOAuth2RequestFactory; import org.springframework.security.oauth2.provider.TokenGranter; import org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator; import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator; +import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory; import org.springframework.util.Assert; /** diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java index a202e6495..f68f23081 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java @@ -40,7 +40,6 @@ import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientRegistrationException; -import org.springframework.security.oauth2.provider.DefaultOAuth2RequestValidator; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.OAuth2RequestValidator; @@ -51,6 +50,7 @@ import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices; import org.springframework.security.oauth2.provider.implicit.ImplicitGrantService; import org.springframework.security.oauth2.provider.implicit.InMemoryImplicitGrantService; +import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestValidator; import org.springframework.util.StringUtils; import org.springframework.web.HttpSessionRequiredException; import org.springframework.web.bind.annotation.ExceptionHandler; @@ -97,7 +97,7 @@ public class AuthorizationEndpoint extends AbstractEndpoint { private SessionAttributeStore sessionAttributeStore = new DefaultSessionAttributeStore(); - private OAuth2RequestValidator oAuth2RequestValidator = new DefaultOAuth2RequestValidator(); + private OAuth2RequestValidator oauth2RequestValidator = new DefaultOAuth2RequestValidator(); private ImplicitGrantService implicitGrantService = new InMemoryImplicitGrantService(); @@ -153,7 +153,7 @@ public ModelAndView authorize(Map model, @RequestParam // We intentionally only validate the parameters requested by the client (ignoring any data that may have // been added to the request by the manager). - oAuth2RequestValidator.validateScope(authorizationRequest, client); + oauth2RequestValidator.validateScope(authorizationRequest, client); // Some systems may allow for approval decisions to be remembered or approved by default. Check for // such logic here, and set the approved flag on the authorization request accordingly. @@ -423,8 +423,8 @@ public void setUserApprovalHandler(UserApprovalHandler userApprovalHandler) { this.userApprovalHandler = userApprovalHandler; } - public void setoAuth2RequestValidator(OAuth2RequestValidator oAuth2RequestValidator) { - this.oAuth2RequestValidator = oAuth2RequestValidator; + public void setOAuth2RequestValidator(OAuth2RequestValidator oauth2RequestValidator) { + this.oauth2RequestValidator = oauth2RequestValidator; } public void setImplicitGrantService(ImplicitGrantService implicitGrantService) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java index 34847f66a..2728c5a32 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java @@ -35,10 +35,10 @@ import org.springframework.security.oauth2.common.util.OAuth2Utils; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientRegistrationException; -import org.springframework.security.oauth2.provider.DefaultOAuth2RequestValidator; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2RequestValidator; import org.springframework.security.oauth2.provider.TokenRequest; +import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestValidator; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; @@ -64,7 +64,7 @@ @FrameworkEndpoint public class TokenEndpoint extends AbstractEndpoint { - private OAuth2RequestValidator oAuth2RequestValidator = new DefaultOAuth2RequestValidator(); + private OAuth2RequestValidator oauth2RequestValidator = new DefaultOAuth2RequestValidator(); @RequestMapping(value = "/oauth/token") public ResponseEntity getAccessToken(Principal principal, @RequestParam @@ -89,7 +89,7 @@ public ResponseEntity getAccessToken(Principal principal, @Re throw new InvalidClientException("Given client ID does not match authenticated client"); } if (authenticatedClient != null) { - oAuth2RequestValidator.validateScope(tokenRequest, authenticatedClient); + oauth2RequestValidator.validateScope(tokenRequest, authenticatedClient); } } if (!StringUtils.hasText(tokenRequest.getGrantType())) { @@ -165,8 +165,8 @@ private boolean isAuthCodeRequest(Map parameters) { return "authorization_code".equals(parameters.get("grant_type")) && parameters.get("code") != null; } - public void setoAuth2RequestValidator(OAuth2RequestValidator oAuth2RequestValidator) { - this.oAuth2RequestValidator = oAuth2RequestValidator; + public void setOAuth2RequestValidator(OAuth2RequestValidator oauth2RequestValidator) { + this.oauth2RequestValidator = oauth2RequestValidator; } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelApprovalEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelApprovalEndpoint.java index a39d67d4a..ee497b278 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelApprovalEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelApprovalEndpoint.java @@ -27,7 +27,10 @@ public class WhitelabelApprovalEndpoint { @RequestMapping("/oauth/confirm_access") - public ModelAndView getAccessConfirmation(Map model) throws Exception { + public ModelAndView getAccessConfirmation(Map model, HttpServletRequest request) throws Exception { + if (request.getAttribute("_csrf")!=null) { + model.put("_csrf", request.getAttribute("_csrf")); + } return new ModelAndView(new SpelView(APPROVAL), model); } @@ -40,7 +43,7 @@ public ModelAndView handleError(HttpServletRequest request) { /** * Simple String template renderer. - * + * */ private static class SpelView implements View { @@ -62,7 +65,7 @@ public SpelView(String template) { public String resolvePlaceholder(String name) { Expression expression = parser.parseExpression(name); Object value = expression.getValue(context); - return value==null ? null : value.toString(); + return value == null ? null : value.toString(); } }; } @@ -83,10 +86,13 @@ public void render(Map model, HttpServletRequest request, HttpServlet } + private static String CSRF = "${#root['_csrf']!=null ? '' : ''}"; + private static String APPROVAL = "

OAuth Approval

" + "

Do you authorize '${authorizationRequest.clientId}' to access your protected resources?

" - + "" - + "
" + + "
"+CSRF+"
" + + "
"+CSRF+"
" + ""; private static String ERROR = "

OAuth Error

${error.summary}

"; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestFactory.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/request/DefaultOAuth2RequestFactory.java similarity index 60% rename from spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestFactory.java rename to spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/request/DefaultOAuth2RequestFactory.java index e1093a4d2..a5863bdde 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestFactory.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/request/DefaultOAuth2RequestFactory.java @@ -10,18 +10,28 @@ * 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; +package org.springframework.security.oauth2.provider.request; import java.util.Collections; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; +import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.oauth2.common.exceptions.InvalidClientException; +import org.springframework.security.oauth2.common.util.DefaultSecurityContextAccessor; import org.springframework.security.oauth2.common.util.OAuth2Utils; +import org.springframework.security.oauth2.common.util.SecurityContextAccessor; +import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; +import org.springframework.security.oauth2.provider.TokenRequest; /** - * Default implementation of {@link OAuth2RequestFactory} which initializes fields from the parameters map, - * validates grant types and scopes, and fills in scopes with the default values from the client if they are missing. + * Default implementation of {@link OAuth2RequestFactory} which initializes fields from the parameters map, validates + * grant types and scopes, and fills in scopes with the default values from the client if they are missing. * * @author Dave Syer * @author Amanda Anganes @@ -30,19 +40,41 @@ public class DefaultOAuth2RequestFactory implements OAuth2RequestFactory { private final ClientDetailsService clientDetailsService; - + + private SecurityContextAccessor securityContextAccessor = new DefaultSecurityContextAccessor(); + + private boolean checkUserScopes = false; + public DefaultOAuth2RequestFactory(ClientDetailsService clientDetailsService) { this.clientDetailsService = clientDetailsService; } + /** + * @param securityContextAccessor the security context accessor to set + */ + public void setSecurityContextAccessor(SecurityContextAccessor securityContextAccessor) { + this.securityContextAccessor = securityContextAccessor; + } + + /** + * Flag to indicate that scopes should be interpreted as valid authorities. No scopes will be granted to a user + * unless they are permitted as a granted authority to that user. + * + * @param checkUserScopes the checkUserScopes to set (default false) + */ + public void setCheckUserScopes(boolean checkUserScopes) { + this.checkUserScopes = checkUserScopes; + } + public AuthorizationRequest createAuthorizationRequest(Map authorizationParameters) { - + String clientId = authorizationParameters.get(OAuth2Utils.CLIENT_ID); Set scopes = OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Utils.SCOPE)); String state = authorizationParameters.get(OAuth2Utils.STATE); String redirectUri = authorizationParameters.get(OAuth2Utils.REDIRECT_URI); - Set responseTypes = OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Utils.RESPONSE_TYPE)); - + Set responseTypes = OAuth2Utils.parseParameterList(authorizationParameters + .get(OAuth2Utils.RESPONSE_TYPE)); + ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId); if ((scopes == null || scopes.isEmpty())) { @@ -52,26 +84,47 @@ public AuthorizationRequest createAuthorizationRequest(Map autho scopes = clientDetails.getScope(); } - AuthorizationRequest request = new AuthorizationRequest(authorizationParameters, Collections. emptyMap(), - clientId, scopes, null, null, false, state, redirectUri, responseTypes); - + if (checkUserScopes) { + scopes = checkUserScopes(scopes, clientDetails); + } + + AuthorizationRequest request = new AuthorizationRequest(authorizationParameters, + Collections. emptyMap(), clientId, scopes, null, null, false, state, redirectUri, + responseTypes); + request.setResourceIdsAndAuthoritiesFromClientDetails(clientDetails); - + return request; } + private Set checkUserScopes(Set scopes, ClientDetails clientDetails) { + if (!securityContextAccessor.isUser()) { + return scopes; + } + Set result = new LinkedHashSet(); + Set authorities = AuthorityUtils.authorityListToSet(securityContextAccessor.getAuthorities()); + for (String scope : scopes) { + if (authorities.contains(scope) || authorities.contains(scope.toUpperCase()) + || authorities.contains("ROLE_" + scope.toUpperCase())) { + result.add(scope); + } + } + return result; + } + public OAuth2Request createOAuth2Request(AuthorizationRequest request) { return request.createOAuth2Request(); } - + public TokenRequest createTokenRequest(Map requestParameters, ClientDetails authenticatedClient) { String clientId = requestParameters.get(OAuth2Utils.CLIENT_ID); if (clientId == null) { // if the clientId wasn't passed in in the map, we add pull it from the authenticated client object clientId = authenticatedClient.getClientId(); - } else { + } + else { // otherwise, make sure that they match if (!clientId.equals(authenticatedClient.getClientId())) { throw new InvalidClientException("Given client ID does not match authenticated client"); @@ -79,7 +132,7 @@ public TokenRequest createTokenRequest(Map requestParameters, Cl } Set scopes = OAuth2Utils.parseParameterList(requestParameters.get(OAuth2Utils.SCOPE)); String grantType = requestParameters.get(OAuth2Utils.GRANT_TYPE); - + ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId); if ((scopes == null || scopes.isEmpty())) { @@ -90,12 +143,13 @@ public TokenRequest createTokenRequest(Map requestParameters, Cl } TokenRequest tokenRequest = new TokenRequest(requestParameters, clientId, scopes, grantType); - + return tokenRequest; } public TokenRequest createTokenRequest(AuthorizationRequest authorizationRequest, String grantType) { - TokenRequest tokenRequest = new TokenRequest(authorizationRequest.getRequestParameters(), authorizationRequest.getClientId(), authorizationRequest.getScope(), grantType); + TokenRequest tokenRequest = new TokenRequest(authorizationRequest.getRequestParameters(), + authorizationRequest.getClientId(), authorizationRequest.getScope(), grantType); return tokenRequest; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestValidator.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/request/DefaultOAuth2RequestValidator.java similarity index 66% rename from spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestValidator.java rename to spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/request/DefaultOAuth2RequestValidator.java index 445408ddf..ea297e336 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultOAuth2RequestValidator.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/request/DefaultOAuth2RequestValidator.java @@ -1,8 +1,12 @@ -package org.springframework.security.oauth2.provider; +package org.springframework.security.oauth2.provider.request; import java.util.Set; import org.springframework.security.oauth2.common.exceptions.InvalidScopeException; +import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.OAuth2RequestValidator; +import org.springframework.security.oauth2.provider.TokenRequest; /** * Default implementation of {@link OAuth2RequestValidator}. @@ -29,6 +33,10 @@ private void validateScope(Set requestScopes, Set clientScopes) } } } + + if (requestScopes.isEmpty()) { + throw new InvalidScopeException("Empty scope (either the client or the user is not allowed the requested scopes)"); + } } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancer.java index 3026dca8f..c7b8845d8 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancer.java @@ -182,7 +182,7 @@ public void afterPropertiesSet() throws Exception { } } else { - // Avoid a race condition where + // Avoid a race condition where setters are called in the wrong order. Use of == is intentional. Assert.state(this.signingKey == this.verifierKey, "For MAC signing you do not need to specify the verifier key separately, and if you do it must match the signing key"); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java index a588b9884..a0ba4610a 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java @@ -25,10 +25,10 @@ import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.config.annotation.web.configurers.OAuth2ResourceServerConfigurer; -import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.TokenRequest; +import org.springframework.security.oauth2.provider.client.BaseClientDetails; import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler; import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequestTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequestTests.java deleted file mode 100644 index aaa0de253..000000000 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/DefaultAuthorizationRequestTests.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * 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; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.SortedSet; - -import org.junit.Before; -import org.junit.Test; -import org.springframework.security.oauth2.common.util.OAuth2Utils; -import org.springframework.util.StringUtils; - -/** - * @author Dave Syer - * @author Christian Hilmersson - * - */ -public class DefaultAuthorizationRequestTests { - - private Map parameters; - - @Before - public void prepare() { - parameters = new HashMap(); - parameters.put("client_id", "theClient"); - parameters.put("state", "XYZ123"); - parameters.put("redirect_uri", "http://www.callistaenterprise.se/"); - } - - private AuthorizationRequest createFromParameters(Map authorizationParameters) { - AuthorizationRequest request = new AuthorizationRequest(authorizationParameters, Collections. emptyMap(), - authorizationParameters.get(OAuth2Utils.CLIENT_ID), - OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Utils.SCOPE)), null, - null, false, authorizationParameters.get(OAuth2Utils.STATE), - authorizationParameters.get(OAuth2Utils.REDIRECT_URI), - OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Utils.RESPONSE_TYPE))); - return request; - } - - @Test - public void testApproval() throws Exception { - AuthorizationRequest authorizationRequest = createFromParameters(parameters); - assertFalse(authorizationRequest.isApproved()); - authorizationRequest.setApproved(true); - assertTrue(authorizationRequest.isApproved()); - } - - /** - * Ensure that setting the scope does not alter the original request parameters. - * - * @throws Exception - */ - @Test - public void testScopeNotSetInParameters() throws Exception { - parameters.put("scope", "read,write"); - AuthorizationRequest authorizationRequest = createFromParameters(parameters); - authorizationRequest.setScope(StringUtils.commaDelimitedListToSet("foo,bar")); - assertFalse(authorizationRequest.getRequestParameters().get(OAuth2Utils.SCOPE).contains("bar")); - assertFalse(authorizationRequest.getRequestParameters().get(OAuth2Utils.SCOPE).contains("foo")); - } - - @Test - public void testClientIdNotOverwitten() throws Exception { - AuthorizationRequest authorizationRequest = new AuthorizationRequest("client", Arrays.asList("read")); - parameters = new HashMap(); - parameters.put("scope", "write"); - authorizationRequest.setRequestParameters(parameters); - - assertEquals("client", authorizationRequest.getClientId()); - assertEquals(1, authorizationRequest.getScope().size()); - assertTrue(authorizationRequest.getScope().contains("read")); - assertFalse(authorizationRequest.getRequestParameters().get(OAuth2Utils.SCOPE).contains("read")); - } - - @Test - public void testScopeWithSpace() throws Exception { - parameters.put("scope", "bar foo"); - AuthorizationRequest authorizationRequest = createFromParameters(parameters); - authorizationRequest.setScope(Collections.singleton("foo bar")); - assertEquals("bar foo", authorizationRequest.getRequestParameters().get(OAuth2Utils.SCOPE)); - } - - /** - * Tests that the construction of an AuthorizationRequest objects using - * a parameter Map maintains a sorted order of the scope. - */ - @Test - public void testScopeSortedOrder() { - // Arbitrary scope set - String scopeString = "AUTHORITY_A AUTHORITY_X AUTHORITY_B AUTHORITY_C AUTHORITY_D " + - "AUTHORITY_Y AUTHORITY_V AUTHORITY_ZZ AUTHORITY_DYV AUTHORITY_ABC AUTHORITY_BA " + - "AUTHORITY_AV AUTHORITY_AB AUTHORITY_CDA AUTHORITY_ABCD"; - // Create correctly sorted scope string - Set sortedSet = OAuth2Utils.parseParameterList(scopeString); - assertTrue(sortedSet instanceof SortedSet); - String sortedScopeString = OAuth2Utils.formatParameterList(sortedSet); - - parameters.put("scope", scopeString); - AuthorizationRequest authorizationRequest = createFromParameters(parameters); - authorizationRequest.setScope(sortedSet); - - // Assert that the scope parameter is still sorted - - String fromAR = OAuth2Utils.formatParameterList(authorizationRequest.getScope()); - - assertEquals(sortedScopeString, fromAR); - } - - @Test - public void testRedirectUriDefaultsToMap() { - parameters.put("scope", "one two"); - AuthorizationRequest authorizationRequest = createFromParameters(parameters); - - assertEquals("XYZ123", authorizationRequest.getState()); - assertEquals("theClient", authorizationRequest.getClientId()); - assertEquals("http://www.callistaenterprise.se/", authorizationRequest.getRedirectUri()); - assertEquals("http://www.callistaenterprise.se/", authorizationRequest.getRequestParameters().get(OAuth2Utils.REDIRECT_URI)); - assertEquals("[one, two]", authorizationRequest.getScope().toString()); - } - -} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandlerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandlerTests.java index b5d59741a..6129a203b 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandlerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandlerTests.java @@ -18,10 +18,10 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.oauth2.provider.AuthorizationRequest; -import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.ClientDetails; -import org.springframework.security.oauth2.provider.DefaultOAuth2RequestFactory; -import org.springframework.security.oauth2.provider.InMemoryClientDetailsService; +import org.springframework.security.oauth2.provider.client.BaseClientDetails; +import org.springframework.security.oauth2.provider.client.InMemoryClientDetailsService; +import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory; public class ApprovalStoreUserApprovalHandlerTests { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandlerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandlerTests.java index db0e1290d..ab9e1f536 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandlerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandlerTests.java @@ -20,9 +20,9 @@ import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.oauth2.common.util.OAuth2Utils; import org.springframework.security.oauth2.provider.AuthorizationRequest; -import org.springframework.security.oauth2.provider.DefaultOAuth2RequestFactory; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory; import org.springframework.security.oauth2.provider.token.DefaultTokenServices; import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/BaseClientDetailsTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/BaseClientDetailsTests.java similarity index 97% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/BaseClientDetailsTests.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/BaseClientDetailsTests.java index ece15eb88..9d0340960 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/BaseClientDetailsTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/BaseClientDetailsTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.security.oauth2.provider; +package org.springframework.security.oauth2.provider.client; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -24,6 +24,7 @@ import org.codehaus.jackson.map.ObjectMapper; import org.junit.Test; +import org.springframework.security.oauth2.provider.client.BaseClientDetails; import org.springframework.util.StringUtils; /** diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/JdbcClientDetailsServiceTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/JdbcClientDetailsServiceTests.java similarity index 96% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/JdbcClientDetailsServiceTests.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/JdbcClientDetailsServiceTests.java index f2af3d12f..762aefe0e 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/JdbcClientDetailsServiceTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/JdbcClientDetailsServiceTests.java @@ -1,4 +1,4 @@ -package org.springframework.security.oauth2.provider; +package org.springframework.security.oauth2.provider.client; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -19,6 +19,11 @@ import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.oauth2.provider.ClientAlreadyExistsException; +import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.NoSuchClientException; +import org.springframework.security.oauth2.provider.client.BaseClientDetails; +import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService; public class JdbcClientDetailsServiceTests { private JdbcClientDetailsService service; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranterTests.java index 0ff03e18e..a27b75af4 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranterTests.java @@ -26,15 +26,15 @@ import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.common.exceptions.RedirectMismatchException; import org.springframework.security.oauth2.common.util.OAuth2Utils; -import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; -import org.springframework.security.oauth2.provider.DefaultOAuth2RequestFactory; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; import org.springframework.security.oauth2.provider.RequestTokenFactory; import org.springframework.security.oauth2.provider.TokenRequest; +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.InMemoryTokenStore; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/SubdomainRedirectResolverTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/SubdomainRedirectResolverTests.java index 73dff82ad..0cb2cb7a6 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/SubdomainRedirectResolverTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/SubdomainRedirectResolverTests.java @@ -9,7 +9,7 @@ import org.junit.Test; import org.springframework.security.oauth2.common.exceptions.RedirectMismatchException; -import org.springframework.security.oauth2.provider.BaseClientDetails; +import org.springframework.security.oauth2.provider.client.BaseClientDetails; import org.springframework.security.oauth2.provider.endpoint.DefaultRedirectResolver; public class SubdomainRedirectResolverTests diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java index 03b921782..2e0bfc3b2 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java @@ -38,7 +38,6 @@ import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.common.util.OAuth2Utils; import org.springframework.security.oauth2.provider.AuthorizationRequest; -import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; @@ -46,6 +45,7 @@ import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.approval.DefaultUserApprovalHandler; import org.springframework.security.oauth2.provider.approval.UserApprovalHandler; +import org.springframework.security.oauth2.provider.client.BaseClientDetails; import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; import org.springframework.web.bind.support.SimpleSessionStatus; import org.springframework.web.servlet.ModelAndView; @@ -121,7 +121,7 @@ public void testMandatoryProperties() throws Exception { @Test public void testStartAuthorizationCodeFlow() throws Exception { - ModelAndView result = endpoint.authorize(model, getAuthorizationRequest("foo", null, null, null, Collections.singleton("code")) + ModelAndView result = endpoint.authorize(model, getAuthorizationRequest("foo", null, null, "read", Collections.singleton("code")) .getRequestParameters(), sessionStatus, principal); assertEquals("forward:/oauth/confirm_access", result.getViewName()); } @@ -221,7 +221,7 @@ public void testAuthorizationCodeWithMultipleResponseTypes() throws Exception { Set responseTypes = new HashSet(); responseTypes.add("code"); responseTypes.add("other"); - ModelAndView result = endpoint.authorize(model, getAuthorizationRequest("foo", null, null, null, responseTypes) + ModelAndView result = endpoint.authorize(model, getAuthorizationRequest("foo", null, null, "read", responseTypes) .getRequestParameters(), sessionStatus, principal); assertEquals("forward:/oauth/confirm_access", result.getViewName()); } @@ -340,6 +340,7 @@ public AuthorizationRequest updateAfterApproval( return authorizationRequest; } }); + client.setScope(Collections.singleton("read")); AuthorizationRequest authorizationRequest = getAuthorizationRequest("foo", "http://anywhere.com/", "mystate", null, Collections.singleton("token")); ModelAndView result = endpoint.authorize(model,authorizationRequest.getRequestParameters(), @@ -452,7 +453,7 @@ public void testApprovalDenied() throws Exception { @Test public void testDirectApproval() throws Exception { ModelAndView result = endpoint.authorize(model, - getAuthorizationRequest("foo", "http://anywhere.com/", null, null, Collections.singleton("code")).getRequestParameters(), + getAuthorizationRequest("foo", "http://anywhere.com/", null, "read", Collections.singleton("code")).getRequestParameters(), sessionStatus, principal); // Should go to approval page (SECOAUTH-191) assertFalse(result.getView() instanceof RedirectView); @@ -460,7 +461,7 @@ public void testDirectApproval() throws Exception { @Test public void testRedirectUriOptionalForAuthorization() throws Exception { - ModelAndView result = endpoint.authorize(model, getAuthorizationRequest("foo", null, null, null, Collections.singleton("code")) + ModelAndView result = endpoint.authorize(model, getAuthorizationRequest("foo", null, null, "read", Collections.singleton("code")) .getRequestParameters(), sessionStatus, principal); // RedirectUri parameter should be null (SECOAUTH-333), however the resolvedRedirectUri not AuthorizationRequest authorizationRequest = (AuthorizationRequest) result.getModelMap().get( diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolverTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolverTests.java index 52991966b..f5985e1a8 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolverTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolverTests.java @@ -22,7 +22,7 @@ import org.junit.Test; import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; import org.springframework.security.oauth2.common.exceptions.RedirectMismatchException; -import org.springframework.security.oauth2.provider.BaseClientDetails; +import org.springframework.security.oauth2.provider.client.BaseClientDetails; import org.springframework.security.oauth2.provider.endpoint.DefaultRedirectResolver; /** diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/ExactMatchRedirectResolverTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/ExactMatchRedirectResolverTests.java index e9fb327df..f4429763b 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/ExactMatchRedirectResolverTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/ExactMatchRedirectResolverTests.java @@ -22,7 +22,7 @@ import org.junit.Test; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.common.exceptions.RedirectMismatchException; -import org.springframework.security.oauth2.provider.BaseClientDetails; +import org.springframework.security.oauth2.provider.client.BaseClientDetails; import org.springframework.security.oauth2.provider.endpoint.ExactMatchRedirectResolver; /** diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilterTests.java index 58f293e6b..954b1b5d9 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilterTests.java @@ -33,11 +33,11 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; -import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; -import org.springframework.security.oauth2.provider.DefaultOAuth2RequestFactory; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.client.BaseClientDetails; +import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory; /** * @author Dave Syer diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointTests.java index 382f647dd..f2623a741 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointTests.java @@ -41,12 +41,12 @@ import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; import org.springframework.security.oauth2.common.util.OAuth2Utils; -import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; import org.springframework.security.oauth2.provider.TokenGranter; import org.springframework.security.oauth2.provider.TokenRequest; +import org.springframework.security.oauth2.provider.client.BaseClientDetails; /** * @author Dave Syer @@ -148,6 +148,7 @@ public void testImplicitGrant() { HashMap parameters = new HashMap(); parameters.put(OAuth2Utils.GRANT_TYPE, "implicit"); parameters.put("client_id", clientId); + parameters.put("scope", "read"); @SuppressWarnings("unchecked") Map anyMap = Mockito.any(Map.class); when(authorizationRequestFactory.createTokenRequest(anyMap, Mockito.eq(clientDetails))).thenReturn( diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelApprovalEndpointTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelApprovalEndpointTests.java index 1a9f3789c..debcabfb8 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelApprovalEndpointTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelApprovalEndpointTests.java @@ -55,7 +55,7 @@ public void testApprovalPage() throws Exception { parameters.put("client_id", "client"); HashMap model = new HashMap(); model.put("authorizationRequest", createFromParameters(parameters)); - ModelAndView result = endpoint.getAccessConfirmation(model); + ModelAndView result = endpoint.getAccessConfirmation(model, request); result.getView().render(result.getModel(), request , response); String content = response.getContentAsString(); assertTrue("Wrong content: " + content, content.contains(" params; + + @Before + public void start() { + client.setClientId("foo"); + client.setScope(Collections.singleton("bar")); + params = new HashMap(); + params.put("client_id", "foo"); + params.put("scope", "foo"); + } + + @Test(expected=InvalidScopeException.class) + public void testNotPermittedForEmpty() { + AuthorizationRequest request = factory.createAuthorizationRequest(params); + request.setScope(Collections.emptySet()); + validator.validateScope(request, client);; + } + + @Test(expected=InvalidScopeException.class) + public void testNotPermittedForAuthorization() { + AuthorizationRequest request = factory.createAuthorizationRequest(params ); + request.setScope(Collections.singleton("foo")); + validator.validateScope(request, client); + } + + @Test(expected=InvalidScopeException.class) + public void testNotPermittedForScope() { + AuthorizationRequest request = factory.createAuthorizationRequest(params ); + TokenRequest tokenRequest = factory.createTokenRequest(request, "authorization_code"); + tokenRequest.setScope(Collections.singleton("foo")); + validator.validateScope(tokenRequest, client);; + } + +} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractTestDefaultTokenServices.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractTestDefaultTokenServices.java index f70aca577..0b7789139 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractTestDefaultTokenServices.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractTestDefaultTokenServices.java @@ -19,12 +19,12 @@ import org.springframework.security.oauth2.common.OAuth2RefreshToken; import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; -import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.RequestTokenFactory; import org.springframework.security.oauth2.provider.TokenRequest; +import org.springframework.security.oauth2.provider.client.BaseClientDetails; /** * @author Dave Syer diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithInMemoryTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithInMemoryTests.java index fc591b36d..31a67037a 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithInMemoryTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithInMemoryTests.java @@ -19,12 +19,12 @@ import org.springframework.security.oauth2.common.OAuth2RefreshToken; import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; -import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.RequestTokenFactory; import org.springframework.security.oauth2.provider.TokenRequest; +import org.springframework.security.oauth2.provider.client.BaseClientDetails; import org.springframework.test.util.ReflectionTestUtils; /** diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenServicesTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenServicesTests.java index 7aca786cb..e37744c61 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenServicesTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenServicesTests.java @@ -35,12 +35,12 @@ import org.springframework.security.oauth2.common.OAuth2RefreshToken; import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; -import org.springframework.security.oauth2.provider.BaseClientDetails; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.TokenRequest; +import org.springframework.security.oauth2.provider.client.BaseClientDetails; import org.springframework.test.util.ReflectionTestUtils; /** diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/ClientScopeVoterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/ClientScopeVoterTests.java index c35882a1d..ca3b15ea0 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/ClientScopeVoterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/ClientScopeVoterTests.java @@ -15,9 +15,9 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.oauth2.provider.AuthorizationRequest; -import org.springframework.security.oauth2.provider.BaseClientDetails; -import org.springframework.security.oauth2.provider.InMemoryClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.client.BaseClientDetails; +import org.springframework.security.oauth2.provider.client.InMemoryClientDetailsService; public class ClientScopeVoterTests { diff --git a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-extras.xml b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-extras.xml index acff75874..701fde1d0 100644 --- a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-extras.xml +++ b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-extras.xml @@ -31,7 +31,7 @@ - + @@ -39,7 +39,7 @@ - + From 47f75525d75980a0e96ad3b0e4ce4f3c5e6b027f Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 24 Mar 2014 11:38:16 +0000 Subject: [PATCH 188/831] Ensure tonr samples work from command line Tomcat plugin configuration needs to be extracted so that it applies to all runs (not just integration tests) Fixes gh-164 --- README.md | 8 ++++-- samples/README.md | 2 +- samples/oauth/sparklr/pom.xml | 12 ++++---- samples/oauth/tonr/pom.xml | 18 +++++++++--- samples/oauth2/sparklr/pom.xml | 15 +++++----- samples/oauth2/tonr/pom.xml | 28 +++++++++---------- .../tonr/src/main/webapp/oauth_error.jsp | 2 -- 7 files changed, 50 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 57df597ab..724da83d3 100644 --- a/README.md +++ b/README.md @@ -31,11 +31,15 @@ have installed the artifacts locally (as per the getting started instructions above) you should be able to $ cd samples/oauth2/tonr - $ mvn tomcat:run + $ mvn tomcat7:run and visit the app in your browser at [http://localhost:8080/tonr2/](http://localhost:8080/tonr2/) to check that it works. (This is for the OAuth 2.0 sample, for the -OAuth 1.0a sample just remove the "2" from the directory path.) +OAuth 1.0a sample just remove the "2" from the directory path.) Integration tests +require slightly different settings for Tomcat so you need to add a profile: + + $ cd samples/oauth2/tonr + $ mvn integration-test -P integration ## Changelog diff --git a/samples/README.md b/samples/README.md index 992ff7aa7..c6dce912c 100644 --- a/samples/README.md +++ b/samples/README.md @@ -19,7 +19,7 @@ to read his photos for the purpose of printing them. To run the apps the easiest thing is to first install all the artifacts using `mvn install` and then go to the `tonr` directory (in -`oauth` or `oauth2`) and run `mvn tomcat:run`. You can also use the +`oauth` or `oauth2`) and run `mvn tomcat7:run`. You can also use the command line to build war files with `mvn package` and drop them in your favourite server, or you can run them directly from an IDE. diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index 4ca71dec4..f53096dea 100644 --- a/samples/oauth/sparklr/pom.xml +++ b/samples/oauth/sparklr/pom.xml @@ -1,4 +1,5 @@ - + 4.0.0 @@ -32,8 +33,8 @@ - org.codehaus.mojo - tomcat-maven-plugin + org.apache.tomcat.maven + tomcat7-maven-plugin /sparklr true @@ -101,7 +102,8 @@
- +
diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index 439d42eca..aff81fae5 100644 --- a/samples/oauth/tonr/pom.xml +++ b/samples/oauth/tonr/pom.xml @@ -1,4 +1,5 @@ - + 4.0.0 @@ -27,11 +28,20 @@ - org.codehaus.mojo - tomcat-maven-plugin + org.apache.tomcat.maven + tomcat7-maven-plugin - /tonr true + + + /sparklr2 + ${pom.groupId} + sparklr + ${pom.version} + war + true + + diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 0ef4adb91..344babe7d 100644 --- a/samples/oauth2/sparklr/pom.xml +++ b/samples/oauth2/sparklr/pom.xml @@ -1,4 +1,5 @@ - + 4.0.0 @@ -41,9 +42,9 @@ - org.apache.tomcat.maven - tomcat7-maven-plugin - + org.apache.tomcat.maven + tomcat7-maven-plugin + start-tomcat pre-integration-test @@ -51,7 +52,7 @@ run - /sparklr2 + /sparklr2 true @@ -76,8 +77,8 @@ - org.codehaus.mojo - tomcat-maven-plugin + org.apache.tomcat.maven + tomcat7-maven-plugin true diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index b69b0ca7b..dc461a083 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -1,4 +1,5 @@ - + 4.0.0 @@ -52,17 +53,6 @@ true - true - - - /sparklr2 - ${pom.groupId} - sparklr2 - ${pom.version} - war - true - - @@ -86,10 +76,20 @@ - org.codehaus.mojo - tomcat-maven-plugin + org.apache.tomcat.maven + tomcat7-maven-plugin true + + + /sparklr2 + ${pom.groupId} + sparklr2 + ${pom.version} + war + true + + diff --git a/samples/oauth2/tonr/src/main/webapp/oauth_error.jsp b/samples/oauth2/tonr/src/main/webapp/oauth_error.jsp index f3a332b13..ac9accec8 100644 --- a/samples/oauth2/tonr/src/main/webapp/oauth_error.jsp +++ b/samples/oauth2/tonr/src/main/webapp/oauth_error.jsp @@ -1,5 +1,3 @@ -<%@ page import="java.io.PrintWriter"%> -<%@ page import="java.io.StringWriter"%> <%@ taglib prefix="authz" uri="http://www.springframework.org/security/tags"%> <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core"%> From 77790a488045044914896688eea1009838dec6b3 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 25 Mar 2014 13:16:57 +0000 Subject: [PATCH 189/831] Tidy up build, removing unnecessary plugins See gh-163 --- pom.xml | 89 ++-------------------------------- spring-security-oauth/pom.xml | 12 +++-- spring-security-oauth2/pom.xml | 11 ++--- 3 files changed, 16 insertions(+), 96 deletions(-) diff --git a/pom.xml b/pom.xml index 965b0641c..7acacd4fd 100644 --- a/pom.xml +++ b/pom.xml @@ -16,10 +16,8 @@ UTF-8 - 3.2.8.RELEASE + 4.0.2.RELEASE 3.2.2.RELEASE - [3.2.0,5.0.0) - [3.2.1,5.0.0) 1.6 @@ -170,16 +168,6 @@ ${java.version} - - org.apache.maven.plugins - maven-idea-plugin - 2.3-atlassian-1 - - true - true - target/tomcat,target/war - - org.apache.maven.plugins maven-source-plugin @@ -253,66 +241,10 @@ - - com.springsource.bundlor - com.springsource.bundlor.maven - 1.0.0.RELEASE - - - bundlor - - bundlor - - - - - true - - - org.apache.tomcat.maven tomcat7-maven-plugin 2.2 - - maven-jar-plugin - - - target/classes/META-INF/MANIFEST.MF - - - - - - org.eclipse.m2e - lifecycle-mapping - 1.0.0 - - - - - - com.springsource.bundlor - com.springsource.bundlor.maven - [1.0,) - - bundlor - - - - - - - - - - org.apache.maven.plugins maven-release-plugin @@ -344,9 +276,9 @@ - org.springframework.build.aws - org.springframework.build.aws.maven - 3.0.0.RELEASE + org.springframework.build + aws-maven + 5.0.0.RELEASE @@ -406,19 +338,6 @@ - - - atlassian - https://maven.atlassian.com/repository/public - - - - repository.plugin.springsource.release - SpringSource Maven Repository - http://repository.springsource.com/maven/bundles/release - - - diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index e2e00bca1..ba8a9f8ab 100644 --- a/spring-security-oauth/pom.xml +++ b/spring-security-oauth/pom.xml @@ -44,10 +44,6 @@ - - com.springsource.bundlor - com.springsource.bundlor.maven - @@ -132,6 +128,14 @@ 1.3 + + javax.servlet + javax.servlet-api + + 3.0.1 + provided + + junit junit diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index cd0f1acde..a41a26d38 100644 --- a/spring-security-oauth2/pom.xml +++ b/spring-security-oauth2/pom.xml @@ -35,7 +35,7 @@ - + @@ -51,18 +51,15 @@ - - com.springsource.bundlor - com.springsource.bundlor.maven - javax.servlet - servlet-api - 2.5 + javax.servlet-api + + 3.0.1 provided From 19b5d6640f9760be58ab7b3df33c004ff3ded941 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 27 Mar 2014 15:55:15 +0000 Subject: [PATCH 190/831] Ignore .springBeans --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 3cc2e963f..4a96b9ffa 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ target/ .project .DS_Store .settings/ +.springBeans *.iml *.iws *.ipr From 55e7b5405b04b9c2d31e766b9725ae1222ecab1b Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 28 Mar 2014 11:58:20 +0000 Subject: [PATCH 191/831] Java 1.6 for JWT --- spring-security-jwt/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-security-jwt/pom.xml b/spring-security-jwt/pom.xml index 5e2f4199d..d061b10e3 100755 --- a/spring-security-jwt/pom.xml +++ b/spring-security-jwt/pom.xml @@ -94,8 +94,8 @@ maven-compiler-plugin 2.3.2 - 1.5 - 1.5 + 1.6 + 1.6 From ef8bf80d07807e7d9da49324c066c8603f288b02 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 28 Mar 2014 12:34:36 +0000 Subject: [PATCH 192/831] Fix XML validation --- .../Jackson2ArrayOrStringDeserializer.java | 42 +++++++++++++++++++ .../JacksonArrayOrStringDeserializer.java | 41 ++++++++++++++++++ ...rviceBeanDefinitionParserTests-context.xml | 2 +- ...ourceBeanDefinitionParserTests-context.xml | 2 +- .../config/xml/authorization-server-types.xml | 2 +- .../xml/authorization-server-vanilla.xml | 2 +- .../config/xml/resource-server-context.xml | 2 +- 7 files changed, 88 insertions(+), 5 deletions(-) create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/Jackson2ArrayOrStringDeserializer.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/JacksonArrayOrStringDeserializer.java diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/Jackson2ArrayOrStringDeserializer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/Jackson2ArrayOrStringDeserializer.java new file mode 100644 index 000000000..de1dca335 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/Jackson2ArrayOrStringDeserializer.java @@ -0,0 +1,42 @@ +package org.springframework.security.oauth2.provider; + +import java.io.IOException; +import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.Set; + +import org.springframework.util.StringUtils; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.type.SimpleType; + +public class Jackson2ArrayOrStringDeserializer extends StdDeserializer> { + + public Jackson2ArrayOrStringDeserializer() { + super(Set.class); + } + + @Override + public JavaType getValueType() { + return SimpleType.construct(String.class); + } + + @Override + public Set deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, + JsonProcessingException { + JsonToken token = jp.getCurrentToken(); + if (token.isScalarValue()) { + String list = jp.getText(); + list = list.replaceAll("\\s+", ","); + return new LinkedHashSet(Arrays.asList(StringUtils.commaDelimitedListToStringArray(list))); + } + return jp.readValueAs(new TypeReference>() { + }); + } +} \ No newline at end of file diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/JacksonArrayOrStringDeserializer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/JacksonArrayOrStringDeserializer.java new file mode 100644 index 000000000..7a53ec229 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/JacksonArrayOrStringDeserializer.java @@ -0,0 +1,41 @@ +package org.springframework.security.oauth2.provider; + +import java.io.IOException; +import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.Set; + +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.JsonToken; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.deser.std.StdDeserializer; +import org.codehaus.jackson.map.type.SimpleType; +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.type.TypeReference; +import org.springframework.util.StringUtils; + +public class JacksonArrayOrStringDeserializer extends StdDeserializer> { + + public JacksonArrayOrStringDeserializer() { + super(Set.class); + } + + @Override + public JavaType getValueType() { + return SimpleType.construct(String.class); + } + + @Override + public Set deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, + JsonProcessingException { + JsonToken token = jp.getCurrentToken(); + if (token.isScalarValue()) { + String list = jp.getText(); + list = list.replaceAll("\\s+", ","); + return new LinkedHashSet(Arrays.asList(StringUtils.commaDelimitedListToStringArray(list))); + } + return jp.readValueAs(new TypeReference>() { + }); + } +} \ No newline at end of file diff --git a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/ClientDetailsServiceBeanDefinitionParserTests-context.xml b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/ClientDetailsServiceBeanDefinitionParserTests-context.xml index 7747a9b0a..b142b6fa6 100644 --- a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/ClientDetailsServiceBeanDefinitionParserTests-context.xml +++ b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/ClientDetailsServiceBeanDefinitionParserTests-context.xml @@ -3,7 +3,7 @@ diff --git a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/ResourceBeanDefinitionParserTests-context.xml b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/ResourceBeanDefinitionParserTests-context.xml index 475093106..b9c65aebc 100644 --- a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/ResourceBeanDefinitionParserTests-context.xml +++ b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/ResourceBeanDefinitionParserTests-context.xml @@ -2,7 +2,7 @@ diff --git a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-types.xml b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-types.xml index fdd50d3f3..c56398ff5 100644 --- a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-types.xml +++ b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-types.xml @@ -4,7 +4,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:oauth="http://www.springframework.org/schema/security/oauth2" xmlns:security="http://www.springframework.org/schema/security" - xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2%20http://www.springframework.org/schema/security/spring-security-oauth2-1.0.xsd+xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> diff --git a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-vanilla.xml b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-vanilla.xml index e29ae8d94..a6fd3f9f2 100644 --- a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-vanilla.xml +++ b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-vanilla.xml @@ -2,7 +2,7 @@ diff --git a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/resource-server-context.xml b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/resource-server-context.xml index 4c6aca764..6bb483061 100644 --- a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/resource-server-context.xml +++ b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/resource-server-context.xml @@ -1,7 +1,7 @@ From 3fefee4173acccb909a3f0940ee9db258cebf365 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 28 Mar 2014 12:35:12 +0000 Subject: [PATCH 193/831] Remove unused @Suppress annotations --- .../oauth2/provider/authentication/BearerTokenExtractor.java | 1 - .../provider/endpoint/TokenEndpointAuthenticationFilter.java | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/BearerTokenExtractor.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/BearerTokenExtractor.java index 0c8e8d29d..437933dd3 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/BearerTokenExtractor.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/BearerTokenExtractor.java @@ -68,7 +68,6 @@ protected String extractToken(HttpServletRequest request) { * @return The token, or null if no OAuth authorization header was supplied. */ protected String extractHeaderToken(HttpServletRequest request) { - @SuppressWarnings("unchecked") Enumeration headers = request.getHeaders("Authorization"); while (headers.hasMoreElements()) { // typically there is only one (most servers enforce that) String value = headers.nextElement(); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java index 72d394134..f01295986 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java @@ -41,10 +41,10 @@ import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.oauth2.common.util.OAuth2Utils; -import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.AuthorizationRequest; -import org.springframework.security.oauth2.provider.OAuth2RequestFactory; +import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; @@ -178,7 +178,6 @@ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) private Map getSingleValueMap(HttpServletRequest request) { Map map = new HashMap(); - @SuppressWarnings("unchecked") Map parameters = request.getParameterMap(); for (String key : parameters.keySet()) { String[] values = parameters.get(key); From 56457735ce0230d541d6fcbc375f91cdbda4adf7 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 28 Mar 2014 12:35:35 +0000 Subject: [PATCH 194/831] Add Jackson2 support for BaseClientDetails --- .../provider/client/BaseClientDetails.java | 287 +++++++++--------- .../Jackson2ArrayOrStringDeserializer.java | 3 +- .../JacksonArrayOrStringDeserializer.java | 2 +- 3 files changed, 149 insertions(+), 143 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/BaseClientDetails.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/BaseClientDetails.java index 83539591e..a8ec566d9 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/BaseClientDetails.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/BaseClientDetails.java @@ -1,6 +1,5 @@ package org.springframework.security.oauth2.provider.client; -import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -12,72 +11,73 @@ import java.util.Map; import java.util.Set; -import org.codehaus.jackson.JsonParser; -import org.codehaus.jackson.JsonProcessingException; -import org.codehaus.jackson.JsonToken; -import org.codehaus.jackson.annotate.JsonAnyGetter; -import org.codehaus.jackson.annotate.JsonAnySetter; -import org.codehaus.jackson.annotate.JsonIgnore; -import org.codehaus.jackson.annotate.JsonIgnoreProperties; -import org.codehaus.jackson.annotate.JsonProperty; -import org.codehaus.jackson.map.DeserializationContext; -import org.codehaus.jackson.map.annotate.JsonDeserialize; -import org.codehaus.jackson.map.annotate.JsonSerialize; -import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion; -import org.codehaus.jackson.map.deser.std.StdDeserializer; -import org.codehaus.jackson.map.type.SimpleType; -import org.codehaus.jackson.type.JavaType; -import org.codehaus.jackson.type.TypeReference; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.util.StringUtils; /** - * Base implementation of {@link org.springframework.security.oauth2.provider.ClientDetails}. + * Base implementation of + * {@link org.springframework.security.oauth2.provider.ClientDetails}. * * @author Ryan Heaton * @author Dave Syer */ @SuppressWarnings("serial") -@JsonSerialize(include = Inclusion.NON_DEFAULT) -@JsonIgnoreProperties(ignoreUnknown = true) +@org.codehaus.jackson.map.annotate.JsonSerialize(include = org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion.NON_DEFAULT) +@org.codehaus.jackson.annotate.JsonIgnoreProperties(ignoreUnknown = true) +@com.fasterxml.jackson.annotation.JsonInclude(com.fasterxml.jackson.annotation.JsonInclude.Include.NON_DEFAULT) +@com.fasterxml.jackson.annotation.JsonIgnoreProperties(ignoreUnknown = true) public class BaseClientDetails implements ClientDetails { - @JsonProperty("client_id") + @org.codehaus.jackson.annotate.JsonProperty("client_id") + @com.fasterxml.jackson.annotation.JsonProperty("client_id") private String clientId; - @JsonProperty("client_secret") + @org.codehaus.jackson.annotate.JsonProperty("client_secret") + @com.fasterxml.jackson.annotation.JsonProperty("client_secret") private String clientSecret; - @JsonDeserialize(using = ArrayOrStringDeserializer.class) + @org.codehaus.jackson.map.annotate.JsonDeserialize(using = JacksonArrayOrStringDeserializer.class) + @com.fasterxml.jackson.databind.annotation.JsonDeserialize(using = Jackson2ArrayOrStringDeserializer.class) private Set scope = Collections.emptySet(); - @JsonProperty("resource_ids") - @JsonDeserialize(using = ArrayOrStringDeserializer.class) + @org.codehaus.jackson.annotate.JsonProperty("resource_ids") + @org.codehaus.jackson.map.annotate.JsonDeserialize(using = JacksonArrayOrStringDeserializer.class) + @com.fasterxml.jackson.annotation.JsonProperty("resource_ids") + @com.fasterxml.jackson.databind.annotation.JsonDeserialize(using = Jackson2ArrayOrStringDeserializer.class) private Set resourceIds = Collections.emptySet(); - @JsonProperty("authorized_grant_types") - @JsonDeserialize(using = ArrayOrStringDeserializer.class) + @org.codehaus.jackson.annotate.JsonProperty("authorized_grant_types") + @org.codehaus.jackson.map.annotate.JsonDeserialize(using = JacksonArrayOrStringDeserializer.class) + @com.fasterxml.jackson.annotation.JsonProperty("authorized_grant_types") + @com.fasterxml.jackson.databind.annotation.JsonDeserialize(using = Jackson2ArrayOrStringDeserializer.class) private Set authorizedGrantTypes = Collections.emptySet(); - @JsonProperty("redirect_uri") - @JsonDeserialize(using = ArrayOrStringDeserializer.class) + @org.codehaus.jackson.annotate.JsonProperty("redirect_uri") + @org.codehaus.jackson.map.annotate.JsonDeserialize(using = JacksonArrayOrStringDeserializer.class) + @com.fasterxml.jackson.annotation.JsonProperty("redirect_uri") + @com.fasterxml.jackson.databind.annotation.JsonDeserialize(using = Jackson2ArrayOrStringDeserializer.class) private Set registeredRedirectUris; - @JsonProperty("autoapprove") - @JsonDeserialize(using = ArrayOrStringDeserializer.class) + @org.codehaus.jackson.annotate.JsonProperty("autoapprove") + @org.codehaus.jackson.map.annotate.JsonDeserialize(using = JacksonArrayOrStringDeserializer.class) + @com.fasterxml.jackson.annotation.JsonProperty("autoapprove") + @com.fasterxml.jackson.databind.annotation.JsonDeserialize(using = Jackson2ArrayOrStringDeserializer.class) private Set autoApproveScopes; private List authorities = Collections.emptyList(); - @JsonProperty("access_token_validity") + @org.codehaus.jackson.annotate.JsonProperty("access_token_validity") + @com.fasterxml.jackson.annotation.JsonProperty("access_token_validity") private Integer accessTokenValiditySeconds; - @JsonProperty("refresh_token_validity") + @org.codehaus.jackson.annotate.JsonProperty("refresh_token_validity") + @com.fasterxml.jackson.annotation.JsonProperty("refresh_token_validity") private Integer refreshTokenValiditySeconds; - @JsonIgnore + @org.codehaus.jackson.annotate.JsonIgnore + @com.fasterxml.jackson.annotation.JsonIgnore private Map additionalInformation = new LinkedHashMap(); public BaseClientDetails() { @@ -86,7 +86,8 @@ public BaseClientDetails() { public BaseClientDetails(ClientDetails prototype) { this(); setAccessTokenValiditySeconds(prototype.getAccessTokenValiditySeconds()); - setRefreshTokenValiditySeconds(prototype.getRefreshTokenValiditySeconds()); + setRefreshTokenValiditySeconds(prototype + .getRefreshTokenValiditySeconds()); setAuthorities(prototype.getAuthorities()); setAuthorizedGrantTypes(prototype.getAuthorizedGrantTypes()); setClientId(prototype.getClientId()); @@ -96,17 +97,20 @@ public BaseClientDetails(ClientDetails prototype) { setResourceIds(prototype.getResourceIds()); } - public BaseClientDetails(String clientId, String resourceIds, String scopes, String grantTypes, String authorities) { + public BaseClientDetails(String clientId, String resourceIds, + String scopes, String grantTypes, String authorities) { this(clientId, resourceIds, scopes, grantTypes, authorities, null); } - public BaseClientDetails(String clientId, String resourceIds, String scopes, String grantTypes, String authorities, + public BaseClientDetails(String clientId, String resourceIds, + String scopes, String grantTypes, String authorities, String redirectUris) { this.clientId = clientId; if (StringUtils.hasText(resourceIds)) { - Set resources = StringUtils.commaDelimitedListToSet(resourceIds); + Set resources = StringUtils + .commaDelimitedListToSet(resourceIds); if (!resources.isEmpty()) { this.resourceIds = resources; } @@ -120,22 +124,26 @@ public BaseClientDetails(String clientId, String resourceIds, String scopes, Str } if (StringUtils.hasText(grantTypes)) { - this.authorizedGrantTypes = StringUtils.commaDelimitedListToSet(grantTypes); - } - else { - this.authorizedGrantTypes = new HashSet(Arrays.asList("authorization_code", "refresh_token")); + this.authorizedGrantTypes = StringUtils + .commaDelimitedListToSet(grantTypes); + } else { + this.authorizedGrantTypes = new HashSet(Arrays.asList( + "authorization_code", "refresh_token")); } if (StringUtils.hasText(authorities)) { - this.authorities = AuthorityUtils.commaSeparatedStringToAuthorityList(authorities); + this.authorities = AuthorityUtils + .commaSeparatedStringToAuthorityList(authorities); } if (StringUtils.hasText(redirectUris)) { - this.registeredRedirectUris = StringUtils.commaDelimitedListToSet(redirectUris); + this.registeredRedirectUris = StringUtils + .commaDelimitedListToSet(redirectUris); } } - @JsonIgnore + @org.codehaus.jackson.annotate.JsonIgnore + @com.fasterxml.jackson.annotation.JsonIgnore public String getClientId() { return clientId; } @@ -161,12 +169,14 @@ public boolean isAutoApprove(String scope) { return false; } - @JsonIgnore + @org.codehaus.jackson.annotate.JsonIgnore + @com.fasterxml.jackson.annotation.JsonIgnore public boolean isSecretRequired() { return this.clientSecret != null; } - @JsonIgnore + @org.codehaus.jackson.annotate.JsonIgnore + @com.fasterxml.jackson.annotation.JsonIgnore public String getClientSecret() { return clientSecret; } @@ -175,7 +185,8 @@ public void setClientSecret(String clientSecret) { this.clientSecret = clientSecret; } - @JsonIgnore + @org.codehaus.jackson.annotate.JsonIgnore + @com.fasterxml.jackson.annotation.JsonIgnore public boolean isScoped() { return this.scope != null && !this.scope.isEmpty(); } @@ -185,85 +196,74 @@ public Set getScope() { } public void setScope(Collection scope) { - this.scope = scope == null ? Collections. emptySet() : new LinkedHashSet(scope); + this.scope = scope == null ? Collections. emptySet() + : new LinkedHashSet(scope); } - @JsonIgnore + @org.codehaus.jackson.annotate.JsonIgnore + @com.fasterxml.jackson.annotation.JsonIgnore public Set getResourceIds() { return resourceIds; } public void setResourceIds(Collection resourceIds) { - this.resourceIds = resourceIds == null ? Collections. emptySet() : new LinkedHashSet( - resourceIds); + this.resourceIds = resourceIds == null ? Collections + . emptySet() : new LinkedHashSet(resourceIds); } - @JsonIgnore + @org.codehaus.jackson.annotate.JsonIgnore + @com.fasterxml.jackson.annotation.JsonIgnore public Set getAuthorizedGrantTypes() { return authorizedGrantTypes; } public void setAuthorizedGrantTypes(Collection authorizedGrantTypes) { - this.authorizedGrantTypes = new LinkedHashSet(authorizedGrantTypes); + this.authorizedGrantTypes = new LinkedHashSet( + authorizedGrantTypes); } - @JsonIgnore + @org.codehaus.jackson.annotate.JsonIgnore + @com.fasterxml.jackson.annotation.JsonIgnore public Set getRegisteredRedirectUri() { return registeredRedirectUris; } public void setRegisteredRedirectUri(Set registeredRedirectUris) { - this.registeredRedirectUris = registeredRedirectUris == null ? null : new LinkedHashSet( - registeredRedirectUris); + this.registeredRedirectUris = registeredRedirectUris == null ? null + : new LinkedHashSet(registeredRedirectUris); } - @JsonProperty("authorities") + @org.codehaus.jackson.annotate.JsonProperty("authorities") + @com.fasterxml.jackson.annotation.JsonProperty("authorities") private List getAuthoritiesAsStrings() { - return new ArrayList(AuthorityUtils.authorityListToSet(authorities)); + return new ArrayList( + AuthorityUtils.authorityListToSet(authorities)); } - @JsonProperty("authorities") - @JsonDeserialize(using = ArrayOrStringDeserializer.class) + @org.codehaus.jackson.annotate.JsonProperty("authorities") + @org.codehaus.jackson.map.annotate.JsonDeserialize(using = JacksonArrayOrStringDeserializer.class) + @com.fasterxml.jackson.annotation.JsonProperty("authorities") + @com.fasterxml.jackson.databind.annotation.JsonDeserialize(using = Jackson2ArrayOrStringDeserializer.class) private void setAuthoritiesAsStrings(Set values) { - setAuthorities(AuthorityUtils.createAuthorityList(values.toArray(new String[values.size()]))); - } - - public static class ArrayOrStringDeserializer extends StdDeserializer> { - - public ArrayOrStringDeserializer() { - super(Set.class); - } - - @Override - public JavaType getValueType() { - return SimpleType.construct(String.class); - } - - @Override - public Set deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, - JsonProcessingException { - JsonToken token = jp.getCurrentToken(); - if (token.isScalarValue()) { - String list = jp.getText(); - list = list.replaceAll("\\s+", ","); - return new LinkedHashSet(Arrays.asList(StringUtils.commaDelimitedListToStringArray(list))); - } - return jp.readValueAs(new TypeReference>() { - }); - } + setAuthorities(AuthorityUtils.createAuthorityList(values + .toArray(new String[values.size()]))); } - @JsonIgnore + @org.codehaus.jackson.annotate.JsonIgnore + @com.fasterxml.jackson.annotation.JsonIgnore public Collection getAuthorities() { return authorities; } - @JsonIgnore - public void setAuthorities(Collection authorities) { + @org.codehaus.jackson.annotate.JsonIgnore + @com.fasterxml.jackson.annotation.JsonIgnore + public void setAuthorities( + Collection authorities) { this.authorities = new ArrayList(authorities); } - @JsonIgnore + @org.codehaus.jackson.annotate.JsonIgnore + @com.fasterxml.jackson.annotation.JsonIgnore public Integer getAccessTokenValiditySeconds() { return accessTokenValiditySeconds; } @@ -272,25 +272,30 @@ public void setAccessTokenValiditySeconds(Integer accessTokenValiditySeconds) { this.accessTokenValiditySeconds = accessTokenValiditySeconds; } - @JsonIgnore + @org.codehaus.jackson.annotate.JsonIgnore + @com.fasterxml.jackson.annotation.JsonIgnore public Integer getRefreshTokenValiditySeconds() { return refreshTokenValiditySeconds; } - public void setRefreshTokenValiditySeconds(Integer refreshTokenValiditySeconds) { + public void setRefreshTokenValiditySeconds( + Integer refreshTokenValiditySeconds) { this.refreshTokenValiditySeconds = refreshTokenValiditySeconds; } public void setAdditionalInformation(Map additionalInformation) { - this.additionalInformation = new LinkedHashMap(additionalInformation); + this.additionalInformation = new LinkedHashMap( + additionalInformation); } - @JsonAnyGetter + @org.codehaus.jackson.annotate.JsonAnyGetter + @com.fasterxml.jackson.annotation.JsonAnyGetter public Map getAdditionalInformation() { return Collections.unmodifiableMap(this.additionalInformation); } - @JsonAnySetter + @org.codehaus.jackson.annotate.JsonAnySetter + @com.fasterxml.jackson.annotation.JsonAnySetter public void addAdditionalInformation(String key, Object value) { this.additionalInformation.put(key, value); } @@ -299,14 +304,30 @@ public void addAdditionalInformation(String key, Object value) { public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + ((accessTokenValiditySeconds == null) ? 0 : accessTokenValiditySeconds); - result = prime * result + ((refreshTokenValiditySeconds == null) ? 0 : refreshTokenValiditySeconds); - result = prime * result + ((authorities == null) ? 0 : authorities.hashCode()); - result = prime * result + ((authorizedGrantTypes == null) ? 0 : authorizedGrantTypes.hashCode()); - result = prime * result + ((clientId == null) ? 0 : clientId.hashCode()); - result = prime * result + ((clientSecret == null) ? 0 : clientSecret.hashCode()); - result = prime * result + ((registeredRedirectUris == null) ? 0 : registeredRedirectUris.hashCode()); - result = prime * result + ((resourceIds == null) ? 0 : resourceIds.hashCode()); + result = prime + * result + + ((accessTokenValiditySeconds == null) ? 0 + : accessTokenValiditySeconds); + result = prime + * result + + ((refreshTokenValiditySeconds == null) ? 0 + : refreshTokenValiditySeconds); + result = prime * result + + ((authorities == null) ? 0 : authorities.hashCode()); + result = prime + * result + + ((authorizedGrantTypes == null) ? 0 : authorizedGrantTypes + .hashCode()); + result = prime * result + + ((clientId == null) ? 0 : clientId.hashCode()); + result = prime * result + + ((clientSecret == null) ? 0 : clientSecret.hashCode()); + result = prime + * result + + ((registeredRedirectUris == null) ? 0 + : registeredRedirectUris.hashCode()); + result = prime * result + + ((resourceIds == null) ? 0 : resourceIds.hashCode()); result = prime * result + ((scope == null) ? 0 : scope.hashCode()); result = prime * result + additionalInformation.hashCode(); return result; @@ -321,80 +342,64 @@ public boolean equals(Object obj) { if (getClass() != obj.getClass()) return false; BaseClientDetails other = (BaseClientDetails) obj; - if (accessTokenValiditySeconds == null) { - if (other.accessTokenValiditySeconds != null) { - return false; - } - } - else { - return accessTokenValiditySeconds.equals(other.accessTokenValiditySeconds); - } - if (refreshTokenValiditySeconds == null) { - if (other.refreshTokenValiditySeconds != null) { - return false; - } - } - else { - return refreshTokenValiditySeconds.equals(other.refreshTokenValiditySeconds); - } + if (accessTokenValiditySeconds != other.accessTokenValiditySeconds) + return false; + if (refreshTokenValiditySeconds != other.refreshTokenValiditySeconds) + return false; if (authorities == null) { if (other.authorities != null) return false; - } - else if (!authorities.equals(other.authorities)) + } else if (!authorities.equals(other.authorities)) return false; if (authorizedGrantTypes == null) { if (other.authorizedGrantTypes != null) return false; - } - else if (!authorizedGrantTypes.equals(other.authorizedGrantTypes)) + } else if (!authorizedGrantTypes.equals(other.authorizedGrantTypes)) return false; if (clientId == null) { if (other.clientId != null) return false; - } - else if (!clientId.equals(other.clientId)) + } else if (!clientId.equals(other.clientId)) return false; if (clientSecret == null) { if (other.clientSecret != null) return false; - } - else if (!clientSecret.equals(other.clientSecret)) + } else if (!clientSecret.equals(other.clientSecret)) return false; if (registeredRedirectUris == null) { if (other.registeredRedirectUris != null) return false; - } - else if (!registeredRedirectUris.equals(other.registeredRedirectUris)) + } else if (!registeredRedirectUris.equals(other.registeredRedirectUris)) return false; if (resourceIds == null) { if (other.resourceIds != null) return false; - } - else if (!resourceIds.equals(other.resourceIds)) + } else if (!resourceIds.equals(other.resourceIds)) return false; if (scope == null) { if (other.scope != null) return false; - } - else if (!scope.equals(other.scope)) + } else if (!scope.equals(other.scope)) return false; if (additionalInformation == null) { if (other.additionalInformation != null) return false; - } - else if (!additionalInformation.equals(other.additionalInformation)) + } else if (!additionalInformation.equals(other.additionalInformation)) return false; return true; } @Override public String toString() { - return "BaseClientDetails [clientId=" + clientId + ", clientSecret=" + clientSecret + ", scope=" + scope - + ", resourceIds=" + resourceIds + ", authorizedGrantTypes=" + authorizedGrantTypes - + ", registeredRedirectUris=" + registeredRedirectUris + ", authorities=" + authorities - + ", accessTokenValiditySeconds=" + accessTokenValiditySeconds + ", refreshTokenValiditySeconds=" - + refreshTokenValiditySeconds + ", additionalInformation=" + additionalInformation + "]"; + return "BaseClientDetails [clientId=" + clientId + ", clientSecret=" + + clientSecret + ", scope=" + scope + ", resourceIds=" + + resourceIds + ", authorizedGrantTypes=" + + authorizedGrantTypes + ", registeredRedirectUris=" + + registeredRedirectUris + ", authorities=" + authorities + + ", accessTokenValiditySeconds=" + accessTokenValiditySeconds + + ", refreshTokenValiditySeconds=" + + refreshTokenValiditySeconds + ", additionalInformation=" + + additionalInformation + "]"; } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/Jackson2ArrayOrStringDeserializer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/Jackson2ArrayOrStringDeserializer.java index de1dca335..20698f491 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/Jackson2ArrayOrStringDeserializer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/Jackson2ArrayOrStringDeserializer.java @@ -1,4 +1,4 @@ -package org.springframework.security.oauth2.provider; +package org.springframework.security.oauth2.provider.client; import java.io.IOException; import java.util.Arrays; @@ -16,6 +16,7 @@ import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.type.SimpleType; +@SuppressWarnings("serial") public class Jackson2ArrayOrStringDeserializer extends StdDeserializer> { public Jackson2ArrayOrStringDeserializer() { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/JacksonArrayOrStringDeserializer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/JacksonArrayOrStringDeserializer.java index 7a53ec229..18677562a 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/JacksonArrayOrStringDeserializer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/JacksonArrayOrStringDeserializer.java @@ -1,4 +1,4 @@ -package org.springframework.security.oauth2.provider; +package org.springframework.security.oauth2.provider.client; import java.io.IOException; import java.util.Arrays; From 5819960ad985e45e5c47f6d4e232b7eb8c31ce67 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 28 Mar 2014 14:32:50 +0000 Subject: [PATCH 195/831] Updgrade to Spring 4.0.3 --- pom.xml | 4 ++-- samples/oauth2/sparklr/pom.xml | 6 +++--- .../oauth/examples/sparklr/config/WebMvcConfig.java | 5 ++--- spring-security-oauth/src/test/resources/data.sql | 1 + spring-security-oauth2/src/test/resources/data.sql | 1 + 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index 7acacd4fd..e5654dcd5 100644 --- a/pom.xml +++ b/pom.xml @@ -16,8 +16,8 @@ UTF-8 - 4.0.2.RELEASE - 3.2.2.RELEASE + 4.0.3.RELEASE + 3.2.3.RELEASE 1.6 diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 344babe7d..f86461c2a 100644 --- a/samples/oauth2/sparklr/pom.xml +++ b/samples/oauth2/sparklr/pom.xml @@ -159,9 +159,9 @@ - org.codehaus.jackson - jackson-mapper-asl - 1.9.13 + com.fasterxml.jackson.core + jackson-databind + 2.3.1 diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/WebMvcConfig.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/WebMvcConfig.java index b65415129..d0394fbeb 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/WebMvcConfig.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/WebMvcConfig.java @@ -27,7 +27,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.view.ContentNegotiatingViewResolver; import org.springframework.web.servlet.view.InternalResourceViewResolver; -import org.springframework.web.servlet.view.json.MappingJacksonJsonView; +import org.springframework.web.servlet.view.json.MappingJackson2JsonView; @Configuration @EnableWebMvc @@ -47,12 +47,11 @@ public ContentNegotiatingViewResolver contentViewResolver() throws Exception { viewResolver.setPrefix("/WEB-INF/jsp/"); viewResolver.setSuffix(".jsp"); - MappingJacksonJsonView defaultView = new MappingJacksonJsonView(); + MappingJackson2JsonView defaultView = new MappingJackson2JsonView(); defaultView.setExtractValueFromSingleKeyModel(true); ContentNegotiatingViewResolver contentViewResolver = new ContentNegotiatingViewResolver(); contentViewResolver.setContentNegotiationManager(contentNegotiationManager.getObject()); - contentViewResolver.setDefaultViews(Arrays.asList(new MappingJacksonJsonView())); contentViewResolver.setViewResolvers(Arrays.asList(viewResolver)); contentViewResolver.setDefaultViews(Arrays.asList(defaultView)); return contentViewResolver; diff --git a/spring-security-oauth/src/test/resources/data.sql b/spring-security-oauth/src/test/resources/data.sql index e69de29bb..2ea0468f0 100644 --- a/spring-security-oauth/src/test/resources/data.sql +++ b/spring-security-oauth/src/test/resources/data.sql @@ -0,0 +1 @@ +select * from oauth_client_details; \ No newline at end of file diff --git a/spring-security-oauth2/src/test/resources/data.sql b/spring-security-oauth2/src/test/resources/data.sql index e69de29bb..2ea0468f0 100644 --- a/spring-security-oauth2/src/test/resources/data.sql +++ b/spring-security-oauth2/src/test/resources/data.sql @@ -0,0 +1 @@ +select * from oauth_client_details; \ No newline at end of file From ef27402b9662702b5d90d00439d95ceb70df9ec1 Mon Sep 17 00:00:00 2001 From: Rob Winch Date: Thu, 14 Jun 2012 18:00:30 -0500 Subject: [PATCH 196/831] Created OAuth2ExpressionParser that automatically wraps a Spring Expression ... with a method that provides meaningful errors. This allows Spring Security OAuth to check for errors and throw Excepions when an error occurs while ensuring that the exception is only thrown when necessary. For example, if an expression has an or statment we do not want to throw the Exception if only part of the expression is false. Fixes gh-41, Fixes gh-118 --- .../expression/OAuth2ExpressionParser.java | 57 ++++++++++++ ...OAuth2MethodSecurityExpressionHandler.java | 26 +++--- .../OAuth2SecurityExpressionMethods.java | 39 ++++---- .../OAuth2WebSecurityExpressionHandler.java | 26 +++--- .../OAuth2ExpressionParserTests.java | 52 +++++++++++ ...2MethodSecurityExpressionHandlerTests.java | 89 ++++++++++++++----- .../OAuth2SecurityExpressionMethodsTests.java | 48 +++++----- ...uth2WebSecurityExpressionHandlerTests.java | 56 ++++++++++-- 8 files changed, 288 insertions(+), 105 deletions(-) create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionParser.java create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionParserTests.java diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionParser.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionParser.java new file mode 100644 index 000000000..571d8c013 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionParser.java @@ -0,0 +1,57 @@ +/* + * 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.expression; + +import org.springframework.expression.Expression; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.ParseException; +import org.springframework.expression.ParserContext; +import org.springframework.util.Assert; + +/** + *

+ * A custom {@link ExpressionParser} that automatically wraps SpEL expression with + * {@link OAuth2SecurityExpressionMethods#throwOnError(boolean)}. This makes it simple for users to specify an + * expression and then have it verified (providing errors) after the result of the expression is known. + *

+ *

+ * Note: The implication is that all expressions that are parsed must return a boolean result. This expectation is + * already true since Spring Security expects the result to be a boolean. + *

+ * + * @author Rob Winch + * + */ +final class OAuth2ExpressionParser implements ExpressionParser { + private final ExpressionParser delegate; + + public OAuth2ExpressionParser(ExpressionParser delegate) { + Assert.notNull(delegate, "delegate cannot be null"); + this.delegate = delegate; + } + + public Expression parseExpression(String expressionString) throws ParseException { + return delegate.parseExpression(wrapExpression(expressionString)); + } + + public Expression parseExpression(String expressionString, ParserContext context) throws ParseException { + return delegate.parseExpression(wrapExpression(expressionString), context); + } + + private String wrapExpression(String expressionString) { + return "#oauth2.throwOnError(" + expressionString + ")"; + } +} \ No newline at end of file diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2MethodSecurityExpressionHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2MethodSecurityExpressionHandler.java index a64524ba9..cf9da9385 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2MethodSecurityExpressionHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2MethodSecurityExpressionHandler.java @@ -1,38 +1,36 @@ package org.springframework.security.oauth2.provider.expression; import org.aopalliance.intercept.MethodInvocation; +import org.springframework.expression.ExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler; import org.springframework.security.core.Authentication; /** + *

* A security expression handler that can handle default method security expressions plus the set provided by * {@link OAuth2SecurityExpressionMethods} using the variable oauth2 to access the methods. For example, the expression * #oauth2.clientHasRole('ROLE_ADMIN') would invoke {@link OAuth2SecurityExpressionMethods#clientHasRole} - * + *

+ *

+ * By default the {@link OAuth2ExpressionParser} is used. If this is undesirable one can inject their own + * {@link ExpressionParser} using {@link #setExpressionParser(ExpressionParser)}. + *

+ * * @author Dave Syer * @author Rob Winch + * @see OAuth2ExpressionParser */ public class OAuth2MethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler { - - private boolean throwExceptionOnInvalidScope = true; - /** - * Flag to determine the behaviour on access denied if the reason is . If set then we throw an - * {@link InvalidScopeException} instead of returning true. This is unconventional for an access decision because it - * vetos the other voters in the chain, but it enables us to pass a message to the caller with information about the - * required scope. - * - * @param throwException the flag to set (default true) - */ - public void setThrowExceptionOnInvalidScope(boolean throwException) { - this.throwExceptionOnInvalidScope = throwException; + public OAuth2MethodSecurityExpressionHandler() { + setExpressionParser(new OAuth2ExpressionParser(getExpressionParser())); } @Override public StandardEvaluationContext createEvaluationContextInternal(Authentication authentication, MethodInvocation mi) { StandardEvaluationContext ec = super.createEvaluationContextInternal(authentication, mi); - ec.setVariable("oauth2", new OAuth2SecurityExpressionMethods(authentication, throwExceptionOnInvalidScope)); + ec.setVariable("oauth2", new OAuth2SecurityExpressionMethods(authentication)); return ec; } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethods.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethods.java index d9bb325a6..7a0e3262b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethods.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethods.java @@ -37,25 +37,33 @@ public class OAuth2SecurityExpressionMethods { private Set missingScopes = new LinkedHashSet(); - private boolean throwExceptionOnInvalidScope; - - public OAuth2SecurityExpressionMethods(Authentication authentication, boolean throwExceptionOnInvalidScope) { + public OAuth2SecurityExpressionMethods(Authentication authentication) { this.authentication = authentication; - this.throwExceptionOnInvalidScope = throwExceptionOnInvalidScope; } /** - * Check if any scope decisions have been denied in the current context and throw an exception if so. Example usage: + * Check if any scope decisions have been denied in the current context and throw an exception if so. This method + * automatically wraps any expressions when using {@link OAuth2MethodSecurityExpressionHandler} or + * {@link OAuth2WebSecurityExpressionHandler}. + * + * OAuth2Example usage: + * + *
+	 * access = "#oauth2.hasScope('read') or (#oauth2.hasScope('other') and hasRole('ROLE_USER'))"
+	 * 
+ * + * Will automatically be wrapped to ensure that explicit errors are propagated rather than a generic error when + * returning false: * *
-	 * access = "#oauth2.sufficientScope(#oauth2.hasScope('read') or (#oauth2.hasScope('other') and hasRole('ROLE_USER')))"
+	 * access = "#oauth2.throwOnError(#oauth2.hasScope('read') or (#oauth2.hasScope('other') and hasRole('ROLE_USER'))"
 	 * 
* * @param decision the existing access decision * @return true if the OAuth2 token has one of these scopes * @throws InsufficientScopeException if the scope is invalid and we the flag is set to throw the exception */ - public boolean sufficientScope(boolean decision) { + public boolean throwOnError(boolean decision) { if (!decision && !missingScopes.isEmpty()) { throw new InsufficientScopeException("Insufficient scope for this resource", missingScopes); } @@ -103,10 +111,8 @@ public boolean hasScope(String scope) { */ public boolean hasAnyScope(String... scopes) { boolean result = OAuth2ExpressionUtils.hasAnyScope(authentication, scopes); - if (!result && throwExceptionOnInvalidScope) { + if (!result) { missingScopes.addAll(Arrays.asList(scopes)); - Throwable failure = new InsufficientScopeException("Insufficient scope for this resource", missingScopes); - throw new AccessDeniedException(failure.getMessage(), failure); } return result; } @@ -142,10 +148,8 @@ public boolean hasScopeMatching(String scopeRegex) { public boolean hasAnyScopeMatching(String... scopesRegex) { boolean result = OAuth2ExpressionUtils.hasAnyScopeMatching(authentication, scopesRegex); - if (!result && throwExceptionOnInvalidScope) { + if (!result) { missingScopes.addAll(Arrays.asList(scopesRegex)); - Throwable failure = new InsufficientScopeException("Insufficient scope for this resource", missingScopes); - throw new AccessDeniedException(failure.getMessage(), failure); } return result; } @@ -185,13 +189,4 @@ public boolean isUser() { public boolean isClient() { return OAuth2ExpressionUtils.isOAuthClientAuth(authentication); } - - /** - * A flag to indicate that an exception should be thrown if a scope decision is negative. - * - * @param throwExceptionOnInvalidScope flag value (default true) - */ - public void setThrowExceptionOnInvalidScope(boolean throwExceptionOnInvalidScope) { - this.throwExceptionOnInvalidScope = throwExceptionOnInvalidScope; - } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2WebSecurityExpressionHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2WebSecurityExpressionHandler.java index 7b5bd0c70..f4e458373 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2WebSecurityExpressionHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2WebSecurityExpressionHandler.java @@ -12,40 +12,38 @@ */ package org.springframework.security.oauth2.provider.expression; +import org.springframework.expression.ExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.security.core.Authentication; import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler; /** + *

* A security expression handler that can handle default web security expressions plus the set provided by * {@link OAuth2SecurityExpressionMethods} using the variable oauth2 to access the methods. For example, the expression * #oauth2.clientHasRole('ROLE_ADMIN') would invoke {@link OAuth2SecurityExpressionMethods#clientHasRole}. + *

+ *

+ * By default the {@link OAuth2ExpressionParser} is used. If this is undesirable one can inject their own + * {@link ExpressionParser} using {@link #setExpressionParser(ExpressionParser)}. + *

* * @author Dave Syer * @author Rob Winch * + * @see OAuth2ExpressionParser */ public class OAuth2WebSecurityExpressionHandler extends DefaultWebSecurityExpressionHandler { - private boolean throwExceptionOnInvalidScope = true; - - /** - * Flag to determine the behaviour on access denied if the reason is . If set then we throw an - * {@link InvalidScopeException} instead of returning true. This is unconventional for an access decision because it - * vetos the other voters in the chain, but it enables us to pass a message to the caller with information about the - * required scope. - * - * @param throwException the flag to set (default true) - */ - public void setThrowExceptionOnInvalidScope(boolean throwException) { - this.throwExceptionOnInvalidScope = throwException; + public OAuth2WebSecurityExpressionHandler() { + setExpressionParser(new OAuth2ExpressionParser(getExpressionParser())); } - + @Override protected StandardEvaluationContext createEvaluationContextInternal(Authentication authentication, FilterInvocation invocation) { StandardEvaluationContext ec = super.createEvaluationContextInternal(authentication, invocation); - ec.setVariable("oauth2", new OAuth2SecurityExpressionMethods(authentication, throwExceptionOnInvalidScope)); + ec.setVariable("oauth2", new OAuth2SecurityExpressionMethods(authentication)); return ec; } } \ No newline at end of file diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionParserTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionParserTests.java new file mode 100644 index 000000000..67dd495d0 --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionParserTests.java @@ -0,0 +1,52 @@ +package org.springframework.security.oauth2.provider.expression; + +import static org.mockito.Mockito.verify; + +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.expression.ExpressionParser; +import org.springframework.expression.ParserContext; + +/** + * + * @author Rob Winch + * + */ +@RunWith(MockitoJUnitRunner.class) +public class OAuth2ExpressionParserTests { + @Mock + private ExpressionParser delegate; + @Mock + private ParserContext parserContext; + + private final String expressionString = "ORIGIONAL"; + + private final String wrappedExpression = "#oauth2.throwOnError(" + expressionString + ")"; + + private OAuth2ExpressionParser parser; + + @Before + public void setUp() { + parser = new OAuth2ExpressionParser(delegate); + } + + @Test(expected = IllegalArgumentException.class) + public void constructorNull() { + new OAuth2ExpressionParser(null); + } + + @Test + public void parseExpression() { + parser.parseExpression(expressionString); + verify(delegate).parseExpression(wrappedExpression); + } + + @Test + public void parseExpressionWithContext() { + parser.parseExpression(expressionString, parserContext); + verify(delegate).parseExpression(wrappedExpression, parserContext); + } +} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2MethodSecurityExpressionHandlerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2MethodSecurityExpressionHandlerTests.java index df45e1332..08c9b5fff 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2MethodSecurityExpressionHandlerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2MethodSecurityExpressionHandlerTests.java @@ -25,9 +25,10 @@ import org.junit.Test; import org.springframework.expression.EvaluationContext; import org.springframework.expression.Expression; -import org.springframework.security.access.AccessDeniedException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.oauth2.common.exceptions.InsufficientScopeException; import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; @@ -45,17 +46,52 @@ public class OAuth2MethodSecurityExpressionHandlerTests { private OAuth2MethodSecurityExpressionHandler handler = new OAuth2MethodSecurityExpressionHandler(); + @Test + public void testScopesWithOr() throws Exception { + AuthorizationRequest request = new AuthorizationRequest("foo", Collections.singleton("read")); + request.setResourceIdsAndAuthoritiesFromClientDetails(new BaseClientDetails("foo", "bar", "", + "client_credentials", "ROLE_CLIENT")); + request.setApproved(true); + OAuth2Request clientAuthentication = request.createOAuth2Request(); + Authentication userAuthentication = new UsernamePasswordAuthenticationToken("user", "pass", + AuthorityUtils.createAuthorityList("ROLE_USER")); + OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); + MethodInvocation invocation = new SimpleMethodInvocation(this, ReflectionUtils.findMethod(getClass(), + "testOauthClient")); + EvaluationContext context = handler.createEvaluationContext(oAuth2Authentication, invocation); + Expression expression = handler.getExpressionParser().parseExpression( + "#oauth2.hasAnyScope('write') or #oauth2.isUser()"); + assertTrue((Boolean) expression.getValue(context)); + } + + @Test(expected = InsufficientScopeException.class) + public void testScopesInsufficient() throws Exception { + AuthorizationRequest request = new AuthorizationRequest("foo", Collections.singleton("read")); + request.setResourceIdsAndAuthoritiesFromClientDetails(new BaseClientDetails("foo", "bar", "", + "client_credentials", "ROLE_CLIENT")); + OAuth2Request clientAuthentication = request.createOAuth2Request(); + Authentication userAuthentication = new UsernamePasswordAuthenticationToken("user", "pass", + AuthorityUtils.createAuthorityList("ROLE_USER")); + OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); + MethodInvocation invocation = new SimpleMethodInvocation(this, ReflectionUtils.findMethod(getClass(), + "testOauthClient")); + EvaluationContext context = handler.createEvaluationContext(oAuth2Authentication, invocation); + Expression expression = handler.getExpressionParser().parseExpression("#oauth2.hasAnyScope('write')"); + expression.getValue(context); + } + @Test public void testOauthClient() throws Exception { - AuthorizationRequest request = new AuthorizationRequest("foo", - Collections.singleton("read")); - request - .setResourceIdsAndAuthoritiesFromClientDetails(new BaseClientDetails("foo", "", "", "client_credentials", "ROLE_CLIENT")); + AuthorizationRequest request = new AuthorizationRequest("foo", Collections.singleton("read")); + request.setResourceIdsAndAuthoritiesFromClientDetails(new BaseClientDetails("foo", "", "", + "client_credentials", "ROLE_CLIENT")); Authentication userAuthentication = null; - - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(request.getRequestParameters(), request.getClientId(), request.getAuthorities(), request.isApproved(), request.getScope(), request.getResourceIds(), - request.getRedirectUri(), request.getResponseTypes(), request.getExtensions()); - + + OAuth2Request clientAuthentication = RequestTokenFactory + .createOAuth2Request(request.getRequestParameters(), request.getClientId(), request.getAuthorities(), + request.isApproved(), request.getScope(), request.getResourceIds(), request.getRedirectUri(), + request.getResponseTypes(), request.getExtensions()); + OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); MethodInvocation invocation = new SimpleMethodInvocation(this, ReflectionUtils.findMethod(getClass(), "testOauthClient")); @@ -67,9 +103,10 @@ public void testOauthClient() throws Exception { @Test public void testScopes() throws Exception { - - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null, null); - + + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, + Collections.singleton("read"), null, null, null, null); + Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); MethodInvocation invocation = new SimpleMethodInvocation(this, ReflectionUtils.findMethod(getClass(), @@ -82,30 +119,35 @@ public void testScopes() throws Exception { @Test public void testScopesRegex() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("ns_admin:read"), null, null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, + Collections.singleton("ns_admin:read"), null, null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); MethodInvocation invocation = new SimpleMethodInvocation(this, ReflectionUtils.findMethod(getClass(), - "testOauthClient")); + "testOauthClient")); EvaluationContext context = handler.createEvaluationContext(oAuth2Authentication, invocation); - Expression expression = handler.getExpressionParser().parseExpression("#oauth2.hasScopeMatching('.*_admin:read')"); + Expression expression = handler.getExpressionParser().parseExpression( + "#oauth2.hasScopeMatching('.*_admin:read')"); assertTrue((Boolean) expression.getValue(context)); - expression = handler.getExpressionParser().parseExpression("#oauth2.hasAnyScopeMatching('.*_admin:write','.*_admin:read')"); + expression = handler.getExpressionParser().parseExpression( + "#oauth2.hasAnyScopeMatching('.*_admin:write','.*_admin:read')"); assertTrue((Boolean) expression.getValue(context)); } - @Test(expected = AccessDeniedException.class) + @Test(expected = InsufficientScopeException.class) public void testScopesRegexThrowsException() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("ns_admin:read"), null, null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, + Collections.singleton("ns_admin:read"), null, null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); MethodInvocation invocation = new SimpleMethodInvocation(this, ReflectionUtils.findMethod(getClass(), - "testOauthClient")); + "testOauthClient")); EvaluationContext context = handler.createEvaluationContext(oAuth2Authentication, invocation); - Expression expression = handler.getExpressionParser().parseExpression("#oauth2.hasScopeMatching('.*_admin:write')"); + Expression expression = handler.getExpressionParser().parseExpression( + "#oauth2.hasScopeMatching('.*_admin:write')"); assertFalse((Boolean) expression.getValue(context)); } @@ -138,9 +180,10 @@ public void testReEvaluationWithDifferentRoot() throws Exception { Authentication clientAuthentication = new UsernamePasswordAuthenticationToken("foo", "bar"); EvaluationContext context = handler.createEvaluationContext(clientAuthentication, invocation); assertFalse((Boolean) expression.getValue(context)); - - OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "foo", null, true, Collections.singleton("read"), null, null, null, null); - + + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "foo", null, true, + Collections.singleton("read"), null, null, null, null); + OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(storedOAuth2Request, null); EvaluationContext anotherContext = handler.createEvaluationContext(oAuth2Authentication, invocation); assertTrue((Boolean) expression.getValue(anotherContext)); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethodsTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethodsTests.java index b45139d2d..f89bf9c2f 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethodsTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethodsTests.java @@ -22,14 +22,14 @@ import java.util.Collections; import org.junit.Test; -import org.springframework.security.access.AccessDeniedException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.common.exceptions.InsufficientScopeException; import org.springframework.security.oauth2.provider.AuthorizationRequest; -import org.springframework.security.oauth2.provider.RequestTokenFactory; +import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.RequestTokenFactory; import org.springframework.security.oauth2.provider.client.BaseClientDetails; /** @@ -50,7 +50,7 @@ public void testOauthClient() throws Exception { request.getRedirectUri(), request.getResponseTypes(), request.getExtensions()); OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); - assertTrue(new OAuth2SecurityExpressionMethods(oAuth2Authentication, true).clientHasAnyRole("ROLE_CLIENT")); + assertTrue(new OAuth2SecurityExpressionMethods(oAuth2Authentication).clientHasAnyRole("ROLE_CLIENT")); } @Test @@ -59,7 +59,7 @@ public void testScopes() throws Exception { Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); - OAuth2SecurityExpressionMethods root = new OAuth2SecurityExpressionMethods(oAuth2Authentication, false); + OAuth2SecurityExpressionMethods root = new OAuth2SecurityExpressionMethods(oAuth2Authentication); assertTrue(root.hasAnyScope("read")); } @@ -69,27 +69,30 @@ public void testScopesFalse() throws Exception { Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); - OAuth2SecurityExpressionMethods root = new OAuth2SecurityExpressionMethods(oAuth2Authentication, false); + OAuth2SecurityExpressionMethods root = new OAuth2SecurityExpressionMethods(oAuth2Authentication); assertFalse(root.hasAnyScope("write")); } - @Test(expected = AccessDeniedException.class) + @Test(expected = InsufficientScopeException.class) public void testScopesWithException() throws Exception { OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); - assertTrue(new OAuth2SecurityExpressionMethods(oAuth2Authentication, true).hasAnyScope("foo")); + OAuth2SecurityExpressionMethods root = new OAuth2SecurityExpressionMethods(oAuth2Authentication); + boolean hasAnyScope = root.hasAnyScope("foo"); + assertFalse(root.throwOnError(hasAnyScope)); } - @Test(expected = AccessDeniedException.class) + @Test(expected = InsufficientScopeException.class) public void testInsufficientScope() throws Exception { OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); - assertFalse(new OAuth2SecurityExpressionMethods(oAuth2Authentication, true).hasAnyScope("foo")); - assertFalse(new OAuth2SecurityExpressionMethods(oAuth2Authentication, true).sufficientScope(false)); + OAuth2SecurityExpressionMethods root = new OAuth2SecurityExpressionMethods(oAuth2Authentication); + boolean hasAnyScope = root.hasAnyScope("foo"); + root.throwOnError(hasAnyScope); } @Test @@ -98,8 +101,8 @@ public void testSufficientScope() throws Exception { Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); - assertTrue(new OAuth2SecurityExpressionMethods(oAuth2Authentication, true).hasAnyScope("read")); - assertTrue(new OAuth2SecurityExpressionMethods(oAuth2Authentication, true).sufficientScope(true)); + assertTrue(new OAuth2SecurityExpressionMethods(oAuth2Authentication).hasAnyScope("read")); + assertTrue(new OAuth2SecurityExpressionMethods(oAuth2Authentication).throwOnError(true)); } @Test @@ -108,25 +111,25 @@ public void testSufficientScopeWithNoPreviousScopeDecision() throws Exception { Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); - assertTrue(new OAuth2SecurityExpressionMethods(oAuth2Authentication, true).isClient()); - assertFalse(new OAuth2SecurityExpressionMethods(oAuth2Authentication, true).sufficientScope(false)); + assertTrue(new OAuth2SecurityExpressionMethods(oAuth2Authentication).isClient()); + assertFalse(new OAuth2SecurityExpressionMethods(oAuth2Authentication).throwOnError(false)); } @Test public void testNonOauthClient() throws Exception { Authentication clientAuthentication = new UsernamePasswordAuthenticationToken("foo", "bar"); - assertFalse(new OAuth2SecurityExpressionMethods(clientAuthentication, true).clientHasAnyRole("ROLE_USER")); + assertFalse(new OAuth2SecurityExpressionMethods(clientAuthentication).clientHasAnyRole("ROLE_USER")); } @Test public void testClientOnly() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, true, Collections.singleton("read"), null, null, null, null); + OAuth2Request request = RequestTokenFactory.createOAuth2Request(null, "foo", null, true, Collections.singleton("read"), null, null, null, null); Authentication userAuthentication = new UsernamePasswordAuthenticationToken("foo", "bar", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"))); - OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); - assertFalse(new OAuth2SecurityExpressionMethods(oAuth2Authentication, true).isClient()); - assertTrue(new OAuth2SecurityExpressionMethods(new OAuth2Authentication(clientAuthentication, null), true).isClient()); + OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(request, userAuthentication); + assertFalse(new OAuth2SecurityExpressionMethods(oAuth2Authentication).isClient()); + assertTrue(new OAuth2SecurityExpressionMethods(new OAuth2Authentication(request, null)).isClient()); } @Test @@ -136,9 +139,8 @@ public void testOAuthUser() throws Exception { Authentication userAuthentication = new UsernamePasswordAuthenticationToken("foo", "bar", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"))); OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); - assertTrue(new OAuth2SecurityExpressionMethods(oAuth2Authentication, true).isUser()); - assertFalse(new OAuth2SecurityExpressionMethods(new OAuth2Authentication(clientAuthentication, null), true) - .isUser()); + assertTrue(new OAuth2SecurityExpressionMethods(oAuth2Authentication).isUser()); + assertFalse(new OAuth2SecurityExpressionMethods(new OAuth2Authentication(clientAuthentication, null)).isUser()); } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2WebSecurityExpressionHandlerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2WebSecurityExpressionHandlerTests.java index 792d70266..5fc82bc67 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2WebSecurityExpressionHandlerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2WebSecurityExpressionHandlerTests.java @@ -22,13 +22,16 @@ import java.util.Collections; import org.junit.Test; +import org.springframework.expression.EvaluationContext; import org.springframework.expression.Expression; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.oauth2.common.exceptions.InsufficientScopeException; import org.springframework.security.oauth2.provider.AuthorizationRequest; -import org.springframework.security.oauth2.provider.RequestTokenFactory; +import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.RequestTokenFactory; import org.springframework.security.oauth2.provider.client.BaseClientDetails; import org.springframework.security.web.FilterInvocation; @@ -40,24 +43,46 @@ public class OAuth2WebSecurityExpressionHandlerTests { private OAuth2WebSecurityExpressionHandler handler = new OAuth2WebSecurityExpressionHandler(); + @Test + public void testScopesWithOr() throws Exception { + AuthorizationRequest request = new AuthorizationRequest("foo", Collections.singleton("read")); + request.setResourceIdsAndAuthoritiesFromClientDetails(new BaseClientDetails("foo", "bar", "", + "client_credentials", "ROLE_USER")); + request.setApproved(true); + OAuth2Request clientAuthentication = request.createOAuth2Request(); + Authentication userAuthentication = new UsernamePasswordAuthenticationToken("user", "pass", + AuthorityUtils.createAuthorityList("ROLE_USER")); + OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); + FilterInvocation invocation = new FilterInvocation("/foo", "GET"); + EvaluationContext context = handler.createEvaluationContext(oAuth2Authentication, invocation); + Expression expression = handler.getExpressionParser().parseExpression( + "#oauth2.hasAnyScope('write') or #oauth2.isUser()"); + assertTrue((Boolean) expression.getValue(context)); + } + @Test public void testOauthClient() throws Exception { AuthorizationRequest request = new AuthorizationRequest("foo", Collections.singleton("read")); - request.setResourceIdsAndAuthoritiesFromClientDetails(new BaseClientDetails("foo", "", "", "client_credentials", "ROLE_CLIENT")); - - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(request.getRequestParameters(), request.getClientId(), request.getAuthorities(), request.isApproved(), request.getScope(), request.getResourceIds(), - request.getRedirectUri(), request.getResponseTypes(), request.getExtensions()); - + request.setResourceIdsAndAuthoritiesFromClientDetails(new BaseClientDetails("foo", "", "", + "client_credentials", "ROLE_CLIENT")); + + OAuth2Request clientAuthentication = RequestTokenFactory + .createOAuth2Request(request.getRequestParameters(), request.getClientId(), request.getAuthorities(), + request.isApproved(), request.getScope(), request.getResourceIds(), request.getRedirectUri(), + request.getResponseTypes(), request.getExtensions()); + Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); FilterInvocation invocation = new FilterInvocation("/foo", "GET"); - Expression expression = handler.getExpressionParser().parseExpression("#oauth2.clientHasAnyRole('ROLE_CLIENT')"); + Expression expression = handler.getExpressionParser() + .parseExpression("#oauth2.clientHasAnyRole('ROLE_CLIENT')"); assertTrue((Boolean) expression.getValue(handler.createEvaluationContext(oAuth2Authentication, invocation))); } @Test public void testScopes() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, + Collections.singleton("read"), null, null, null, null); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); FilterInvocation invocation = new FilterInvocation("/foo", "GET"); @@ -65,6 +90,19 @@ public void testScopes() throws Exception { assertTrue((Boolean) expression.getValue(handler.createEvaluationContext(oAuth2Authentication, invocation))); } + @Test(expected = InsufficientScopeException.class) + public void testInsufficientScope() throws Exception { + AuthorizationRequest request = new AuthorizationRequest("foo", Collections.singleton("read")); + request.setResourceIdsAndAuthoritiesFromClientDetails(new BaseClientDetails("foo", "bar", "", + "client_credentials", "ROLE_USER")); + OAuth2Request clientAuthentication = request.createOAuth2Request(); + Authentication userAuthentication = null; + OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); + OAuth2SecurityExpressionMethods root = new OAuth2SecurityExpressionMethods(oAuth2Authentication); + boolean hasAnyScope = root.hasAnyScope("foo"); + root.throwOnError(hasAnyScope); + } + @Test public void testNonOauthClient() throws Exception { Authentication clientAuthentication = new UsernamePasswordAuthenticationToken("foo", "bar"); From 36370442ca3d54093cf78504bdab5bac779472aa Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 1 Apr 2014 11:12:13 +0100 Subject: [PATCH 197/831] Disable anonymous auth for resource server --- .../web/configuration/ResourceServerConfiguration.java | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java index 01661c782..47fac4f55 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java @@ -102,6 +102,7 @@ protected void configure(HttpSecurity http) throws Exception { http .exceptionHandling().accessDeniedHandler(accessDeniedHandler) .and() + .anonymous().disable() .csrf().disable(); // @formatter:on for (ResourceServerConfigurer configurer : configurers) { From 45a0964cb9ec89701a7765dc3b7ce2aedce0e481 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 1 Apr 2014 11:40:51 +0100 Subject: [PATCH 198/831] Ensure AccessDeniedException is thrown from expression handler ... otherwise the AccessDeniedHandler doesn't get a chance to send the proper response and user just sees 500 status Fixes gh-118 --- .../expression/OAuth2SecurityExpressionMethods.java | 3 ++- .../OAuth2MethodSecurityExpressionHandlerTests.java | 6 +++--- .../expression/OAuth2SecurityExpressionMethodsTests.java | 6 +++--- .../expression/OAuth2WebSecurityExpressionHandlerTests.java | 4 ++-- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethods.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethods.java index 7a0e3262b..5b2cb90d7 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethods.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethods.java @@ -65,7 +65,8 @@ public OAuth2SecurityExpressionMethods(Authentication authentication) { */ public boolean throwOnError(boolean decision) { if (!decision && !missingScopes.isEmpty()) { - throw new InsufficientScopeException("Insufficient scope for this resource", missingScopes); + Throwable failure = new InsufficientScopeException("Insufficient scope for this resource", missingScopes); + throw new AccessDeniedException(failure.getMessage(), failure); } return decision; } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2MethodSecurityExpressionHandlerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2MethodSecurityExpressionHandlerTests.java index 08c9b5fff..50c88b48c 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2MethodSecurityExpressionHandlerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2MethodSecurityExpressionHandlerTests.java @@ -25,10 +25,10 @@ import org.junit.Test; import org.springframework.expression.EvaluationContext; import org.springframework.expression.Expression; +import org.springframework.security.access.AccessDeniedException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.authority.AuthorityUtils; -import org.springframework.security.oauth2.common.exceptions.InsufficientScopeException; import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; @@ -64,7 +64,7 @@ public void testScopesWithOr() throws Exception { assertTrue((Boolean) expression.getValue(context)); } - @Test(expected = InsufficientScopeException.class) + @Test(expected = AccessDeniedException.class) public void testScopesInsufficient() throws Exception { AuthorizationRequest request = new AuthorizationRequest("foo", Collections.singleton("read")); request.setResourceIdsAndAuthoritiesFromClientDetails(new BaseClientDetails("foo", "bar", "", @@ -135,7 +135,7 @@ public void testScopesRegex() throws Exception { assertTrue((Boolean) expression.getValue(context)); } - @Test(expected = InsufficientScopeException.class) + @Test(expected = AccessDeniedException.class) public void testScopesRegexThrowsException() throws Exception { OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethodsTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethodsTests.java index f89bf9c2f..d72244d45 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethodsTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethodsTests.java @@ -22,10 +22,10 @@ import java.util.Collections; import org.junit.Test; +import org.springframework.security.access.AccessDeniedException; 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.exceptions.InsufficientScopeException; import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; @@ -73,7 +73,7 @@ public void testScopesFalse() throws Exception { assertFalse(root.hasAnyScope("write")); } - @Test(expected = InsufficientScopeException.class) + @Test(expected = AccessDeniedException.class) public void testScopesWithException() throws Exception { OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null, null); @@ -84,7 +84,7 @@ public void testScopesWithException() throws Exception { assertFalse(root.throwOnError(hasAnyScope)); } - @Test(expected = InsufficientScopeException.class) + @Test(expected = AccessDeniedException.class) public void testInsufficientScope() throws Exception { OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null, null); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2WebSecurityExpressionHandlerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2WebSecurityExpressionHandlerTests.java index 5fc82bc67..caeb4eae3 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2WebSecurityExpressionHandlerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2WebSecurityExpressionHandlerTests.java @@ -24,10 +24,10 @@ import org.junit.Test; import org.springframework.expression.EvaluationContext; import org.springframework.expression.Expression; +import org.springframework.security.access.AccessDeniedException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.authority.AuthorityUtils; -import org.springframework.security.oauth2.common.exceptions.InsufficientScopeException; import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; @@ -90,7 +90,7 @@ public void testScopes() throws Exception { assertTrue((Boolean) expression.getValue(handler.createEvaluationContext(oAuth2Authentication, invocation))); } - @Test(expected = InsufficientScopeException.class) + @Test(expected = AccessDeniedException.class) public void testInsufficientScope() throws Exception { AuthorizationRequest request = new AuthorizationRequest("foo", Collections.singleton("read")); request.setResourceIdsAndAuthoritiesFromClientDetails(new BaseClientDetails("foo", "bar", "", From 3e4e134b719c8985e9dc88281c9dd70940228745 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 1 Apr 2014 12:13:36 +0100 Subject: [PATCH 199/831] Support for Jackson2 in JdbcClientDetailsService --- .../client/JdbcClientDetailsService.java | 75 ++++++++++++++++--- 1 file changed, 65 insertions(+), 10 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/JdbcClientDetailsService.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/JdbcClientDetailsService.java index 2d3b3b199..f503b9d2d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/JdbcClientDetailsService.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/JdbcClientDetailsService.java @@ -28,7 +28,6 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.codehaus.jackson.map.ObjectMapper; import org.springframework.dao.DuplicateKeyException; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.JdbcTemplate; @@ -45,6 +44,7 @@ import org.springframework.security.oauth2.provider.ClientRegistrationService; import org.springframework.security.oauth2.provider.NoSuchClientException; import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; /** @@ -54,7 +54,7 @@ public class JdbcClientDetailsService implements ClientDetailsService, ClientReg private static final Log logger = LogFactory.getLog(JdbcClientDetailsService.class); - private ObjectMapper mapper = new ObjectMapper(); + private JsonMapper mapper = createJsonMapper(); private static final String CLIENT_FIELDS_FOR_UPDATE = "resource_ids, scope, " + "authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, " @@ -171,7 +171,7 @@ private Object[] getFields(ClientDetails clientDetails) { private Object[] getFieldsForUpdate(ClientDetails clientDetails) { String json = null; try { - json = mapper.writeValueAsString(clientDetails.getAdditionalInformation()); + json = mapper.write(clientDetails.getAdditionalInformation()); } catch (Exception e) { logger.warn("Could not serialize additional information: " + clientDetails, e); @@ -186,11 +186,8 @@ private Object[] getFieldsForUpdate(ClientDetails clientDetails) { clientDetails.getRegisteredRedirectUri() != null ? StringUtils .collectionToCommaDelimitedString(clientDetails.getRegisteredRedirectUri()) : null, clientDetails.getAuthorities() != null ? StringUtils.collectionToCommaDelimitedString(clientDetails - .getAuthorities()) : null, - clientDetails.getAccessTokenValiditySeconds(), - clientDetails.getRefreshTokenValiditySeconds(), - json, - getAutoApproveScopes(clientDetails), + .getAuthorities()) : null, clientDetails.getAccessTokenValiditySeconds(), + clientDetails.getRefreshTokenValiditySeconds(), json, getAutoApproveScopes(clientDetails), clientDetails.getClientId() }; } @@ -252,7 +249,7 @@ public void setRowMapper(RowMapper rowMapper) { * */ private static class ClientDetailsRowMapper implements RowMapper { - private ObjectMapper mapper = new ObjectMapper(); + private JsonMapper mapper = createJsonMapper(); public ClientDetails mapRow(ResultSet rs, int rowNum) throws SQLException { BaseClientDetails details = new BaseClientDetails(rs.getString(1), rs.getString(3), rs.getString(4), @@ -268,7 +265,7 @@ public ClientDetails mapRow(ResultSet rs, int rowNum) throws SQLException { if (json != null) { try { @SuppressWarnings("unchecked") - Map additionalInformation = mapper.readValue(json, Map.class); + Map additionalInformation = mapper.read(json, Map.class); details.setAdditionalInformation(additionalInformation); } catch (Exception e) { @@ -283,4 +280,62 @@ public ClientDetails mapRow(ResultSet rs, int rowNum) throws SQLException { } } + interface JsonMapper { + String write(Object input) throws Exception; + + T read(String input, Class type) throws Exception; + } + + private static JsonMapper createJsonMapper() { + if (ClassUtils.isPresent("org.codehaus.jackson.map.ObjectMapper", null)) { + return new JacksonMapper(); + } + else if (ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", null)) { + return new Jackson2Mapper(); + } + return new NotSupportedJsonMapper(); + } + + private static class JacksonMapper implements JsonMapper { + private org.codehaus.jackson.map.ObjectMapper mapper = new org.codehaus.jackson.map.ObjectMapper(); + + @Override + public String write(Object input) throws Exception { + return mapper.writeValueAsString(input); + } + + @Override + public T read(String input, Class type) throws Exception { + return mapper.readValue(input, type); + } + } + + private static class Jackson2Mapper implements JsonMapper { + private com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper(); + + @Override + public String write(Object input) throws Exception { + return mapper.writeValueAsString(input); + } + + @Override + public T read(String input, Class type) throws Exception { + return mapper.readValue(input, type); + } + } + + private static class NotSupportedJsonMapper implements JsonMapper { + @Override + public String write(Object input) throws Exception { + throw new UnsupportedOperationException( + "Neither Jackson 1 nor 2 is available so JSON conversion cannot be done"); + } + + @Override + public T read(String input, Class type) throws Exception { + throw new UnsupportedOperationException( + "Neither Jackson 1 nor 2 is available so JSON conversion cannot be done"); + } + } + } From d89e94a298526b1265577b3314d23f105eb1b387 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 1 Apr 2014 13:20:49 +0100 Subject: [PATCH 200/831] Fix potential duplicate token problem in JdbcTokenStore It shouldn't happen in practice, but the JdbcTokenStore, since it didn't check for the existence of a token with the same value before doing an insert, might break confusingly later. I think I would recommend a uniqueness constraint in the database anyway but now we have a "last one wins" rule. --- .../oauth2/provider/token/JdbcTokenStore.java | 4 ++++ .../provider/token/TokenStoreBaseTests.java | 15 +++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JdbcTokenStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JdbcTokenStore.java index dcb762b64..e070c8522 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JdbcTokenStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JdbcTokenStore.java @@ -133,6 +133,10 @@ public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authe if (token.getRefreshToken() != null) { refreshToken = token.getRefreshToken().getValue(); } + + if (readAccessToken(token.getValue())!=null) { + removeAccessToken(token.getValue()); + } jdbcTemplate.update(insertAccessTokenSql, new Object[] { extractTokenKey(token.getValue()), new SqlLobValue(serializeAccessToken(token)), authenticationKeyGenerator.extractKey(authentication), diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenStoreBaseTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenStoreBaseTests.java index f1ef9cb8d..d0508abd3 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenStoreBaseTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenStoreBaseTests.java @@ -58,6 +58,21 @@ public void testStoreAccessToken() { assertNull(getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue())); } + @Test + public void testStoreAccessTokenTwice() { + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null, null), new TestAuthentication("test2", false)); + OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); + getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); + getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); + + OAuth2AccessToken actualOAuth2AccessToken = getTokenStore().readAccessToken("testToken"); + assertEquals(expectedOAuth2AccessToken, actualOAuth2AccessToken); + assertEquals(expectedAuthentication, getTokenStore().readAuthentication(expectedOAuth2AccessToken)); + getTokenStore().removeAccessToken(expectedOAuth2AccessToken); + assertNull(getTokenStore().readAccessToken("testToken")); + assertNull(getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue())); + } + @Test public void testRetrieveAccessToken() { //Test approved request From bcdedc4187ba3dfadff0ba8ebcbfac92680e0738 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 2 Apr 2014 10:55:26 +0100 Subject: [PATCH 201/831] Add support for authorization code services in @Configuration --- .../web/configurers/OAuth2AuthorizationServerConfigurer.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java index 685bd945b..1f7ad35ee 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java @@ -190,6 +190,11 @@ public OAuth2AuthorizationServerConfigurer requestValidator(OAuth2RequestValidat return this; } + public OAuth2AuthorizationServerConfigurer authorizationCodeServices(AuthorizationCodeServices authorizationCodeServices) { + this.authorizationCodeServices = authorizationCodeServices; + return this; + } + @Override public void init(HttpSecurity http) throws Exception { registerDefaultAuthenticationEntryPoint(http); From 787c9b47d801b0cf08d35bca4805986c43f56836 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 17 Mar 2014 16:14:03 +0000 Subject: [PATCH 202/831] Add support for ApprovalStore in @EnableAuthorizationServer If user defines a @Bean of type ApprovalStore the AuthorizationEndpoint and WhitelabelApprovalEndpoint change their behaviour accordingly. --- .../AuthorizationServerConfiguration.java | 64 +++++++---- .../OAuth2AuthorizationServerConfigurer.java | 2 +- .../endpoint/AuthorizationEndpoint.java | 37 ++++++- .../oauth2/provider/endpoint/SpelView.java | 73 ++++++++++++ .../endpoint/WhitelabelApprovalEndpoint.java | 104 +++++++----------- .../endpoint/WhitelabelErrorEndpoint.java | 28 +++++ .../request/DefaultOAuth2RequestFactory.java | 75 ++++++------- .../endpoint/AuthorizationEndpointTests.java | 10 ++ .../WhitelabelApprovalEndpointTests.java | 36 +++++- .../WhitelabelErrorEndpointTests.java | 46 ++++++++ ...aultAuthorizationRequestFactoryTests.java} | 9 +- 11 files changed, 346 insertions(+), 138 deletions(-) create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/SpelView.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelErrorEndpoint.java create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelErrorEndpointTests.java rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/request/{DefaultAuthorizationRequestManagerTests.java => DefaultAuthorizationRequestFactoryTests.java} (91%) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java index 01937cd25..41b7b999a 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java @@ -18,6 +18,8 @@ import java.util.Collections; import java.util.List; +import javax.annotation.PostConstruct; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -36,14 +38,15 @@ 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.approval.ApprovalStore; import org.springframework.security.oauth2.provider.approval.UserApprovalHandler; import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; import org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint; import org.springframework.security.oauth2.provider.endpoint.FrameworkEndpointHandlerMapping; import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint; import org.springframework.security.oauth2.provider.endpoint.WhitelabelApprovalEndpoint; +import org.springframework.security.oauth2.provider.endpoint.WhitelabelErrorEndpoint; import org.springframework.security.oauth2.provider.implicit.ImplicitGrantService; -import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; import org.springframework.security.oauth2.provider.token.ConsumerTokenServices; import org.springframework.security.oauth2.provider.token.TokenStore; @@ -63,9 +66,6 @@ public class AuthorizationServerConfiguration extends WebSecurityConfigurerAdapt @Autowired private ClientDetailsService clientDetailsService; - @Autowired - private AuthorizationEndpoint authorizationEndpoint; - @Configuration protected static class ClientDetailsAuthenticationManagerConfiguration extends GlobalAuthenticationConfigurerAdapter { @@ -115,6 +115,35 @@ public AuthorizationEndpoint authorizationEndpoint() throws Exception { authorizationEndpoint.setImplicitGrantService(implicitGrantService()); return authorizationEndpoint; } + + @Configuration + protected static class EndpointsConfiguration { + + @Autowired + private AuthorizationEndpoint authorizationEndpoint; + + @Autowired(required=false) + private ApprovalStore approvalStore; + + @Autowired + private FrameworkEndpointHandlerMapping mapping; + + @PostConstruct + public void init() { + authorizationEndpoint.setApprovalStore(approvalStore); + authorizationEndpoint.setUserApprovalPage(extractPath(mapping, "/oauth/confirm_access")); + authorizationEndpoint.setErrorPage(extractPath(mapping, "/oauth/error")); + } + + private String extractPath(FrameworkEndpointHandlerMapping mapping, String page) { + String path = mapping.getPath(page); + if (path.contains(":")) { + return path; + } + return "forward:" + path; + } + + } @Bean @Lazy @@ -157,24 +186,25 @@ public OAuth2RequestValidator oauth2RequestValidator() throws Exception { @Bean @Lazy @Scope(proxyMode = ScopedProxyMode.INTERFACES) - public TokenStore tokenStore() throws Exception { - return authorizationServerConfigurer().getTokenStore(); + public UserApprovalHandler userApprovalHandler() throws Exception { + return authorizationServerConfigurer().getUserApprovalHandler(); } @Bean @Lazy @Scope(proxyMode = ScopedProxyMode.INTERFACES) - public UserApprovalHandler userApprovalHandler() throws Exception { - return authorizationServerConfigurer().getUserApprovalHandler(); + public TokenStore tokenStore() throws Exception { + return authorizationServerConfigurer().getTokenStore(); } - protected AuthorizationServerTokenServices tokenServices() throws Exception { - return authorizationServerConfigurer().getTokenServices(); + @Bean + public WhitelabelApprovalEndpoint whitelabelApprovalEndpoint() { + return new WhitelabelApprovalEndpoint(); } @Bean - public WhitelabelApprovalEndpoint approvalEndpoint() { - return new WhitelabelApprovalEndpoint(); + public WhitelabelErrorEndpoint whitelabelErrorEndpoint() { + return new WhitelabelErrorEndpoint(); } @Bean @@ -182,19 +212,9 @@ public WhitelabelApprovalEndpoint approvalEndpoint() { @Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) public FrameworkEndpointHandlerMapping oauth2EndpointHandlerMapping() throws Exception { FrameworkEndpointHandlerMapping mapping = authorizationServerConfigurer().getFrameworkEndpointHandlerMapping(); - authorizationEndpoint.setUserApprovalPage(extractPath(mapping, "/oauth/confirm_access")); - authorizationEndpoint.setErrorPage(extractPath(mapping, "/oauth/error")); return mapping; } - private String extractPath(FrameworkEndpointHandlerMapping mapping, String page) { - String path = mapping.getPath(page); - if (path.contains(":")) { - return path; - } - return "forward:" + path; - } - @Bean @Lazy @Scope(proxyMode = ScopedProxyMode.INTERFACES) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java index 1f7ad35ee..83467ac36 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java @@ -133,7 +133,7 @@ public OAuth2RequestValidator getOAuth2RequestValidator() { public UserApprovalHandler getUserApprovalHandler() { return userApprovalHandler; } - + public OAuth2AuthorizationServerConfigurer allowFormAuthenticationForClients() { this.allowFormAuthenticationForClients = true; return this; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java index f68f23081..4baedc3e2 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java @@ -44,8 +44,11 @@ import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.OAuth2RequestValidator; import org.springframework.security.oauth2.provider.TokenRequest; +import org.springframework.security.oauth2.provider.approval.Approval; +import org.springframework.security.oauth2.provider.approval.ApprovalStore; import org.springframework.security.oauth2.provider.approval.DefaultUserApprovalHandler; import org.springframework.security.oauth2.provider.approval.UserApprovalHandler; +import org.springframework.security.oauth2.provider.approval.Approval.ApprovalStatus; import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices; import org.springframework.security.oauth2.provider.implicit.ImplicitGrantService; @@ -105,6 +108,18 @@ public class AuthorizationEndpoint extends AbstractEndpoint { private String errorPage = "forward:/oauth/error"; + private ApprovalStore approvalStore; + + /** + * Optional approval store (if one is available) will result in approval information being added to the model for + * the confirmation page, and therefore potentially the user being able to approve individual scopes. + * + * @param approvalStore the approvalStore to set + */ + public void setApprovalStore(ApprovalStore approvalStore) { + this.approvalStore = approvalStore; + } + public void setSessionAttributeStore(SessionAttributeStore sessionAttributeStore) { this.sessionAttributeStore = sessionAttributeStore; } @@ -179,7 +194,7 @@ public ModelAndView authorize(Map model, @RequestParam // so any auth request parameters passed to approveOrDeny will be ignored and retrieved from the session. model.put("authorizationRequest", authorizationRequest); - return getUserApprovalPageResponse(model, authorizationRequest); + return getUserApprovalPageResponse(model, authorizationRequest, principal, client); } catch (RuntimeException e) { @@ -240,10 +255,23 @@ public View approveOrDeny(@RequestParam // We need explicit approval from the user. private ModelAndView getUserApprovalPageResponse(Map model, - AuthorizationRequest authorizationRequest) { + AuthorizationRequest authorizationRequest, Principal principal, ClientDetails client) { logger.debug("Loading user approval page: " + userApprovalPage); // In case of a redirect we might want the request parameters to be included model.putAll(authorizationRequest.getRequestParameters()); + if (approvalStore != null) { + Map scopes = new LinkedHashMap(); + for (String scope : authorizationRequest.getScope()) { + scopes.put(OAuth2Utils.SCOPE_PREFIX + scope, "false"); + } + for (Approval approval : approvalStore.getApprovals(principal.getName(), client.getClientId())) { + if (authorizationRequest.getScope().contains(approval.getScope())) { + scopes.put(OAuth2Utils.SCOPE_PREFIX + approval.getScope(), + approval.getStatus() == ApprovalStatus.APPROVED ? "true" : "false"); + } + } + model.put("scopes", scopes); + } return new ModelAndView(userApprovalPage, model); } @@ -396,10 +424,11 @@ private String getUnsuccessfulRedirect(AuthorizationRequest authorizationRequest query.put(additionalInfo.getKey(), additionalInfo.getValue()); } } - + if (fragment) { template.fragment(values.toString()); - } else { + } + else { template.query(values.toString()); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/SpelView.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/SpelView.java new file mode 100644 index 000000000..5e17e68b9 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/SpelView.java @@ -0,0 +1,73 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.springframework.security.oauth2.provider.endpoint; + +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.context.expression.MapAccessor; +import org.springframework.expression.Expression; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.spel.support.StandardEvaluationContext; +import org.springframework.util.PropertyPlaceholderHelper; +import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver; +import org.springframework.web.servlet.View; + +/** + * Simple String template renderer. + * + */ +class SpelView implements View { + + private final String template; + + private final SpelExpressionParser parser = new SpelExpressionParser(); + + private final StandardEvaluationContext context = new StandardEvaluationContext(); + + private PropertyPlaceholderHelper helper; + + private PlaceholderResolver resolver; + + public SpelView(String template) { + this.template = template; + this.context.addPropertyAccessor(new MapAccessor()); + this.helper = new PropertyPlaceholderHelper("${", "}"); + this.resolver = new PlaceholderResolver() { + public String resolvePlaceholder(String name) { + Expression expression = parser.parseExpression(name); + Object value = expression.getValue(context); + return value == null ? null : value.toString(); + } + }; + } + + public String getContentType() { + return "text/html"; + } + + public void render(Map model, HttpServletRequest request, HttpServletResponse response) + throws Exception { + Map map = new HashMap(model); + map.put("path", (Object) request.getContextPath()); + context.setRootObject(map); + String result = helper.replacePlaceholders(template, resolver); + response.setContentType(getContentType()); + response.getWriter().append(result); + } + +} \ No newline at end of file diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelApprovalEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelApprovalEndpoint.java index ee497b278..73a643f5b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelApprovalEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelApprovalEndpoint.java @@ -1,24 +1,15 @@ package org.springframework.security.oauth2.provider.endpoint; -import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.springframework.context.expression.MapAccessor; -import org.springframework.expression.Expression; -import org.springframework.expression.spel.standard.SpelExpressionParser; -import org.springframework.expression.spel.support.StandardEvaluationContext; -import org.springframework.util.PropertyPlaceholderHelper; -import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.SessionAttributes; import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.View; /** - * Controller for displaying the approval and error pages for the authorization server. + * Controller for displaying the approval page for the authorization server. * * @author Dave Syer */ @@ -28,73 +19,56 @@ public class WhitelabelApprovalEndpoint { @RequestMapping("/oauth/confirm_access") public ModelAndView getAccessConfirmation(Map model, HttpServletRequest request) throws Exception { - if (request.getAttribute("_csrf")!=null) { + String template = createTemplate(model, request); + if (request.getAttribute("_csrf") != null) { model.put("_csrf", request.getAttribute("_csrf")); } - return new ModelAndView(new SpelView(APPROVAL), model); + return new ModelAndView(new SpelView(template), model); } - @RequestMapping("/oauth/error") - public ModelAndView handleError(HttpServletRequest request) { - Map model = new HashMap(); - model.put("error", request.getAttribute("error")); - return new ModelAndView(new SpelView(ERROR), model); - } - - /** - * Simple String template renderer. - * - */ - private static class SpelView implements View { - - private final String template; - - private final SpelExpressionParser parser = new SpelExpressionParser(); - - private final StandardEvaluationContext context = new StandardEvaluationContext(); - - private PropertyPlaceholderHelper helper; - - private PlaceholderResolver resolver; - - public SpelView(String template) { - this.template = template; - this.context.addPropertyAccessor(new MapAccessor()); - this.helper = new PropertyPlaceholderHelper("${", "}"); - this.resolver = new PlaceholderResolver() { - public String resolvePlaceholder(String name) { - Expression expression = parser.parseExpression(name); - Object value = expression.getValue(context); - return value == null ? null : value.toString(); - } - }; + protected String createTemplate(Map model, HttpServletRequest request) { + String template = TEMPLATE; + if (model.containsKey("scopes") || request.getAttribute("scopes") != null) { + template = template.replace("%scopes%", createScopes(model, request)).replace("%denial%", ""); } - - public String getContentType() { - return "text/html"; + else { + template = template.replace("%scopes%", "").replace("%denial%", DENIAL); } - - public void render(Map model, HttpServletRequest request, HttpServletResponse response) - throws Exception { - Map map = new HashMap(model); - map.put("path", (Object) request.getContextPath()); - context.setRootObject(map); - String result = helper.replacePlaceholders(template, resolver); - response.setContentType(getContentType()); - response.getWriter().append(result); + if (model.containsKey("_csrf") || request.getAttribute("_csrf") != null) { + template = template.replace("%csrf%", CSRF); + } + else { + template = template.replace("%csrf%", ""); } + return template; + } + private CharSequence createScopes(Map model, HttpServletRequest request) { + StringBuilder builder = new StringBuilder("
    "); + @SuppressWarnings("unchecked") + Map scopes = (Map) (model.containsKey("scopes") ? model.get("scopes") : request + .getAttribute("scopes")); + for (String scope : scopes.keySet()) { + String approved = "true".equals(scopes.get(scope)) ? " checked" : ""; + String denied = !"true".equals(scopes.get(scope)) ? " checked" : ""; + String value = SCOPE.replace("%scope%", scope).replace("%key%", scope).replace("%approved%", approved) + .replace("%denied%", denied); + builder.append(value); + } + builder.append("
"); + return builder.toString(); } - private static String CSRF = "${#root['_csrf']!=null ? '' : ''}"; + private static String CSRF = ""; + + private static String DENIAL = "
%csrf%
"; - private static String APPROVAL = "

OAuth Approval

" + private static String TEMPLATE = "

OAuth Approval

" + "

Do you authorize '${authorizationRequest.clientId}' to access your protected resources?

" - + "
"+CSRF+"
" - + "
"+CSRF+"
" - + ""; + + "
%csrf%%scopes%
" + + "%denial%"; - private static String ERROR = "

OAuth Error

${error.summary}

"; + private static String SCOPE = "
  • %scope%: Approve Deny
  • "; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelErrorEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelErrorEndpoint.java new file mode 100644 index 000000000..2035093d9 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelErrorEndpoint.java @@ -0,0 +1,28 @@ +package org.springframework.security.oauth2.provider.endpoint; + +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.servlet.ModelAndView; + +/** + * Controller for displaying the error page for the authorization server. + * + * @author Dave Syer + */ +@FrameworkEndpoint +public class WhitelabelErrorEndpoint { + + @RequestMapping("/oauth/error") + public ModelAndView handleError(HttpServletRequest request) { + Map model = new HashMap(); + model.put("error", request.getAttribute("error")); + return new ModelAndView(new SpelView(ERROR), model); + } + + private static String ERROR = "

    OAuth Error

    ${error.summary}

    "; + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/request/DefaultOAuth2RequestFactory.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/request/DefaultOAuth2RequestFactory.java index a5863bdde..bf3887d58 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/request/DefaultOAuth2RequestFactory.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/request/DefaultOAuth2RequestFactory.java @@ -69,50 +69,24 @@ public void setCheckUserScopes(boolean checkUserScopes) { public AuthorizationRequest createAuthorizationRequest(Map authorizationParameters) { String clientId = authorizationParameters.get(OAuth2Utils.CLIENT_ID); - Set scopes = OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Utils.SCOPE)); String state = authorizationParameters.get(OAuth2Utils.STATE); String redirectUri = authorizationParameters.get(OAuth2Utils.REDIRECT_URI); Set responseTypes = OAuth2Utils.parseParameterList(authorizationParameters .get(OAuth2Utils.RESPONSE_TYPE)); - ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId); - - if ((scopes == null || scopes.isEmpty())) { - // If no scopes are specified in the incoming data, use the default values registered with the client - // (the spec allows us to choose between this option and rejecting the request completely, so we'll take the - // least obnoxious choice as a default). - scopes = clientDetails.getScope(); - } - - if (checkUserScopes) { - scopes = checkUserScopes(scopes, clientDetails); - } - + Set scopes = extractScopes(authorizationParameters, clientId); + AuthorizationRequest request = new AuthorizationRequest(authorizationParameters, Collections. emptyMap(), clientId, scopes, null, null, false, state, redirectUri, responseTypes); + ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId); request.setResourceIdsAndAuthoritiesFromClientDetails(clientDetails); return request; } - private Set checkUserScopes(Set scopes, ClientDetails clientDetails) { - if (!securityContextAccessor.isUser()) { - return scopes; - } - Set result = new LinkedHashSet(); - Set authorities = AuthorityUtils.authorityListToSet(securityContextAccessor.getAuthorities()); - for (String scope : scopes) { - if (authorities.contains(scope) || authorities.contains(scope.toUpperCase()) - || authorities.contains("ROLE_" + scope.toUpperCase())) { - result.add(scope); - } - } - return result; - } - public OAuth2Request createOAuth2Request(AuthorizationRequest request) { return request.createOAuth2Request(); } @@ -130,18 +104,9 @@ public TokenRequest createTokenRequest(Map requestParameters, Cl throw new InvalidClientException("Given client ID does not match authenticated client"); } } - Set scopes = OAuth2Utils.parseParameterList(requestParameters.get(OAuth2Utils.SCOPE)); String grantType = requestParameters.get(OAuth2Utils.GRANT_TYPE); - ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId); - - if ((scopes == null || scopes.isEmpty())) { - // If no scopes are specified in the incoming data, use the default values registered with the client - // (the spec allows us to choose between this option and rejecting the request completely, so we'll take the - // least obnoxious choice as a default). - scopes = clientDetails.getScope(); - } - + Set scopes = extractScopes(requestParameters, clientId); TokenRequest tokenRequest = new TokenRequest(requestParameters, clientId, scopes, grantType); return tokenRequest; @@ -157,4 +122,36 @@ public OAuth2Request createOAuth2Request(ClientDetails client, TokenRequest toke return tokenRequest.createOAuth2Request(client); } + private Set extractScopes(Map requestParameters, String clientId) { + Set scopes = OAuth2Utils.parseParameterList(requestParameters.get(OAuth2Utils.SCOPE)); + ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId); + + if ((scopes == null || scopes.isEmpty())) { + // If no scopes are specified in the incoming data, use the default values registered with the client + // (the spec allows us to choose between this option and rejecting the request completely, so we'll take the + // least obnoxious choice as a default). + scopes = clientDetails.getScope(); + } + + if (checkUserScopes) { + scopes = checkUserScopes(scopes, clientDetails); + } + return scopes; + } + + private Set checkUserScopes(Set scopes, ClientDetails clientDetails) { + if (!securityContextAccessor.isUser()) { + return scopes; + } + Set result = new LinkedHashSet(); + Set authorities = AuthorityUtils.authorityListToSet(securityContextAccessor.getAuthorities()); + for (String scope : scopes) { + if (authorities.contains(scope) || authorities.contains(scope.toUpperCase()) + || authorities.contains("ROLE_" + scope.toUpperCase())) { + result.add(scope); + } + } + return result; + } + } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java index 2e0bfc3b2..184e114e4 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java @@ -44,6 +44,7 @@ import org.springframework.security.oauth2.provider.TokenGranter; import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.approval.DefaultUserApprovalHandler; +import org.springframework.security.oauth2.provider.approval.InMemoryApprovalStore; import org.springframework.security.oauth2.provider.approval.UserApprovalHandler; import org.springframework.security.oauth2.provider.client.BaseClientDetails; import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; @@ -126,6 +127,15 @@ public void testStartAuthorizationCodeFlow() throws Exception { assertEquals("forward:/oauth/confirm_access", result.getViewName()); } + @Test + public void testApprovalStoreAddsScopes() throws Exception { + endpoint.setApprovalStore(new InMemoryApprovalStore()); + ModelAndView result = endpoint.authorize(model, getAuthorizationRequest("foo", null, null, "read", Collections.singleton("code")) + .getRequestParameters(), sessionStatus, principal); + assertEquals("forward:/oauth/confirm_access", result.getViewName()); + assertTrue(result.getModel().containsKey("scopes")); + } + @Test(expected = OAuth2Exception.class) public void testStartAuthorizationCodeFlowForClientCredentialsFails() throws Exception { client.setAuthorizedGrantTypes(Collections.singleton("client_credentials")); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelApprovalEndpointTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelApprovalEndpointTests.java index debcabfb8..bd05b3383 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelApprovalEndpointTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelApprovalEndpointTests.java @@ -23,9 +23,9 @@ import org.junit.Test; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; -import org.springframework.security.oauth2.common.exceptions.InvalidClientException; import org.springframework.security.oauth2.common.util.OAuth2Utils; import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.web.csrf.DefaultCsrfToken; import org.springframework.web.servlet.ModelAndView; /** @@ -61,17 +61,41 @@ public void testApprovalPage() throws Exception { assertTrue("Wrong content: " + content, content.contains(" model = new HashMap(); + model.put("authorizationRequest", createFromParameters(parameters)); + model.put("scopes", Collections.singletonMap("scope.read", "true")); + ModelAndView result = endpoint.getAccessConfirmation(model, request); + result.getView().render(result.getModel(), request , response); + String content = response.getContentAsString(); + assertTrue("Wrong content: " + content, content.contains("scope.read")); + assertTrue("Wrong content: " + content, content.contains("checked")); + assertTrue("Wrong content: " + content, content.contains("/foo/oauth/authorize")); + assertTrue("Wrong content: " + content, !content.contains("${")); + assertTrue("Wrong content: " + content, !content.contains("_csrf")); + assertTrue("Wrong content: " + content, !content.contains("%")); + } + + @Test + public void testApprovalPageWithCsrf() throws Exception { + request.setContextPath("/foo"); + request.setAttribute("_csrf", new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "FOO")); + parameters.put("client_id", "client"); + HashMap model = new HashMap(); + model.put("authorizationRequest", createFromParameters(parameters)); + ModelAndView result = endpoint.getAccessConfirmation(model, request); result.getView().render(result.getModel(), request , response); String content = response.getContentAsString(); - assertTrue("Wrong content: " + content, content.contains("OAuth Error")); - assertTrue("Wrong content: " + content, content.contains("invalid_client")); + assertTrue("Wrong content: " + content, content.contains("_csrf")); + assertTrue("Wrong content: " + content, content.contains("/foo/oauth/authorize")); + assertTrue("Wrong content: " + content, !content.contains("${")); } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelErrorEndpointTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelErrorEndpointTests.java new file mode 100644 index 000000000..e03f81687 --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelErrorEndpointTests.java @@ -0,0 +1,46 @@ +/* + * Copyright 2006-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.endpoint; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.security.oauth2.common.exceptions.InvalidClientException; +import org.springframework.web.servlet.ModelAndView; + +/** + * @author Dave Syer + * + */ +public class WhitelabelErrorEndpointTests { + + private WhitelabelErrorEndpoint endpoint = new WhitelabelErrorEndpoint(); + private MockHttpServletRequest request = new MockHttpServletRequest(); + private MockHttpServletResponse response = new MockHttpServletResponse(); + + @Test + public void testErrorPage() throws Exception { + request.setContextPath("/foo"); + request.setAttribute("error", new InvalidClientException("FOO")); + ModelAndView result = endpoint.handleError(request); + result.getView().render(result.getModel(), request , response); + String content = response.getContentAsString(); + assertTrue("Wrong content: " + content, content.contains("OAuth Error")); + assertTrue("Wrong content: " + content, content.contains("invalid_client")); + } + +} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/request/DefaultAuthorizationRequestManagerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/request/DefaultAuthorizationRequestFactoryTests.java similarity index 91% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/request/DefaultAuthorizationRequestManagerTests.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/request/DefaultAuthorizationRequestFactoryTests.java index 3ccd2980f..623a99744 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/request/DefaultAuthorizationRequestManagerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/request/DefaultAuthorizationRequestFactoryTests.java @@ -27,6 +27,7 @@ import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.client.BaseClientDetails; import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory; @@ -34,7 +35,7 @@ * @author Dave Syer * */ -public class DefaultAuthorizationRequestManagerTests { +public class DefaultAuthorizationRequestFactoryTests { private BaseClientDetails client = new BaseClientDetails(); @@ -61,6 +62,12 @@ public void testCreateAuthorizationRequest() { assertEquals("foo", request.getClientId()); } + @Test + public void testCreateTokenRequest() { + TokenRequest request = factory.createTokenRequest(Collections.singletonMap("client_id", "foo"), client); + assertEquals("foo", request.getClientId()); + } + @Test public void testCreateAuthorizationRequestWithDefaultScopes() { AuthorizationRequest request = factory.createAuthorizationRequest(Collections.singletonMap("client_id", "foo")); From 7789706734613738b92b2a57fce6ef0f1099a43a Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 17 Mar 2014 16:23:17 +0000 Subject: [PATCH 203/831] Remove bundlor plugin --- spring-security-oauth/template.mf | 28 ------------------------ spring-security-oauth2/template.mf | 34 ------------------------------ 2 files changed, 62 deletions(-) delete mode 100644 spring-security-oauth/template.mf delete mode 100644 spring-security-oauth2/template.mf diff --git a/spring-security-oauth/template.mf b/spring-security-oauth/template.mf deleted file mode 100644 index 7f0fbb454..000000000 --- a/spring-security-oauth/template.mf +++ /dev/null @@ -1,28 +0,0 @@ -Bundle-SymbolicName: org.springframework.security.oauth -Bundle-Name: Spring Security OAuth -Bundle-Vendor: SpringSource -Bundle-ManifestVersion: 2 -Import-Template: - org.apache.commons.logging.*;version="[1.1.1, 2.0.0)", - org.apache.commons.codec.*;version="[1.3, 2.0.0)", - org.springframework.beans.*;version="${spring.osgi.range}", - org.springframework.core.*;version="${spring.osgi.range}", - org.springframework.expression.*;version="${spring.osgi.range}", - org.springframework.jdbc.*;version="${spring.osgi.range}", - org.springframework.web.*;version="${spring.osgi.range}", - org.springframework.dao.*;version="${spring.osgi.range}", - org.springframework.http.*;version="${spring.osgi.range}", - org.springframework.context.*;version="${spring.osgi.range}", - org.springframework.util.*;version="${spring.osgi.range}", - org.springframework.security.*;version="${security.osgi.range}", - org.aopalliance.*;version="0", - org.w3c.dom.*;version="0", - javax.servlet.*;version="[2.3,4.0)", - javax.crypto.*;version="0", - javax.sql.*;version="0", - javax.xml.*;version="0" -Ignored-Existing-Headers: - Bnd-LastModified, - Import-Package, - Export-Package, - Tool diff --git a/spring-security-oauth2/template.mf b/spring-security-oauth2/template.mf deleted file mode 100644 index 9a5a474bb..000000000 --- a/spring-security-oauth2/template.mf +++ /dev/null @@ -1,34 +0,0 @@ -Bundle-SymbolicName: org.springframework.security.oauth -Bundle-Name: Spring Security OAuth -Bundle-Vendor: SpringSource -Bundle-ManifestVersion: 2 -Import-Template: - org.apache.commons.logging.*;version="[1.1.1, 2.0.0)", - org.apache.commons.codec.*;version="[1.3, 2.0.0)", - org.codehaus.jackson.*;version="[1.9.3, 2.0.0)";resolution:=optional, - com.fasterxml.jackson.*;version="[2.0.0, 3.0.0)";resolution:=optional, - org.springframework.beans.*;version="${spring.osgi.range}", - org.springframework.aop.*;version="${spring.osgi.range}", - org.springframework.core.*;version="${spring.osgi.range}", - org.springframework.expression.*;version="${spring.osgi.range}", - org.springframework.jdbc.*;version="${spring.osgi.range}", - org.springframework.stereotype.*;version="${spring.osgi.range}", - org.springframework.web.*;version="${spring.osgi.range}", - org.springframework.dao.*;version="${spring.osgi.range}", - org.springframework.http.*;version="${spring.osgi.range}", - org.springframework.context.*;version="${spring.osgi.range}", - org.springframework.util.*;version="${spring.osgi.range}", - org.springframework.security.*;version="${security.osgi.range}", - org.aopalliance.*;version="0", - org.w3c.dom.*;version="0", - org.junit.*;version="[4.8.2,5.0)";resolution:=optional, - org.hamcrest.*;version="[4.8.2,5.0)";resolution:=optional, - javax.servlet.*;version="[2.3,4.0)", - javax.crypto.*;version="0", - javax.sql.*;version="0", - javax.xml.*;version="0" -Ignored-Existing-Headers: - Bnd-LastModified, - Import-Package, - Export-Package, - Tool From 9aae65065663025ef8c04003cf1ec2c22dcbec27 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 17 Mar 2014 18:08:16 +0000 Subject: [PATCH 204/831] Refine ApprovalStore configuration a bit Rather than always create a @Bean of type TokenStore we now look for beans *named* "tokenStore" and "approvalStore" and back out if one of those already exists. That makes more sense for stateless token services (like JwtTokenServices). --- .../AuthorizationServerConfiguration.java | 109 +++++++++++------- .../ResourceServerConfiguration.java | 6 +- .../OAuth2AuthorizationServerConfigurer.java | 53 +++++++-- ...AuthorizationServerConfigurationTests.java | 35 ++++++ 4 files changed, 151 insertions(+), 52 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java index 41b7b999a..b52be2606 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java @@ -21,13 +21,17 @@ import javax.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.ScopedProxyMode; import org.springframework.core.annotation.Order; +import org.springframework.core.type.AnnotationMetadata; import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @@ -48,6 +52,7 @@ import org.springframework.security.oauth2.provider.endpoint.WhitelabelErrorEndpoint; import org.springframework.security.oauth2.provider.implicit.ImplicitGrantService; import org.springframework.security.oauth2.provider.token.ConsumerTokenServices; +import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; import org.springframework.security.oauth2.provider.token.TokenStore; /** @@ -60,12 +65,28 @@ @Order(0) public class AuthorizationServerConfiguration extends WebSecurityConfigurerAdapter { + /** + * The static bean name for a TokenStore if any. If the use creates his own bean with the same name, or else an + * ApprovalStore named {@link #APPROVAL_STORE_BEAN_NAME}, then Spring will create an {@link InMemoryTokenStore}. + * + */ + public static final String TOKEN_STORE_BEAN_NAME = "tokenStore"; + + /** + * The static bean name for a {@link ApprovalStore} if any. Spring will not create one, but it will also not create + * a {@link TokenStore} bean if there is an approval store present. + */ + public static final String APPROVAL_STORE_BEAN_NAME = "approvalStore"; + @Autowired private List configurers = Collections.emptyList(); @Autowired private ClientDetailsService clientDetailsService; - + + @Autowired(required = false) + private TokenStore tokenStore; + @Configuration protected static class ClientDetailsAuthenticationManagerConfiguration extends GlobalAuthenticationConfigurerAdapter { @@ -84,6 +105,9 @@ protected void configure(HttpSecurity http) throws Exception { OAuth2AuthorizationServerConfigurer configurer = new OAuth2AuthorizationServerConfigurer(); configurer.clientDetailsService(clientDetailsService); configure(configurer); + if (tokenStore != null) { + configurer.tokenStore(tokenStore); + } http.apply(configurer); String tokenEndpointPath = oauth2EndpointHandlerMapping().getPath("/oauth/token"); // @formatter:off @@ -115,35 +139,6 @@ public AuthorizationEndpoint authorizationEndpoint() throws Exception { authorizationEndpoint.setImplicitGrantService(implicitGrantService()); return authorizationEndpoint; } - - @Configuration - protected static class EndpointsConfiguration { - - @Autowired - private AuthorizationEndpoint authorizationEndpoint; - - @Autowired(required=false) - private ApprovalStore approvalStore; - - @Autowired - private FrameworkEndpointHandlerMapping mapping; - - @PostConstruct - public void init() { - authorizationEndpoint.setApprovalStore(approvalStore); - authorizationEndpoint.setUserApprovalPage(extractPath(mapping, "/oauth/confirm_access")); - authorizationEndpoint.setErrorPage(extractPath(mapping, "/oauth/error")); - } - - private String extractPath(FrameworkEndpointHandlerMapping mapping, String page) { - String path = mapping.getPath(page); - if (path.contains(":")) { - return path; - } - return "forward:" + path; - } - - } @Bean @Lazy @@ -190,13 +185,6 @@ public UserApprovalHandler userApprovalHandler() throws Exception { return authorizationServerConfigurer().getUserApprovalHandler(); } - @Bean - @Lazy - @Scope(proxyMode = ScopedProxyMode.INTERFACES) - public TokenStore tokenStore() throws Exception { - return authorizationServerConfigurer().getTokenStore(); - } - @Bean public WhitelabelApprovalEndpoint whitelabelApprovalEndpoint() { return new WhitelabelApprovalEndpoint(); @@ -211,8 +199,7 @@ public WhitelabelErrorEndpoint whitelabelErrorEndpoint() { @Lazy @Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) public FrameworkEndpointHandlerMapping oauth2EndpointHandlerMapping() throws Exception { - FrameworkEndpointHandlerMapping mapping = authorizationServerConfigurer().getFrameworkEndpointHandlerMapping(); - return mapping; + return authorizationServerConfigurer().getFrameworkEndpointHandlerMapping(); } @Bean @@ -233,4 +220,48 @@ private OAuth2AuthorizationServerConfigurer authorizationServerConfigurer() thro return getHttp().getConfigurer(OAuth2AuthorizationServerConfigurer.class); } + @Configuration + @Import(TokenStoreRegistrar.class) + protected static class EndpointsConfiguration { + + @Autowired + private AuthorizationEndpoint authorizationEndpoint; + + @Autowired(required = false) + private ApprovalStore approvalStore; + + @Autowired + private FrameworkEndpointHandlerMapping mapping; + + @PostConstruct + public void init() { + if (approvalStore != null) { + authorizationEndpoint.setApprovalStore(approvalStore); + } + authorizationEndpoint.setUserApprovalPage(extractPath(mapping, "/oauth/confirm_access")); + authorizationEndpoint.setErrorPage(extractPath(mapping, "/oauth/error")); + } + + private String extractPath(FrameworkEndpointHandlerMapping mapping, String page) { + String path = mapping.getPath(page); + if (path.contains(":")) { + return path; + } + return "forward:" + path; + } + + } + + protected static class TokenStoreRegistrar implements ImportBeanDefinitionRegistrar { + + @Override + public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { + if (!registry.containsBeanDefinition(TOKEN_STORE_BEAN_NAME) + && !registry.containsBeanDefinition(APPROVAL_STORE_BEAN_NAME)) { + registry.registerBeanDefinition(TOKEN_STORE_BEAN_NAME, new RootBeanDefinition(InMemoryTokenStore.class)); + } + } + + } + } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java index 47fac4f55..833892fc8 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java @@ -42,7 +42,7 @@ @Order(3) public class ResourceServerConfiguration extends WebSecurityConfigurerAdapter { - @Autowired + @Autowired(required = false) private TokenStore tokenStore; @Autowired(required = false) @@ -121,7 +121,9 @@ protected void configure(HttpSecurity http) throws Exception { for (ResourceServerConfigurer configurer : configurers) { configurer.configure(resources); } - resources.tokenStore(tokenStore); + if (tokenStore != null) { + resources.tokenStore(tokenStore); + } } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java index 83467ac36..dd2d39402 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java @@ -31,6 +31,9 @@ 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.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.client.ClientCredentialsTokenEndpointFilter; @@ -86,6 +89,8 @@ public final class OAuth2AuthorizationServerConfigurer extends private TokenStore tokenStore; + private ApprovalStore approvalStore; + private TokenGranter tokenGranter; private OAuth2RequestFactory requestFactory; @@ -118,6 +123,10 @@ public TokenStore getTokenStore() { return tokenStore; } + public ApprovalStore getApprovalStore() { + return approvalStore; + } + public ClientDetailsService getClientDetailsService() { return clientDetailsService; } @@ -133,7 +142,7 @@ public OAuth2RequestValidator getOAuth2RequestValidator() { public UserApprovalHandler getUserApprovalHandler() { return userApprovalHandler; } - + public OAuth2AuthorizationServerConfigurer allowFormAuthenticationForClients() { this.allowFormAuthenticationForClients = true; return this; @@ -260,10 +269,12 @@ public ImplicitGrantService getImplicitGrantService() { private ConsumerTokenServices consumerTokenServices(HttpSecurity http) { if (consumerTokenServices == null) { - DefaultTokenServices defaultTokenServices = new DefaultTokenServices(); - defaultTokenServices.setClientDetailsService(clientDetails()); - defaultTokenServices.setTokenStore(tokenStore()); - consumerTokenServices = defaultTokenServices; + if (tokenStore() != null) { + DefaultTokenServices defaultTokenServices = new DefaultTokenServices(); + defaultTokenServices.setClientDetailsService(clientDetails()); + defaultTokenServices.setTokenStore(tokenStore()); + consumerTokenServices = defaultTokenServices; + } } return consumerTokenServices; } @@ -281,12 +292,21 @@ private AuthorizationServerTokenServices tokenServices(HttpSecurity http) { } private TokenStore tokenStore() { - if (tokenStore == null) { + if (tokenStore == null && approvalStore == null) { this.tokenStore = new InMemoryTokenStore(); } return this.tokenStore; } + private ApprovalStore approvalStore() { + if (tokenStore() != null) { + TokenApprovalStore tokenApprovalStore = new TokenApprovalStore(); + tokenApprovalStore.setTokenStore(tokenStore()); + this.approvalStore = tokenApprovalStore; + } + return this.approvalStore; + } + private ClientDetailsService clientDetailsService() { if (clientDetailsService == null) { this.clientDetailsService = new InMemoryClientDetailsService(); @@ -296,11 +316,22 @@ private ClientDetailsService clientDetailsService() { private UserApprovalHandler userApprovalHandler(HttpSecurity http) { if (userApprovalHandler == null) { - TokenStoreUserApprovalHandler userApprovalHandler = new TokenStoreUserApprovalHandler(); - userApprovalHandler.setTokenStore(tokenStore()); - userApprovalHandler.setClientDetailsService(clientDetails()); - userApprovalHandler.setRequestFactory(requestFactory(http)); - this.userApprovalHandler = userApprovalHandler; + if (approvalStore()!=null) { + ApprovalStoreUserApprovalHandler handler = new ApprovalStoreUserApprovalHandler(); + handler.setApprovalStore(approvalStore()); + handler.setRequestFactory(requestFactory); + handler.setClientDetailsService(clientDetailsService); + this.userApprovalHandler = handler; + } + else if (tokenStore() != null) { + TokenStoreUserApprovalHandler userApprovalHandler = new TokenStoreUserApprovalHandler(); + userApprovalHandler.setTokenStore(tokenStore()); + userApprovalHandler.setClientDetailsService(clientDetails()); + userApprovalHandler.setRequestFactory(requestFactory(http)); + this.userApprovalHandler = userApprovalHandler; + } else { + throw new IllegalStateException("Either a TokenStore or an ApprovalStore must be provided"); + } } return this.userApprovalHandler; } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java index 80eccfd7c..c936d6a60 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java @@ -70,6 +70,7 @@ public static List parameters() { new Object[] { null, new Class[] { AuthorizationServerExtras.class } }, new Object[] { null, new Class[] { AuthorizationServerJdbc.class } }, new Object[] { null, new Class[] { AuthorizationServerJwt.class } }, + new Object[] { null, new Class[] { AuthorizationServerApproval.class } }, new Object[] { BeanCreationException.class, new Class[] { AuthorizationServerTypes.class } } // @formatter:on ); @@ -207,6 +208,40 @@ public void configure(ClientDetailsServiceConfigurer clients) throws Exception { } + @Configuration + @EnableWebMvcSecurity + @EnableAuthorizationServer + protected static class AuthorizationServerApproval extends AuthorizationServerConfigurerAdapter implements Runnable { + + private TokenStore tokenStore = new InMemoryTokenStore(); + + @Autowired + private ApplicationContext context; + + @Override + public void configure(OAuth2AuthorizationServerConfigurer oauthServer) throws Exception { + oauthServer.tokenStore(tokenStore); + } + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + // @formatter:off + clients.inMemory() + .withClient("my-trusted-client") + .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit") + .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") + .scopes("read", "write", "trust") + .accessTokenValiditySeconds(60); + // @formatter:on + } + + @Override + public void run() { + assertNotNull(ReflectionTestUtils.getField(context.getBean(AuthorizationEndpoint.class), "userApprovalHandler")); + } + + } + @Configuration @EnableWebMvcSecurity protected static class AuthorizationServerTypes extends AuthorizationServerConfiguration { From f9c35a173276df5074ac314b23499f515c410fd5 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 2 Apr 2014 10:33:34 +0100 Subject: [PATCH 205/831] Update spring-security-jwt's dependencies --- spring-security-jwt/pom.xml | 12 ++++++------ .../security/jwt/RubyJwtIntegrationTests.java | 3 --- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/spring-security-jwt/pom.xml b/spring-security-jwt/pom.xml index d061b10e3..525c8d6db 100755 --- a/spring-security-jwt/pom.xml +++ b/spring-security-jwt/pom.xml @@ -9,8 +9,8 @@ jar Spring Security JWT Library - Spring Security JWT is a small utility library for encoding and decoding JSON Web Tokens. - It belongs to the family of Spring Security crypto libraries that handle encoding and decoding text as + Spring Security JWT is a small utility library for encoding and decoding JSON Web Tokens. + It belongs to the family of Spring Security crypto libraries that handle encoding and decoding text as a general, useful thing to be able to do. http://github.com/spring-projects/spring-security-oauth @@ -29,7 +29,7 @@ org.codehaus.jackson jackson-mapper-asl - 1.8.3 + 1.9.13 @@ -42,14 +42,14 @@ junit junit - 4.8.2 + 4.11 test org.mockito mockito-all - 1.9.0 + 1.9.5 test @@ -57,7 +57,7 @@ org.jruby jruby - 1.6.5 + 1.7.8 test diff --git a/spring-security-jwt/src/test/java/org/springframework/security/jwt/RubyJwtIntegrationTests.java b/spring-security-jwt/src/test/java/org/springframework/security/jwt/RubyJwtIntegrationTests.java index 33821d3a3..004c3007f 100644 --- a/spring-security-jwt/src/test/java/org/springframework/security/jwt/RubyJwtIntegrationTests.java +++ b/spring-security-jwt/src/test/java/org/springframework/security/jwt/RubyJwtIntegrationTests.java @@ -66,7 +66,6 @@ public void rubyCanDecodeHmacSignedToken() throws Exception { container.put("@token", jwt.getEncoded()); container.put("@claims", ""); String script = - "require \"rubygems\"\n" + "require \"jwt\"\n" + "@claims = JWT.decode(@token, \"secret\", \"HS256\").to_json\n" + "puts @claims"; @@ -79,7 +78,6 @@ public void canDecodeRubyHmacSignedToken() throws Exception { ScriptingContainer container = new ScriptingContainer(); container.put("@token", "xxx"); String script = - "require \"rubygems\"\n" + "require \"jwt\"\n" + "@token = JWT.encode({\"some\" => \"payload\"}, \"secret\", \"HS256\")\n" + "puts @token"; @@ -100,7 +98,6 @@ public JRubyJwtInstalled() { setupOkSet = true; try { String script = - "require \"rubygems\"\n" + "require \"jwt\"\n" + "require \"bouncy-castle-java\"\n" + "require \"openssl\""; From 50a7956d4432d523155d3cfa6e17fc0ea1070463 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 2 Apr 2014 11:25:07 +0100 Subject: [PATCH 206/831] Update oauth modules' dependencies The most notable update is the move to HttpComponents 4.3.3 in the oauth module, bringing it into line with Spring 4's dependency. A duplicate servlet API dependency has also been removed. --- samples/oauth2/sparklr/pom.xml | 2 +- .../oauth2/provider/ServerRunning.java | 35 +++++++++++-------- spring-security-oauth/pom.xml | 15 +++----- spring-security-oauth2/pom.xml | 14 ++++---- 4 files changed, 33 insertions(+), 33 deletions(-) diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index f86461c2a..42cec8296 100644 --- a/samples/oauth2/sparklr/pom.xml +++ b/samples/oauth2/sparklr/pom.xml @@ -193,7 +193,7 @@ org.apache.httpcomponents httpclient - 4.3.2 + 4.3.3 test diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ServerRunning.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ServerRunning.java index 03a20984f..fe8a786f6 100644 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ServerRunning.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ServerRunning.java @@ -12,8 +12,12 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.client.HttpClient; +import org.apache.http.client.config.CookieSpecs; +import org.apache.http.client.config.RequestConfig; import org.apache.http.client.params.ClientPNames; import org.apache.http.client.params.CookiePolicy; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.protocol.HttpContext; import org.junit.Assume; import org.junit.internal.AssumptionViolatedException; import org.junit.rules.MethodRule; @@ -42,22 +46,22 @@ * the server is not running in the background all the tests here will simply be skipped because of a violated * assumption (showing as successful). Usage: *

    - * + * *
      * @Rule public static BrokerRunning brokerIsRunning = BrokerRunning.isRunning();
    - * 
    + *
      * @Test public void testSendAndReceive() throws Exception { // ... test using RabbitTemplate etc. }
      * 
    *

    * The rule can be declared as static so that it only has to check once for all tests in the enclosing test case, but * there isn't a lot of overhead in making it non-static. *

    - * + * * @see Assume * @see AssumptionViolatedException - * + * * @author Dave Syer - * + * */ @SuppressWarnings("deprecation") public class ServerRunning implements MethodRule, RestTemplateHolder { @@ -81,7 +85,7 @@ public class ServerRunning implements MethodRule, RestTemplateHolder { private String hostName = DEFAULT_HOST; private RestOperations client; - + /** * @return a new rule that assumes an existing running broker */ @@ -183,7 +187,7 @@ public void evaluate() throws Throwable { }; } - + public String getBaseUrl() { return "http://" + hostName + ":" + port; } @@ -304,17 +308,20 @@ public void setRestTemplate(RestOperations restTemplate) { public RestOperations getRestTemplate() { return client; } - + public RestOperations createRestTemplate() { RestTemplate client = new RestTemplate(); client.setRequestFactory(new HttpComponentsClientHttpRequestFactory() { @Override - public HttpClient getHttpClient() { - HttpClient client = super.getHttpClient(); - client.getParams().setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, false); - client.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.IGNORE_COOKIES); - client.getParams().setBooleanParameter(ClientPNames.HANDLE_AUTHENTICATION, false); - return client; + protected HttpContext createHttpContext(HttpMethod httpMethod, URI uri) { + HttpContext httpContext = HttpClientContext.create(); + RequestConfig requestConfig = RequestConfig.custom() + .setRedirectsEnabled(false) + .setCookieSpec(CookieSpecs.IGNORE_COOKIES) + .setAuthenticationEnabled(false) + .build(); + httpContext.setAttribute(HttpClientContext.REQUEST_CONFIG, requestConfig); + return httpContext; } }); client.setErrorHandler(new ResponseErrorHandler() { diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index ba8a9f8ab..473f8e906 100644 --- a/spring-security-oauth/pom.xml +++ b/spring-security-oauth/pom.xml @@ -48,13 +48,6 @@ - - javax.servlet - servlet-api - 2.5 - provided - - org.springframework @@ -139,14 +132,14 @@ junit junit - 4.8.2 + 4.11 test org.mockito mockito-core - 1.9.0 + 1.9.5 test @@ -174,13 +167,13 @@ org.apache.httpcomponents httpclient - 4.1.1 + 4.3.3 org.slf4j slf4j-api - 1.5.8 + 1.7.6 test diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index a41a26d38..1b8526970 100644 --- a/spring-security-oauth2/pom.xml +++ b/spring-security-oauth2/pom.xml @@ -12,11 +12,11 @@ OAuth2 for Spring Security Module for providing OAuth2 support to Spring Security - - 1.9.2 - 2.3.1 - 1.0.1.RELEASE - + + 1.9.13 + 2.3.2 + 1.0.2.BUILD-SNAPSHOT + @@ -194,14 +194,14 @@ org.mockito mockito-core - 1.9.0 + 1.9.5 test org.slf4j slf4j-api - 1.5.8 + 1.7.6 test From 23eee7becf5ced92a2217c1057410f73522e6a42 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 4 Apr 2014 16:05:27 +0100 Subject: [PATCH 207/831] Fix some broken tests The upgrade to Jackson2 exposed some other bugs with deserializing exceptions. Should be green now. Fixes gh-177 --- .../oauth2/provider/ServerRunning.java | 46 ++++++++----------- spring-security-oauth2/pom.xml | 7 +++ .../client/http/OAuth2ErrorHandler.java | 2 +- .../common/exceptions/OAuth2Exception.java | 1 + .../OAuth2ExceptionJackson2Deserializer.java | 13 ++++-- .../OAuth2ExceptionDeserializerTests.java | 10 ++++ 6 files changed, 46 insertions(+), 33 deletions(-) diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ServerRunning.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ServerRunning.java index fe8a786f6..2c21e3397 100644 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ServerRunning.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ServerRunning.java @@ -11,11 +11,9 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.http.client.HttpClient; import org.apache.http.client.config.CookieSpecs; import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.params.ClientPNames; -import org.apache.http.client.params.CookiePolicy; +import org.apache.http.client.config.RequestConfig.Builder; import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.protocol.HttpContext; import org.junit.Assume; @@ -34,7 +32,7 @@ import org.springframework.security.oauth2.client.test.RestTemplateHolder; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; -import org.springframework.web.client.ResponseErrorHandler; +import org.springframework.web.client.DefaultResponseErrorHandler; import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestOperations; import org.springframework.web.client.RestTemplate; @@ -46,24 +44,23 @@ * the server is not running in the background all the tests here will simply be skipped because of a violated * assumption (showing as successful). Usage: *

    - * + * *
      * @Rule public static BrokerRunning brokerIsRunning = BrokerRunning.isRunning();
    - *
    + * 
      * @Test public void testSendAndReceive() throws Exception { // ... test using RabbitTemplate etc. }
      * 
    *

    * The rule can be declared as static so that it only has to check once for all tests in the enclosing test case, but * there isn't a lot of overhead in making it non-static. *

    - * + * * @see Assume * @see AssumptionViolatedException - * + * * @author Dave Syer - * + * */ -@SuppressWarnings("deprecation") public class ServerRunning implements MethodRule, RestTemplateHolder { private static Log logger = LogFactory.getLog(ServerRunning.class); @@ -168,8 +165,7 @@ public Statement apply(final Statement base, FrameworkMethod method, Object targ } final RestOperations savedClient = getRestTemplate(); - postForStatus(savedClient, "/sparklr2/oauth/uncache_approvals", - new LinkedMultiValueMap()); + postForStatus(savedClient, "/sparklr2/oauth/uncache_approvals", new LinkedMultiValueMap()); return new Statement() { @@ -250,7 +246,7 @@ private ResponseEntity postForStatus(RestOperations client, String path, H actualHeaders.putAll(headers); actualHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED); return client.exchange(getUrl(path), HttpMethod.POST, new HttpEntity>(formData, - actualHeaders), (Class)null); + actualHeaders), (Class) null); } public ResponseEntity postForRedirect(String path, HttpHeaders headers, MultiValueMap params) { @@ -267,7 +263,7 @@ public ResponseEntity postForRedirect(String path, HttpHeaders headers, Mu String location = exchange.getHeaders().getLocation().toString(); - return client.exchange(location, HttpMethod.GET, new HttpEntity(null, headers), (Class)null); + return client.exchange(location, HttpMethod.GET, new HttpEntity(null, headers), (Class) null); } public ResponseEntity getForString(String path) { @@ -285,7 +281,7 @@ public ResponseEntity getForString(String path, final HttpHeaders header public ResponseEntity getForResponse(String path, final HttpHeaders headers, Map uriVariables) { HttpEntity request = new HttpEntity(null, headers); - return client.exchange(getUrl(path), HttpMethod.GET, request, (Class)null, uriVariables); + return client.exchange(getUrl(path), HttpMethod.GET, request, (Class) null, uriVariables); } public ResponseEntity getForResponse(String path, HttpHeaders headers) { @@ -314,24 +310,18 @@ public RestOperations createRestTemplate() { client.setRequestFactory(new HttpComponentsClientHttpRequestFactory() { @Override protected HttpContext createHttpContext(HttpMethod httpMethod, URI uri) { - HttpContext httpContext = HttpClientContext.create(); - RequestConfig requestConfig = RequestConfig.custom() - .setRedirectsEnabled(false) - .setCookieSpec(CookieSpecs.IGNORE_COOKIES) - .setAuthenticationEnabled(false) - .build(); - httpContext.setAttribute(HttpClientContext.REQUEST_CONFIG, requestConfig); - return httpContext; + HttpClientContext context = HttpClientContext.create(); + Builder builder = RequestConfig.custom().setCookieSpec(CookieSpecs.IGNORE_COOKIES) + .setAuthenticationEnabled(false).setRedirectsEnabled(false); + context.setRequestConfig(builder.build()); + return context; } }); - client.setErrorHandler(new ResponseErrorHandler() { - // Pass errors through in response entity for status code analysis + client.setErrorHandler(new DefaultResponseErrorHandler() { + @Override public boolean hasError(ClientHttpResponse response) throws IOException { return false; } - - public void handleError(ClientHttpResponse response) throws IOException { - } }); return client; } diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 1b8526970..95a81921e 100644 --- a/spring-security-oauth2/pom.xml +++ b/spring-security-oauth2/pom.xml @@ -169,6 +169,13 @@ true
    + + org.apache.httpcomponents + httpclient + 4.3.3 + true + + junit junit diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandler.java index ebf17fd6f..ea0cfb23a 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandler.java @@ -148,7 +148,7 @@ public int getRawStatusCode() throws IOException { errorHandler.handleError(bufferedResponse); } catch (OAuth2Exception ex) { - if (bufferedResponse.getRawStatusCode() == 401 || ! ex.getClass().equals(OAuth2Exception.class)) { + if (bufferedResponse.getRawStatusCode() == 403 || bufferedResponse.getRawStatusCode() == 401 || ! ex.getClass().equals(OAuth2Exception.class)) { // Status code 401 should always mean that we need a legitimate token. // Caught a specific, derived class so this is not just some generic error throw ex; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2Exception.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2Exception.java index 3a3d08fc2..3ee73cac0 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2Exception.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2Exception.java @@ -27,6 +27,7 @@ public class OAuth2Exception extends RuntimeException { public static final String UNAUTHORIZED_CLIENT = "unauthorized_client"; public static final String UNSUPPORTED_GRANT_TYPE = "unsupported_grant_type"; public static final String INVALID_SCOPE = "invalid_scope"; + public static final String INSUFFICIENT_SCOPE = "insufficient_scope"; public static final String INVALID_TOKEN = "invalid_token"; public static final String REDIRECT_URI_MISMATCH ="redirect_uri_mismatch"; public static final String UNSUPPORTED_RESPONSE_TYPE ="unsupported_response_type"; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson2Deserializer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson2Deserializer.java index b829a3441..c9fda44ae 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson2Deserializer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson2Deserializer.java @@ -12,7 +12,6 @@ */ package org.springframework.security.oauth2.common.exceptions; - import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonToken; @@ -25,6 +24,8 @@ import java.util.Map; import java.util.Set; +import org.springframework.security.oauth2.common.util.OAuth2Utils; + /** * @author Brian Clozel * @@ -32,9 +33,9 @@ @SuppressWarnings("serial") public class OAuth2ExceptionJackson2Deserializer extends StdDeserializer { - public OAuth2ExceptionJackson2Deserializer() { - super(OAuth2Exception.class); - } + public OAuth2ExceptionJackson2Deserializer() { + super(OAuth2Exception.class); + } @Override public OAuth2Exception deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, @@ -108,6 +109,10 @@ else if ("unsupported_grant_type".equals(errorCode)) { else if ("unsupported_response_type".equals(errorCode)) { ex = new UnsupportedResponseTypeException(errorMessage); } + else if ("insufficient_scope".equals(errorCode)) { + ex = new InsufficientScopeException(errorMessage, OAuth2Utils.parseParameterList((String) errorParams + .get("scope"))); + } else if ("access_denied".equals(errorCode)) { ex = new UserDeniedAuthorizationException(errorMessage); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/OAuth2ExceptionDeserializerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/OAuth2ExceptionDeserializerTests.java index 456e7b83d..14de789f4 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/OAuth2ExceptionDeserializerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/OAuth2ExceptionDeserializerTests.java @@ -17,6 +17,7 @@ import org.codehaus.jackson.map.ObjectMapper; import org.junit.BeforeClass; import org.junit.Test; +import org.springframework.security.oauth2.common.exceptions.InsufficientScopeException; import org.springframework.security.oauth2.common.exceptions.InvalidClientException; import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; import org.springframework.security.oauth2.common.exceptions.InvalidRequestException; @@ -31,6 +32,7 @@ /** * * @author Rob Winch + * @author Dave Syer * */ public class OAuth2ExceptionDeserializerTests { @@ -66,6 +68,14 @@ public void readValueInvalidScope() throws Exception { assertEquals(null,result.getAdditionalInformation()); } + @Test + public void readValueIsufficientScope() throws Exception { + String accessToken = "{\"error\": \"insufficient_scope\", \"error_description\": \"insufficient scope\", \"scope\": \"bar foo\"}"; + InsufficientScopeException result = (InsufficientScopeException) mapper.readValue(accessToken, OAuth2Exception.class); + assertEquals("insufficient scope",result.getMessage()); + assertEquals("bar foo",result.getAdditionalInformation().get("scope").toString()); + } + @Test public void readValueUnsupportedGrantType() throws Exception { String accessToken = createResponse(OAuth2Exception.UNSUPPORTED_GRANT_TYPE); From ad859587eb3915cfbc22e58bf15dbcbe9b018010 Mon Sep 17 00:00:00 2001 From: Michael Lavelle Date: Fri, 4 Apr 2014 16:26:19 +0100 Subject: [PATCH 208/831] Adding /me endpoint to support Spring Social clients Fixes gh-180 --- .../examples/sparklr/PhotoServiceUser.java | 45 +++++++++++++++++++ .../sparklr/config/OAuth2ServerConfig.java | 6 ++- .../examples/sparklr/config/WebMvcConfig.java | 8 ++++ .../mvc/PhotoServiceUserController.java | 25 +++++++++++ 4 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/PhotoServiceUser.java create mode 100644 samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/PhotoServiceUserController.java diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/PhotoServiceUser.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/PhotoServiceUser.java new file mode 100644 index 000000000..bbc13d796 --- /dev/null +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/PhotoServiceUser.java @@ -0,0 +1,45 @@ +package org.springframework.security.oauth.examples.sparklr; + +/** + * Photo service user information - added to enable user information to be available to Spring Social client + * + * @author Michael Lavelle + */ +public class PhotoServiceUser { + + private String username; + private String name; + + /** + * Create a new PhotoServiceUser + * + * @param username The unique username for the user + * @param name The name of the user + */ + public PhotoServiceUser(String username,String name) + { + this.username = username; + this.name = name; + } + + /** + * The unique username for the user + * + * @return username of the user + */ + public String getUsername() { + return username; + } + + /** + * The name of the user + * + * @return name of the user + */ + public String getName() { + return name; + } + + + +} diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java index 07bbf40c6..720b80c01 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java @@ -56,9 +56,10 @@ protected static class UiResourceConfiguration extends WebSecurityConfigurerAdap protected void configure(HttpSecurity http) throws Exception { // @formatter:off http - .requestMatchers().antMatchers("/photos/**") + .requestMatchers().antMatchers("/photos/**","/me") .and() .authorizeRequests() + .antMatchers("/me").access("hasRole('ROLE_USER')") .antMatchers("/photos").access("hasRole('ROLE_USER')") .antMatchers("/photos/trusted/**").access("hasRole('ROLE_USER')") .antMatchers("/photos/user/**").access("hasRole('ROLE_USER')") @@ -80,9 +81,10 @@ public void configure(OAuth2ResourceServerConfigurer resources) { public void configure(HttpSecurity http) throws Exception { // @formatter:off http - .requestMatchers().antMatchers("/photos/**", "/oauth/users/**", "/oauth/clients/**") + .requestMatchers().antMatchers("/photos/**", "/oauth/users/**", "/oauth/clients/**","/me") .and() .authorizeRequests() + .antMatchers("/me").access("#oauth2.hasScope('read')") .antMatchers("/photos").access("#oauth2.hasScope('read')") .antMatchers("/photos/trusted/**").access("#oauth2.hasScope('trust')") .antMatchers("/photos/user/**").access("#oauth2.hasScope('trust')") diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/WebMvcConfig.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/WebMvcConfig.java index d0394fbeb..4089ce918 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/WebMvcConfig.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/WebMvcConfig.java @@ -14,6 +14,7 @@ import org.springframework.security.oauth.examples.sparklr.mvc.AccessConfirmationController; import org.springframework.security.oauth.examples.sparklr.mvc.AdminController; import org.springframework.security.oauth.examples.sparklr.mvc.PhotoController; +import org.springframework.security.oauth.examples.sparklr.mvc.PhotoServiceUserController; import org.springframework.security.oauth.examples.sparklr.oauth.SparklrUserApprovalHandler; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.approval.ApprovalStore; @@ -57,6 +58,13 @@ public ContentNegotiatingViewResolver contentViewResolver() throws Exception { return contentViewResolver; } + + @Bean + public PhotoServiceUserController photoServiceUserController(PhotoService photoService) { + PhotoServiceUserController photoServiceUserController = new PhotoServiceUserController(); + return photoServiceUserController; + } + @Bean public PhotoController photoController(PhotoService photoService) { PhotoController photoController = new PhotoController(); diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/PhotoServiceUserController.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/PhotoServiceUserController.java new file mode 100644 index 000000000..b2e2ef7ee --- /dev/null +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/PhotoServiceUserController.java @@ -0,0 +1,25 @@ +package org.springframework.security.oauth.examples.sparklr.mvc; + +import java.security.Principal; + +import org.springframework.security.oauth.examples.sparklr.PhotoServiceUser; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +/** + * @author Michael Lavelle + * + * Added to provide an endpoint from which Spring Social can obtain authentication details + */ +@RequestMapping("/me") +@Controller +public class PhotoServiceUserController { + + @ResponseBody + @RequestMapping("") + public PhotoServiceUser getPhotoServiceUser(Principal principal) + { + return new PhotoServiceUser(principal.getName(),principal.getName()); + } +} From 7c24bacd218eefcd7e8ad4651e846ae4075b6855 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 4 Apr 2014 17:41:54 +0100 Subject: [PATCH 209/831] Make access token setter for value more conventional i.e. it has a void return type. Previously it had returned a new object, in an attempt to normalize the hashCode and equals implementations. I believe those may now occasionally be invalid (e.g. if someone sets the expiration without setting the value) in some circumstances, but the value of a token is still used as the sole source of data for hashing. Fixes gh-175 --- .../common/DefaultOAuth2AccessToken.java | 6 +- .../provider/token/JwtTokenEnhancer.java | 3 +- .../provider/token/JwtTokenServices.java | 12 +- ...th2ExceptionJackson2DeserializerTests.java | 164 ++++++++++++++++ .../AbstractTestDefaultTokenServices.java | 183 +++++++----------- .../provider/token/JwtTokenServicesTests.java | 7 +- 6 files changed, 250 insertions(+), 125 deletions(-) create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/OAuth2ExceptionJackson2DeserializerTests.java diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/DefaultOAuth2AccessToken.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/DefaultOAuth2AccessToken.java index 9dbc83c15..4ecf4a186 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/DefaultOAuth2AccessToken.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/DefaultOAuth2AccessToken.java @@ -61,10 +61,8 @@ public DefaultOAuth2AccessToken(OAuth2AccessToken accessToken) { setTokenType(accessToken.getTokenType()); } - public DefaultOAuth2AccessToken setValue(String value) { - DefaultOAuth2AccessToken result = new DefaultOAuth2AccessToken(this); - result.value = value; - return result; + public void setValue(String value) { + this.value = value; } /** diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancer.java index c7b8845d8..931ac5b9d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancer.java @@ -132,7 +132,8 @@ public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentica info.put(TOKEN_ID, tokenId); } result.setAdditionalInformation(info); - return result.setValue(encode(result, authentication)); + result.setValue(encode(result, authentication)); + return result; } protected String encode(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenServices.java index c200659d9..bbfc25aea 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenServices.java @@ -221,9 +221,9 @@ public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) { result = new DefaultOAuth2AccessToken(accessTokenEnhancer.enhance(result, authentication)); } - DefaultOAuth2AccessToken token = result.setValue(encode(result, authentication)); + result.setValue(encode(result, authentication)); - return token; + return result; } @@ -334,12 +334,12 @@ private ExpiringOAuth2RefreshToken createRefreshToken(OAuth2Authentication authe if (!isSupportRefreshToken(authentication.getOAuth2Request())) { return null; } - DefaultOAuth2AccessToken accessToken = new DefaultOAuth2AccessToken(getAccessToken(authentication)); + DefaultOAuth2AccessToken encodedRefreshToken = new DefaultOAuth2AccessToken(getAccessToken(authentication)); int validitySeconds = getRefreshTokenValiditySeconds(authentication.getOAuth2Request()); Date expiration = new Date(System.currentTimeMillis() + (validitySeconds * 1000L)); - accessToken.setExpiration(expiration); - accessToken.setValue(encode(accessToken, authentication)); - ExpiringOAuth2RefreshToken refreshToken = new DefaultExpiringOAuth2RefreshToken(accessToken.getValue(), + encodedRefreshToken.setExpiration(expiration); + encodedRefreshToken.setValue(encode(encodedRefreshToken, authentication)); + ExpiringOAuth2RefreshToken refreshToken = new DefaultExpiringOAuth2RefreshToken(encodedRefreshToken.getValue(), expiration); return refreshToken; } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/OAuth2ExceptionJackson2DeserializerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/OAuth2ExceptionJackson2DeserializerTests.java new file mode 100644 index 000000000..019dcb1ff --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/OAuth2ExceptionJackson2DeserializerTests.java @@ -0,0 +1,164 @@ +/* + * Copyright 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.common.exception; + +import static org.junit.Assert.assertEquals; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.springframework.security.oauth2.common.exceptions.InsufficientScopeException; +import org.springframework.security.oauth2.common.exceptions.InvalidClientException; +import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; +import org.springframework.security.oauth2.common.exceptions.InvalidRequestException; +import org.springframework.security.oauth2.common.exceptions.InvalidScopeException; +import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; +import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; +import org.springframework.security.oauth2.common.exceptions.RedirectMismatchException; +import org.springframework.security.oauth2.common.exceptions.UnauthorizedUserException; +import org.springframework.security.oauth2.common.exceptions.UnsupportedGrantTypeException; +import org.springframework.security.oauth2.common.exceptions.UserDeniedAuthorizationException; + +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * + * @author Rob Winch + * @author Dave Syer + * + */ +public class OAuth2ExceptionJackson2DeserializerTests { + private static final String DETAILS = "some detail"; + private static ObjectMapper mapper; + + @BeforeClass + public static void setUpClass() { + mapper = new ObjectMapper(); + } + + @Test + public void readValueInvalidGrant() throws Exception { + String accessToken = createResponse(OAuth2Exception.INVALID_GRANT); + InvalidGrantException result = (InvalidGrantException) mapper.readValue(accessToken, OAuth2Exception.class); + assertEquals(DETAILS,result.getMessage()); + assertEquals(null,result.getAdditionalInformation()); + } + + @Test + public void readValueInvalidRequest() throws Exception { + String accessToken = createResponse(OAuth2Exception.INVALID_REQUEST); + InvalidRequestException result = (InvalidRequestException) mapper.readValue(accessToken, OAuth2Exception.class); + assertEquals(DETAILS,result.getMessage()); + assertEquals(null,result.getAdditionalInformation()); + } + + @Test + public void readValueInvalidScope() throws Exception { + String accessToken = createResponse(OAuth2Exception.INVALID_SCOPE); + InvalidScopeException result = (InvalidScopeException) mapper.readValue(accessToken, OAuth2Exception.class); + assertEquals(DETAILS,result.getMessage()); + assertEquals(null,result.getAdditionalInformation()); + } + + @Test + public void readValueIsufficientScope() throws Exception { + String accessToken = "{\"error\": \"insufficient_scope\", \"error_description\": \"insufficient scope\", \"scope\": \"bar foo\"}"; + InsufficientScopeException result = (InsufficientScopeException) mapper.readValue(accessToken, OAuth2Exception.class); + assertEquals("insufficient scope",result.getMessage()); + assertEquals("bar foo",result.getAdditionalInformation().get("scope").toString()); + } + + @Test + public void readValueUnsupportedGrantType() throws Exception { + String accessToken = createResponse(OAuth2Exception.UNSUPPORTED_GRANT_TYPE); + UnsupportedGrantTypeException result = (UnsupportedGrantTypeException) mapper.readValue(accessToken, + OAuth2Exception.class); + assertEquals(DETAILS,result.getMessage()); + assertEquals(null,result.getAdditionalInformation()); + } + + @Test + public void readValueUnauthorizedClient() throws Exception { + String accessToken = createResponse(OAuth2Exception.UNAUTHORIZED_CLIENT); + UnauthorizedUserException result = (UnauthorizedUserException) mapper.readValue(accessToken, + OAuth2Exception.class); + assertEquals(DETAILS,result.getMessage()); + assertEquals(null,result.getAdditionalInformation()); + } + + @Test + public void readValueAccessDenied() throws Exception { + String accessToken = createResponse(OAuth2Exception.ACCESS_DENIED); + UserDeniedAuthorizationException result = (UserDeniedAuthorizationException) mapper.readValue(accessToken, + OAuth2Exception.class); + assertEquals(DETAILS,result.getMessage()); + assertEquals(null,result.getAdditionalInformation()); + } + + @Test + public void readValueRedirectUriMismatch() throws Exception { + String accessToken = createResponse(OAuth2Exception.INVALID_GRANT, "Redirect URI mismatch."); + RedirectMismatchException result = (RedirectMismatchException) mapper.readValue(accessToken, + OAuth2Exception.class); + assertEquals("Redirect URI mismatch.",result.getMessage()); + assertEquals(null,result.getAdditionalInformation()); + } + + @Test + public void readValueInvalidToken() throws Exception { + String accessToken = createResponse(OAuth2Exception.INVALID_TOKEN); + InvalidTokenException result = (InvalidTokenException) mapper.readValue(accessToken, OAuth2Exception.class); + assertEquals(DETAILS,result.getMessage()); + assertEquals(null,result.getAdditionalInformation()); + } + + @Test + public void readValueUndefinedException() throws Exception { + String accessToken = createResponse("notdefinedcode"); + OAuth2Exception result = mapper.readValue(accessToken, OAuth2Exception.class); + assertEquals(DETAILS,result.getMessage()); + assertEquals(null,result.getAdditionalInformation()); + } + + @Test + public void readValueInvalidClient() throws Exception { + String accessToken = createResponse(OAuth2Exception.INVALID_CLIENT); + InvalidClientException result = (InvalidClientException) mapper.readValue(accessToken, OAuth2Exception.class); + assertEquals(DETAILS,result.getMessage()); + assertEquals(null,result.getAdditionalInformation()); + } + + @Test + public void readValueWithAdditionalDetails() throws Exception { + String accessToken = "{\"error\": \"invalid_client\", \"error_description\": \"some detail\", \"foo\": \"bar\"}"; + InvalidClientException result = (InvalidClientException) mapper.readValue(accessToken, OAuth2Exception.class); + assertEquals(DETAILS,result.getMessage()); + assertEquals("{foo=bar}",result.getAdditionalInformation().toString()); + } + + @Test + public void readValueWithObjects() throws Exception { + String accessToken = "{\"error\": [\"invalid\",\"client\"], \"error_description\": {\"some\":\"detail\"}, \"foo\": [\"bar\"]}"; + OAuth2Exception result = mapper.readValue(accessToken, OAuth2Exception.class); + assertEquals("{some=detail}",result.getMessage()); + assertEquals("{foo=[bar]}",result.getAdditionalInformation().toString()); + } + + private String createResponse(String error, String message) { + return "{\"error\":\"" + error + "\",\"error_description\":\""+message+"\"}"; + } + + private String createResponse(String error) { + return createResponse(error, DETAILS); + } + +} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractTestDefaultTokenServices.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractTestDefaultTokenServices.java index 0b7789139..d465987b3 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractTestDefaultTokenServices.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractTestDefaultTokenServices.java @@ -49,108 +49,89 @@ public void setUp() throws Exception { @Test public void testTokenEnhancerUpdatesStoredTokens() throws Exception { - final ExpiringOAuth2RefreshToken refreshToken = new DefaultExpiringOAuth2RefreshToken( - "testToken", new Date(System.currentTimeMillis() + 100000)); + final ExpiringOAuth2RefreshToken refreshToken = new DefaultExpiringOAuth2RefreshToken("testToken", new Date( + System.currentTimeMillis() + 100000)); getTokenServices().setTokenEnhancer(new TokenEnhancer() { - public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, - OAuth2Authentication authentication) { - DefaultOAuth2AccessToken result = new DefaultOAuth2AccessToken( - accessToken); + public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { + DefaultOAuth2AccessToken result = new DefaultOAuth2AccessToken(accessToken); result.setRefreshToken(refreshToken); return result; } }); OAuth2Authentication authentication = createAuthentication(); - OAuth2AccessToken original = getTokenServices().createAccessToken( - authentication); + OAuth2AccessToken original = getTokenServices().createAccessToken(authentication); assertTrue(original.getRefreshToken().equals(refreshToken)); OAuth2AccessToken result = tokenStore.getAccessToken(authentication); assertEquals(original, result); assertEquals(refreshToken, result.getRefreshToken()); - assertEquals(refreshToken, - tokenStore.readRefreshToken(refreshToken.getValue())); + assertEquals(refreshToken, tokenStore.readRefreshToken(refreshToken.getValue())); } @Test public void testTokenRevoked() throws Exception { OAuth2Authentication authentication = createAuthentication(); - OAuth2AccessToken original = getTokenServices().createAccessToken( - authentication); + OAuth2AccessToken original = getTokenServices().createAccessToken(authentication); tokenStore.removeAccessToken(original); - assertEquals( - 0, - tokenStore.findTokensByClientId( - authentication.getOAuth2Request().getClientId()).size()); + assertEquals(0, tokenStore.findTokensByClientId(authentication.getOAuth2Request().getClientId()).size()); } @Test public void testRefreshedTokenIsEnhanced() throws Exception { getTokenServices().setTokenEnhancer(new TokenEnhancer() { - public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, - OAuth2Authentication authentication) { - return new DefaultOAuth2AccessToken(accessToken) - .setValue("I'mEnhanced"); + public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { + DefaultOAuth2AccessToken result = new DefaultOAuth2AccessToken(accessToken); + result.setValue("I'mEnhanced"); + return result; } }); - OAuth2AccessToken accessToken = getTokenServices().createAccessToken( - createAuthentication()); + OAuth2AccessToken accessToken = getTokenServices().createAccessToken(createAuthentication()); assertTrue(accessToken.getValue().startsWith("I'mEnhanced")); - TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap( - "client_id", "id"), "id", null, null); - OAuth2AccessToken refreshedAccessToken = getTokenServices() - .refreshAccessToken(accessToken.getRefreshToken().getValue(), - tokenRequest); + TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap("client_id", "id"), "id", null, null); + OAuth2AccessToken refreshedAccessToken = getTokenServices().refreshAccessToken( + accessToken.getRefreshToken().getValue(), tokenRequest); assertTrue(refreshedAccessToken.getValue().startsWith("I'mEnhanced")); } @Test public void testRefreshedTokenHasScopes() throws Exception { - ExpiringOAuth2RefreshToken expectedExpiringRefreshToken = new DefaultExpiringOAuth2RefreshToken( - "testToken", new Date(System.currentTimeMillis() + 100000)); - tokenStore.storeRefreshToken(expectedExpiringRefreshToken, - createAuthentication()); - TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap( - "client_id", "id"), "id", null, null); - OAuth2AccessToken refreshedAccessToken = getTokenServices() - .refreshAccessToken(expectedExpiringRefreshToken.getValue(), - tokenRequest); + ExpiringOAuth2RefreshToken expectedExpiringRefreshToken = new DefaultExpiringOAuth2RefreshToken("testToken", + new Date(System.currentTimeMillis() + 100000)); + tokenStore.storeRefreshToken(expectedExpiringRefreshToken, createAuthentication()); + TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap("client_id", "id"), "id", null, null); + OAuth2AccessToken refreshedAccessToken = getTokenServices().refreshAccessToken( + expectedExpiringRefreshToken.getValue(), tokenRequest); assertEquals("[read, write]", refreshedAccessToken.getScope().toString()); } @Test public void testRefreshedTokenHasNarrowedScopes() throws Exception { - ExpiringOAuth2RefreshToken expectedExpiringRefreshToken = new DefaultExpiringOAuth2RefreshToken( - "testToken", new Date(System.currentTimeMillis() + 100000)); - tokenStore.storeRefreshToken(expectedExpiringRefreshToken, - createAuthentication()); - TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap( - "client_id", "id"), "id", Collections.singleton("read"), null); - OAuth2AccessToken refreshedAccessToken = getTokenServices() - .refreshAccessToken(expectedExpiringRefreshToken.getValue(), - tokenRequest); + ExpiringOAuth2RefreshToken expectedExpiringRefreshToken = new DefaultExpiringOAuth2RefreshToken("testToken", + new Date(System.currentTimeMillis() + 100000)); + tokenStore.storeRefreshToken(expectedExpiringRefreshToken, createAuthentication()); + TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap("client_id", "id"), "id", + Collections.singleton("read"), null); + OAuth2AccessToken refreshedAccessToken = getTokenServices().refreshAccessToken( + expectedExpiringRefreshToken.getValue(), tokenRequest); assertEquals("[read]", refreshedAccessToken.getScope().toString()); } @Test(expected = InvalidGrantException.class) public void testRefreshedTokenInvalidWithWrongClient() throws Exception { - ExpiringOAuth2RefreshToken expectedExpiringRefreshToken = new DefaultExpiringOAuth2RefreshToken( - "testToken", new Date(System.currentTimeMillis() + 100000)); - tokenStore.storeRefreshToken(expectedExpiringRefreshToken, - createAuthentication()); - TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap( - "client_id", "wrong"), "wrong", null, null); - OAuth2AccessToken refreshedAccessToken = getTokenServices() - .refreshAccessToken(expectedExpiringRefreshToken.getValue(), - tokenRequest); + ExpiringOAuth2RefreshToken expectedExpiringRefreshToken = new DefaultExpiringOAuth2RefreshToken("testToken", + new Date(System.currentTimeMillis() + 100000)); + tokenStore.storeRefreshToken(expectedExpiringRefreshToken, createAuthentication()); + TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap("client_id", "wrong"), "wrong", null, + null); + OAuth2AccessToken refreshedAccessToken = getTokenServices().refreshAccessToken( + expectedExpiringRefreshToken.getValue(), tokenRequest); assertEquals("[read]", refreshedAccessToken.getScope().toString()); } @Test public void testUnlimitedTokenExpiry() throws Exception { getTokenServices().setAccessTokenValiditySeconds(0); - OAuth2AccessToken accessToken = getTokenServices().createAccessToken( - createAuthentication()); + OAuth2AccessToken accessToken = getTokenServices().createAccessToken(createAuthentication()); assertEquals(0, accessToken.getExpiresIn()); assertEquals(null, accessToken.getExpiration()); } @@ -158,8 +139,7 @@ public void testUnlimitedTokenExpiry() throws Exception { @Test public void testDefaultTokenExpiry() throws Exception { getTokenServices().setAccessTokenValiditySeconds(100); - OAuth2AccessToken accessToken = getTokenServices().createAccessToken( - createAuthentication()); + OAuth2AccessToken accessToken = getTokenServices().createAccessToken(createAuthentication()); assertTrue(100 >= accessToken.getExpiresIn()); } @@ -167,15 +147,13 @@ public void testDefaultTokenExpiry() throws Exception { public void testClientSpecificTokenExpiry() throws Exception { getTokenServices().setAccessTokenValiditySeconds(1000); getTokenServices().setClientDetailsService(new ClientDetailsService() { - public ClientDetails loadClientByClientId(String clientId) - throws OAuth2Exception { + public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exception { BaseClientDetails client = new BaseClientDetails(); client.setAccessTokenValiditySeconds(100); return client; } }); - OAuth2AccessToken accessToken = getTokenServices().createAccessToken( - createAuthentication()); + OAuth2AccessToken accessToken = getTokenServices().createAccessToken(createAuthentication()); assertTrue(100 >= accessToken.getExpiresIn()); } @@ -183,33 +161,27 @@ public ClientDetails loadClientByClientId(String clientId) public void testClientSpecificRefreshTokenExpiry() throws Exception { getTokenServices().setRefreshTokenValiditySeconds(1000); getTokenServices().setClientDetailsService(new ClientDetailsService() { - public ClientDetails loadClientByClientId(String clientId) - throws OAuth2Exception { + public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exception { BaseClientDetails client = new BaseClientDetails(); client.setRefreshTokenValiditySeconds(100); - client.setAuthorizedGrantTypes(Arrays.asList( - "authorization_code", "refresh_token")); + client.setAuthorizedGrantTypes(Arrays.asList("authorization_code", "refresh_token")); return client; } }); - OAuth2AccessToken accessToken = getTokenServices().createAccessToken( - createAuthentication()); + OAuth2AccessToken accessToken = getTokenServices().createAccessToken(createAuthentication()); DefaultExpiringOAuth2RefreshToken refreshToken = (DefaultExpiringOAuth2RefreshToken) accessToken .getRefreshToken(); - Date expectedExpiryDate = new Date( - System.currentTimeMillis() + 102 * 1000L); + Date expectedExpiryDate = new Date(System.currentTimeMillis() + 102 * 1000L); assertTrue(expectedExpiryDate.after(refreshToken.getExpiration())); } @Test public void testOneAccessTokenPerAuthentication() throws Exception { OAuth2Authentication authentication = createAuthentication(); - OAuth2AccessToken first = getTokenServices().createAccessToken( - authentication); + OAuth2AccessToken first = getTokenServices().createAccessToken(authentication); assertEquals(1, getAccessTokenCount()); assertEquals(1, getRefreshTokenCount()); - OAuth2AccessToken second = getTokenServices().createAccessToken( - authentication); + OAuth2AccessToken second = getTokenServices().createAccessToken(authentication); assertEquals(first, second); assertEquals(1, getAccessTokenCount()); assertEquals(1, getRefreshTokenCount()); @@ -217,34 +189,28 @@ public void testOneAccessTokenPerAuthentication() throws Exception { @Test public void testOneAccessTokenPerUniqueAuthentication() throws Exception { - getTokenServices().createAccessToken( - new OAuth2Authentication(RequestTokenFactory - .createOAuth2Request(null, "id", null, false, - Collections.singleton("read"), null, null, - null, null), new TestAuthentication("test2", - false))); + getTokenServices() + .createAccessToken( + new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, + Collections.singleton("read"), null, null, null, null), new TestAuthentication("test2", + false))); assertEquals(1, getAccessTokenCount()); - getTokenServices().createAccessToken( - new OAuth2Authentication(RequestTokenFactory - .createOAuth2Request(null, "id", null, false, - Collections.singleton("write"), null, null, - null, null), new TestAuthentication("test2", - false))); + getTokenServices() + .createAccessToken( + new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, + Collections.singleton("write"), null, null, null, null), new TestAuthentication( + "test2", false))); assertEquals(2, getAccessTokenCount()); } @Test public void testRefreshTokenMaintainsState() throws Exception { getTokenServices().setSupportRefreshToken(true); - OAuth2AccessToken accessToken = getTokenServices().createAccessToken( - createAuthentication()); - OAuth2RefreshToken expectedExpiringRefreshToken = accessToken - .getRefreshToken(); - TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap( - "client_id", "id"), "id", null, null); - OAuth2AccessToken refreshedAccessToken = getTokenServices() - .refreshAccessToken(expectedExpiringRefreshToken.getValue(), - tokenRequest); + OAuth2AccessToken accessToken = getTokenServices().createAccessToken(createAuthentication()); + OAuth2RefreshToken expectedExpiringRefreshToken = accessToken.getRefreshToken(); + TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap("client_id", "id"), "id", null, null); + OAuth2AccessToken refreshedAccessToken = getTokenServices().refreshAccessToken( + expectedExpiringRefreshToken.getValue(), tokenRequest); assertNotNull(refreshedAccessToken); assertEquals(1, getAccessTokenCount()); } @@ -253,26 +219,19 @@ public void testRefreshTokenMaintainsState() throws Exception { public void testNotReuseRefreshTokenMaintainsState() throws Exception { getTokenServices().setSupportRefreshToken(true); getTokenServices().setReuseRefreshToken(false); - OAuth2AccessToken accessToken = getTokenServices().createAccessToken( - createAuthentication()); - OAuth2RefreshToken expectedExpiringRefreshToken = accessToken - .getRefreshToken(); - TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap( - "client_id", "id"), "id", null, null); - OAuth2AccessToken refreshedAccessToken = getTokenServices() - .refreshAccessToken(expectedExpiringRefreshToken.getValue(), - tokenRequest); + OAuth2AccessToken accessToken = getTokenServices().createAccessToken(createAuthentication()); + OAuth2RefreshToken expectedExpiringRefreshToken = accessToken.getRefreshToken(); + TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap("client_id", "id"), "id", null, null); + OAuth2AccessToken refreshedAccessToken = getTokenServices().refreshAccessToken( + expectedExpiringRefreshToken.getValue(), tokenRequest); assertNotNull(refreshedAccessToken); assertEquals(1, getRefreshTokenCount()); } private OAuth2Authentication createAuthentication() { - return new OAuth2Authentication( - RequestTokenFactory.createOAuth2Request(null, "id", null, - false, - new LinkedHashSet(Arrays.asList("read", "write")), - null, null, null, null), new TestAuthentication( - "test2", false)); + return new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, + new LinkedHashSet(Arrays.asList("read", "write")), null, null, null, null), + new TestAuthentication("test2", false)); } protected abstract int getAccessTokenCount(); @@ -283,10 +242,10 @@ protected DefaultTokenServices getTokenServices() { return services; } - protected static class TestAuthentication extends - AbstractAuthenticationToken { + protected static class TestAuthentication extends AbstractAuthenticationToken { private static final long serialVersionUID = 1L; + private String principal; public TestAuthentication(String name, boolean authenticated) { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenServicesTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenServicesTests.java index e37744c61..3bc7d82d5 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenServicesTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenServicesTests.java @@ -157,8 +157,11 @@ public void testUnlimitedTokenExpiry() throws Exception { @Test public void testDefaultTokenExpiry() throws Exception { services.setAccessTokenValiditySeconds(100); + services.setRefreshTokenValiditySeconds(1000); OAuth2AccessToken accessToken = services.createAccessToken(createAuthentication()); assertTrue(100 >= accessToken.getExpiresIn()); + assertTrue(1000 * 1000 >= ((ExpiringOAuth2RefreshToken) accessToken.getRefreshToken()).getExpiration() + .getTime() - System.currentTimeMillis()); } @Test @@ -233,8 +236,8 @@ public void testNotReuseRefreshTokenMaintainsState() throws Exception { } private OAuth2Authentication createAuthentication() { - return new OAuth2Authentication(createOAuth2Request("id",new LinkedHashSet(Arrays.asList("read", "write"))), - new TestAuthentication("test2", false)); + return new OAuth2Authentication(createOAuth2Request("id", + new LinkedHashSet(Arrays.asList("read", "write"))), new TestAuthentication("test2", false)); } private OAuth2Request createOAuth2Request(String clientId, Set scope) { From 16d633aa62b49126ccd7ecff01c9a49d03dc2b71 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 4 Apr 2014 17:59:21 +0100 Subject: [PATCH 210/831] Open up token and JSON converters in JwtTokenServices Customizing the JSON content of a JWT is a common requirement so we need to provide setters for all the relevant strategies. Fixes gh-176 --- .../token/DefaultAccessTokenConverter.java | 9 +++++++++ .../oauth2/provider/token/JwtTokenServices.java | 12 +++++++++++- .../provider/token/JwtTokenServicesTests.java | 16 ++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java index 2b8a4ef5d..5fa8add79 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java @@ -46,6 +46,15 @@ public class DefaultAccessTokenConverter implements AccessTokenConverter { private static final String SCOPE = OAuth2AccessToken.SCOPE; private UserAuthenticationConverter userTokenConverter = new DefaultUserAuthenticationConverter(); + + /** + * Converter for the part of the data in the token representing a user. + * + * @param userTokenConverter the userTokenConverter to set + */ + public void setUserTokenConverter(UserAuthenticationConverter userTokenConverter) { + this.userTokenConverter = userTokenConverter; + } public Map convertAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) { Map response = new HashMap(); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenServices.java index bbfc25aea..cf367f610 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenServices.java @@ -94,6 +94,16 @@ public void setTokenEnhancer(TokenEnhancer accessTokenEnhancer) { this.accessTokenEnhancer = accessTokenEnhancer; } + /** + * A converter of access tokens to and from a map representation. Can be used to add and subtract fields from the + * JWT. + * + * @param tokenConverter the tokenConverter to set + */ + public void setAccessTokenConverter(AccessTokenConverter tokenConverter) { + this.tokenConverter = tokenConverter; + } + /** * The validity (in seconds) of the refresh token. * @@ -170,7 +180,7 @@ public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication) result.setRefreshToken(createRefreshToken(authentication)); return result; } - + public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, TokenRequest request) throws AuthenticationException { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenServicesTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenServicesTests.java index 3bc7d82d5..a8de53c6e 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenServicesTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenServicesTests.java @@ -21,6 +21,7 @@ import java.util.Collections; import java.util.Date; import java.util.LinkedHashSet; +import java.util.Map; import java.util.Set; import org.junit.Before; @@ -35,6 +36,7 @@ import org.springframework.security.oauth2.common.OAuth2RefreshToken; import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; +import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; @@ -75,6 +77,20 @@ public void testLoadAuthentication() throws Exception { assertEquals(null, authentication.getUserAuthentication()); assertEquals("client", authentication.getOAuth2Request().getClientId()); } + @Test + public void testLoadAuthenticationWithTokenConverter() throws Exception { + services.setAccessTokenConverter(new DefaultAccessTokenConverter() { + @Override + public OAuth2Authentication extractAuthentication(Map map) { + AuthorizationRequest tokenRequest = new AuthorizationRequest("different",Collections.emptySet()); + return new OAuth2Authentication(tokenRequest.createOAuth2Request(), null); + } + }); + String token = JwtHelper.encode("{\"client_id\":\"client\"}", new MacSigner("FOO")).getEncoded(); + OAuth2Authentication authentication = services.loadAuthentication(token); + assertEquals(null, authentication.getUserAuthentication()); + assertEquals("different", authentication.getOAuth2Request().getClientId()); + } @Test public void testTokenEnhancerUpdatesTokens() throws Exception { From 633e5ec81629a2e9ea7cbf7500f2a727276d5d2a Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 7 Apr 2014 10:12:03 +0100 Subject: [PATCH 211/831] Updates docs with @Configuration features (Still some work to do on gh-168) --- .gitignore | 2 +- docs/oauth2.md | 151 ++++++++++-------- .../sparklr/config/OAuth2ServerConfig.java | 4 +- samples/oauth2/tonr/pom.xml | 6 +- .../oauth/examples/config/WebMvcConfig.java | 4 +- .../AuthorizationServerConfiguration.java | 10 +- .../AuthorizationServerConfigurer.java | 4 +- .../AuthorizationServerConfigurerAdapter.java | 4 +- ...uthorizationServerSecurityConfigurer.java} | 26 +-- ...AuthorizationServerConfigurationTests.java | 12 +- 10 files changed, 118 insertions(+), 105 deletions(-) rename spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/{OAuth2AuthorizationServerConfigurer.java => AuthorizationServerSecurityConfigurer.java} (92%) diff --git a/.gitignore b/.gitignore index 4a96b9ffa..d9d370573 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -#*# +*# .#* *~ _site/ diff --git a/docs/oauth2.md b/docs/oauth2.md index 20c8827c7..cc07044cc 100644 --- a/docs/oauth2.md +++ b/docs/oauth2.md @@ -30,9 +30,7 @@ The [`AuthorizationServerTokenServices`][AuthorizationServerTokenServices] inter * When an access token is created, the authentication must be stored so that the subsequent access token can reference it. * The access token is used to load the authentication that was used to authorize its creation. -When creating your `AuthorizationServerTokenServices` implementation, you may want to consider using the [`DefaultTokenServices`][DefaultTokenServices] which creates tokens via random value and handles everything except for the persistence of the tokens which it delegates to a `TokenStore`. - -There is an [in-memory implementation][InMemoryTokenStore] of the `TokenStore` that may be suitable. +When creating your `AuthorizationServerTokenServices` implementation, you may want to consider using the [`DefaultTokenServices`][DefaultTokenServices] which creates tokens via random value and handles everything except for the persistence of the tokens which it delegates to a `TokenStore`. The default store is an [in-memory implementation][InMemoryTokenStore], but there is also a [jdbc version](JdbcTokenStore) that may be suitable for your needs. ## OAuth 2.0 Provider Implementation @@ -41,25 +39,29 @@ The provider role in OAuth 2.0 is actually split between Authorization Service a * [`AuthorizationEndpoint`][AuthorizationEndpoint] is used to service requests for authorization. Default URL: `/oauth/authorize`. * [`TokenEndpoint`][TokenEndpoint] is used to service requests for access tokens. Default URL: `/oauth/token`. -The following filteris required to implement an OAuth 2.0 Resource Server: +The following filter is required to implement an OAuth 2.0 Resource Server: * The [`OAuth2AuthenticationProcessingFilter`][OAuth2AuthenticationProcessingFilter] is used to load the Authentication for the request given an authenticated access token. -For all the OAuth 2.0 provider features, configuration is simplified using the custom spring configuration elements. The schema for these elements rests at [http://www.springframework.org/schema/security/spring-security-oauth2.xsd][oauth2.xsd]. The namespace is `http://www.springframework.org/schema/security/oauth2`. +For all the OAuth 2.0 provider features, configuration is simplified using special Spring OAuth `@Configuration` adapters. There is also XML namespace for OAuth configuration and the schema resides at [http://www.springframework.org/schema/security/spring-security-oauth2.xsd][oauth2.xsd]. The namespace is `http://www.springframework.org/schema/security/oauth2`. ## Authorization Server Configuration As you configure the Authorization Server, you have to consider the grant type that the client is to use to obtain an access token from the end-user (e.g. authorization code, user credentials, refresh token). The configuration of the server is used to provide implementations of the client details service and token services and to enable or disable certain aspects of the mechanism globally. Note, however, that each client can be configured specifically with permissions to be able to use certain authorization mechanisms and access grants. I.e. just because your provider is configured to support the "client credentials" grant type, doesn't mean that a specific client is authorized to use that grant type. -The `` element is used to configure the OAuth 2.0 Authorization Server mechanism. The following attributes can be applied to the `authorization-server` element: +The `@EnableAuthorizationServer` annotation is used to configure the OAuth 2.0 Authorization Server mechanism, together with any `@Beans` that implement `AuthorizationServerConfigurer` (there is a hander adapter implementation with empty methods). The following features are delegated to separate configurers that are created by Spring and passed into the `AuthorizationServerConfigurer`: + +* `ClientDetailsServiceConfigurer`: a configurer that defines the client details service. Client details can be initialized, or you can just refer to an existing store. +* `AuthorizationServerSecurityConfigurer`: defines the authorization and token endpoints and the token services. -* `client-details-service-ref`: The reference to the bean that defines the client details service. -* `token-services-ref`: The reference to the bean that defines the token services. +An important aspect of the provider configuration is the way that an authorization code is supplied to an OAuth client (in the authorization code grant). A authorization code is obtained by the OAuth client by directing the end-user to an authorization page where the user can enter her credentials, resulting in a redirection from the provider authorization server back to the OAuth client with the authorization code. Examples of this are elaborated in the OAuth 2 specification. -An important aspect of the provider configuration is the way that a authorization code is supplied to an OAuth client. A authorization code is obtained by the OAuth client by directing the end-user to an authorization page where the user can enter her credentials, resulting in a redirection from the provider authorization server back to the OAuth client with the authorization code. Examples of this are elaborated in the OAuth 2 specification. +In XML there is an `` element that is used in a similar way to configure the OAuth 2.0 Authorization Server. ### Grant Types +// TODO: Java config for grant types... + The authorization code grant type is configured via the `authorization-code` child element of the `authorization-server` element. The `authorization-code` element supports the following attributes: * `disabled`: Boolean value specifying whether the authorization code mechanism is disabled. This effectively disables the authorization code grant mechanism. @@ -71,104 +73,114 @@ Other grant types are also included as child elements of the `authorization-serv ### Configuring Client Details -The `client-details-service` element is used to define an in-memory implementation of the client details service. It takes an `id` attribute and an arbitrary number of `client` child elements that define the following attributes for each client: +The `ClientDetailsServiceConfigurer` (a callback from your `AuthorizationServerConfigurer`) can be used used to define an in-memory or JDBC implementation of the client details service. Important attributes of a client are -* `client-id`: (required) The client id. -* `secret`: (required) The client secret, if any. -* `scope`: The scope to which the client is limited (comma-separated). If scope is undefined or empty (the default) the client is not limited by scope. -* `authorized-grant-types`: Flows that are authorized for the client to use (comma-separated). Default value is "web\_server". -* `authorities`: Authorities that are granted to the client (comma-separated). +* `clientId`: (required) the client id. +* `secret`: (required for trusted clients) the client secret, if any. +* `scope`: The scope to which the client is limited. If scope is undefined or empty (the default) the client is not limited by scope. +* `authorizedGrantTypes`: Grasnt types that are authorized for the client to use. Default value is empty. +* `authorities`: Authorities that are granted to the client (regular Spring Security authorities). ### Configuring the Endpoint URLs -The `` element has some attributes that can be used to change the default endpoint URLs: - -* `authorization-endpoint-url`: The URL at which a request for an authorization will be serviced (defaults to `/oauth/authorize`). This URL should be protected using Spring Security so that it is only accessible to authenticated users. -* `token-endpoint-url`: The URL at which a request for an access token will be serviced (defaults to `/oauth/token`). This URL should be accessible to anonymous users. - -If the endpoint URLs are changed in this way via the namespace, then an extra bean definition for a servlet Filter is created with id `oauth2EndpointUrlFilter`. This has to be mapped in your servlet container so that incoming requests with those paths are recognized by the Spring dispatcher servlet. The filter definition in `web.xml` would look like this: +The `AuthorizationServerSecurityConfigurer` has a `pathMapping()` method. It takes two arguments: - - oauth2EndpointUrlFilter - org.springframework.web.filter.DelegatingFilterProxy - - contextAttribute - org.springframework.web.servlet.FrameworkServlet.CONTEXT.spring - - +* The default (framework implementation) URL path for the endpoint +* The custom path required (starting with a "/") - - oauth2EndpointUrlFilter - /* - +The URL paths provided by the framework are `/oauth/authorize` (the authorization endpoint), `/oauth/token` (the token endpoint), `/oauth/confirm_access` (user posts approval for grants here) and `/oauth/error` (used to render errors in the authorization server). +N.B. the Authorization endpoint `/oauth/authorize` (or its mapped alternative) should be protected using Spring Security so that it is only accessible to authenticated users. The token endpoint is protected by default by Spring OAuth in the `@Configuration` support using HTTP Basic authentication of the client secret, but not in XML (so in that case it should be protected explicitly). -This filter has to be applied in the right order, so make sure the mapping appears in `web.xml` _before_ the mapping for the Spring Security filter. - -### Configuring An OAuth-Aware Expression Handler - -You may want to take advantage of Spring Security's [expression-based access control][expressions]. You can register a oauth-aware expression handler with the `expression-handler` element. Use the id of the oauth expression handler to add oauth-aware expressions to the built-in expressions. - -The expressions include _oauth2.clientHasRole_, _oauth2.clientHasAnyRole_, and _oath2.denyClient_ which can be used to provide access based on the role of the oauth client. +In XML the `` element has some attributes that can be used to change the default endpoint URLs in a similar way. ## Customizing the Error Handling -Error handling in an Authorization Server uses standard Spring MVC features, namely `@ExceptionHandler` methods in the endpoints themselves that delegate the rendering of exceptions to `HttpMesssageConverters` (which can be added to the MVC configuration). Users can also provide a `WebResponseExceptionTranslator` to the endpoints themselves which is the best way to change the content of the responses as opposed to the way they are rendered. +Error handling in an Authorization Server uses standard Spring MVC features, namely `@ExceptionHandler` methods in the endpoints themselves. Users can also provide a `WebResponseExceptionTranslator` to the endpoints themselves which is the best way to change the content of the responses as opposed to the way they are rendered. The rendering of exceptions delegates to `HttpMesssageConverters` (which can be added to the MVC configuration) in the case of token endpoint and to the OAuth error view (`/oauth/error`) in the case of teh authorization endpoint. A whitelabel error endpoint is provided, but users probably need to provide a custom implementation (e.g. just add a `@Controller` with `@RequestMapping("/oauth/error")`). ## Resource Server Configuration -You need to supply the `` element with an `id` attribute - this is the bean id for a servlet `Filter` that can be added to the standard Spring Security chain, e.g. +A Resource Server (can be the same as the Authorization Server or a separate application) serves resources that are protected by the OAuth2 token. Spring OAuth provides a Spring Security authentication filter that implements this protection. You can switch it on with `@EnableResourceServer` on an `@Configuration` class, and configure it (as necessary) using a `ResourceServerConfigurer`. The following features can be configured: - - - ... - - +* `tokenServices`: the bean that defines the token services (instance of `ResourceServerTokenServices`). +* `resourceId`: the id for the resource (optional, but recommended and will be validated by the auth server if present). - +The `@EnableResourceServer` annotation adds a filter of type `OAuth2AuthenticationProcessingFilter` to the Spring Security filter chain. +In XML there is a `` element with an `id` attribute - this is the bean id for a servlet `Filter` that can be added to the standard Spring Security chain. -The following attributes can be applied to the `resource-server` element: +### Configuring An OAuth-Aware Expression Handler -* `token-services-ref`: The reference to the bean that defines the token services. -* `resource-id`: The id for the resource (optional, but recommended and will be validated by the auth server if present) +You may want to take advantage of Spring Security's [expression-based access control][expressions]. An expression handler will be registered by default in the `@EnableResourceServer` setup. The expressions include _#oauth2.clientHasRole_, _#oauth2.clientHasAnyRole_, and _#oath2.denyClient_ which can be used to provide access based on the role of the oauth client (see `OAuth2SecurityExpressionMethods` for a comprehensive list). In XML you can register a oauth-aware expression handler with the `expression-handler` element of the regular `` security configuration. ## OAuth 2.0 Client -The OAuth 2.0 client mechanism is responsible for access the OAuth 2.0 protected resources of other servers. The configuration involves establishing the relevant protected resources to which users might have access. The client also needs to be supplied with mechanisms for storing authorization codes and access tokens for users. +The OAuth 2.0 client mechanism is responsible for access the OAuth 2.0 protected resources of other servers. The configuration involves establishing the relevant protected resources to which users might have access. The client may also need to be supplied with mechanisms for storing authorization codes and access tokens for users. ### Protected Resource Configuration -Protected resources can be defined using the `resource` configuration element. Each `resource` element is effectively a definition of a bean that is an instance of [`OAuth2ProtectedResourceDetails`][OAuth2ProtectedResourceDetails]. The `resource` element supports the following attributes: +Protected resources (or "remote resources") can be defined using bean definitions of type [`OAuth2ProtectedResourceDetails`][OAuth2ProtectedResourceDetails]. A protected resource has the following properties: * `id`: The id of the resource. The id is only used by the client to lookup the resource; it's never used in the OAuth protocol. It's also used as the id of the bean. -* `type`: The type (i.e. "grant type") of the resource. This is used to specify how an access token is to be obtained for this resource. Valid values include "authorization\_code", "password", and "assertion". Default value is "authorization\_code". -* `client-id`: The OAuth client id. This is the id by which the OAuth provider identifies your client. -* `client-secret`: The secret associated with the resource. By default, no secret is empty. -* `access-token-uri`: The URI of the provider OAuth endpoint that provides the access token. -* `user-authorization-uri`: The uri to which the user will be redirected if the user is ever needed to authorize access to the resource. Note that this is not always required, depending on which OAuth 2 profiles are supported. +* `clientId`: The OAuth client id. This is the id by which the OAuth provider identifies your client. +* `clientSecret`: The secret associated with the resource. By default, no secret is empty. +* `accessTokenUri`: The URI of the provider OAuth endpoint that provides the access token. * `scope`: Comma-separted list of strings specifying the scope of the access to the resource. By default, no scope will be specified. -* `client-authentication-scheme`: The scheme used by your client to authenticate to the access token endpoint. Suggested values: "http\_basic" and "form". Default: "http\_basic". See section 2.1 of the OAuth 2 spec. +* `clientAuthenticationScheme`: The scheme used by your client to authenticate to the access token endpoint. Suggested values: "http\_basic" and "form". Default: "http\_basic". See section 2.1 of the OAuth 2 spec. + +Different grant types have different concrete implementations of `OAuth2ProtectedResourceDetails` (e.g. `ClientCredentialsResource` for "client_credentials" grant type). For grant types that require user authorization there is a further property: + +* `userAuthorizationUri`: The uri to which the user will be redirected if the user is ever needed to authorize access to the resource. Note that this is not always required, depending on which OAuth 2 profiles are supported. + +In XML there is a `` element that can be used to create a bean of type `OAuth2ProtectedResourceDetails`. It has attributes matching all the properties above. + ### Client Configuration -For the OAuth 2.0 client, configuration is simplified using the custom spring configuration elements. The schema for these elements rests at [http://www.springframework.org/schema/security/spring-security-oauth2.xsd][oauth2.xsd]. The namespace is `http://www.springframework.org/schema/security/oauth2`. You need to supply the `` element with an `id` attribute - this is the bean id for a servlet `Filter` that must be added to the standard Spring Security chain, e.g. +For the OAuth 2.0 client, configuration is simplified using `@EnableOAuth2Client`. This does 2 things: + +* Creates a filter bean (with ID `oauth2ClientContextFilter`) to store the current +request and context. In the case of needing to authenticate during a +request it manages the redirection to and from the OAuth +authentication uri. + +* Creates a bean of type `AccessTokenRequest` in request scope. This +can be used by authorization code (or implicit) grant clients to keep +state related to individual users from colliding. + +The filter has to be wired into the application (e.g. using a Servlet +initializer or `web.xml` configuration for a `DelegatingFilterProxy` +with the same name). + +The `AccessTokenRequest` can be used in an +`OAuth2RestTemplate` like this: + +``` +@Resource +@Qualifier("accessTokenRequest") +private AccessTokenRequest accessTokenRequest; + +@Bean +@Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES) +public OAuth2RestTemplate sparklrRestTemplate() { + return new OAuth2RestTemplate(sparklr(), new DefaultOAuth2ClientContext(accessTokenRequest)); +} +``` - - - ... - - +The rest template is placed in session scope to keep the state for +different users separate. Without that you would have to manage the +equivalent data structure yourself on the server, mapping incoming +requests to users, and associating each user with a separate instance +of the `OAuth2ClientContext`. - +In XML there is a `` element with an `id` attribute - this is the bean id for a servlet `Filter` that must be mapped as in the `@Configuration` case to a `DelegatingFilterProxy` (with the same name). -This filter will be needed to store the current request and context, so in the case of needing to authenticate during a request it will manage the redirection to and from the OAuth authentication uri. ### Accessing Protected Resources -Once you've supplied all the configuration for the resources, you can now access those resources. The suggested method for accessing those resources is by using [the `RestTemplate` introduced in Spring 3][restTemplate]. OAuth for Spring Security has provided [an extension of RestTemplate][OAuth2RestTemplate] that only needs to be supplied an instance of [`OAuth2ProtectedResourceDetails`][OAuth2ProtectedResourceDetails]. To use it with user-tokens (authorization code grants) you should consider using the XML namespace shortcut `` which creates some request and session scoped context objects so that requests for different users do not collide at runtime. +Once you've supplied all the configuration for the resources, you can now access those resources. The suggested method for accessing those resources is by using [the `RestTemplate` introduced in Spring 3][restTemplate]. OAuth for Spring Security has provided [an extension of RestTemplate][OAuth2RestTemplate] that only needs to be supplied an instance of [`OAuth2ProtectedResourceDetails`][OAuth2ProtectedResourceDetails]. To use it with user-tokens (authorization code grants) you should consider using the `@EnableOAuth2Client` configuration (or the XML equivalent ``) which creates some request and session scoped context objects so that requests for different users do not collide at runtime. -### Persisting Tokens +### Persisting Tokens in a Client A client does not *need* to persist tokens, but it can be nice for users to not be required to approve a new token grant every time the client app is restarted. The [`ClientTokenServices`](/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/ClientTokenServices.java) interface defines the operations that are necessary to persist OAuth 2.0 tokens for specific users. There is a JDBC implementation provided, but you can if you prefer implement your own service for storing the access tokens and associated authentication instances in a persistent database. If you want to use this feature you need provide a specially configured [`AccessTokenProviderChain`][AccessTokenProviderChain] to your [`OAuth2RestTemplate`][OAuth2RestTemplate] e.g. @@ -193,6 +205,7 @@ Facebook token responses also contain a non-compliant JSON entry for the expiry [TokenEndpoint]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.html "TokenEndpoint" [DefaultTokenServices]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/token/DefaultTokenServices.html "DefaultTokenServices" [InMemoryTokenStore]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/token/InMemoryTokenStore.html "InMemoryTokenStore" + [JdbcTokenStore]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/token/JdbcTokenStore.html "JdbcTokenStore" [ClientDetailsService]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/ClientDetailsService.html "ClientDetailsService" [ClientDetails]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/ClientDetails.html "ClientDetails" [InMemoryClientDetailsService]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/InMemoryClientDetailsService.html "InMemoryClientDetailsService" diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java index 720b80c01..85586df54 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java @@ -31,7 +31,7 @@ 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.config.annotation.web.configuration.ResourceServerConfigurerAdapter; -import org.springframework.security.oauth2.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.OAuth2ResourceServerConfigurer; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; @@ -188,7 +188,7 @@ public ApprovalStore approvalStore() throws Exception { } @Override - public void configure(OAuth2AuthorizationServerConfigurer oauthServer) throws Exception { + public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { oauthServer.tokenStore(tokenStore).userApprovalHandler(userApprovalHandler()) .authenticationManager(authenticationManager).realm("sparklr2/client"); } diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index dc461a083..9975580cf 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -182,9 +182,9 @@ - org.codehaus.jackson - jackson-mapper-asl - 1.9.13 + com.fasterxml.jackson.core + jackson-databind + 2.3.2 diff --git a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/WebMvcConfig.java b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/WebMvcConfig.java index 07dbcf772..bb3fa08bd 100644 --- a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/WebMvcConfig.java +++ b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/WebMvcConfig.java @@ -18,7 +18,7 @@ import org.springframework.http.MediaType; import org.springframework.http.converter.BufferedImageHttpMessageConverter; import org.springframework.http.converter.HttpMessageConverter; -import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.security.oauth.examples.tonr.SparklrService; import org.springframework.security.oauth.examples.tonr.converter.AccessTokenRequestConverter; import org.springframework.security.oauth.examples.tonr.impl.SparklrServiceImpl; @@ -218,7 +218,7 @@ public OAuth2ProtectedResourceDetails trusted() { public OAuth2RestTemplate facebookRestTemplate() { OAuth2RestTemplate template = new OAuth2RestTemplate(facebook(), new DefaultOAuth2ClientContext( accessTokenRequest)); - MappingJacksonHttpMessageConverter converter = new MappingJacksonHttpMessageConverter(); + MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); converter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON, MediaType.valueOf("text/javascript"))); template.setMessageConverters(Arrays.> asList(converter)); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java index b52be2606..c364d52bd 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java @@ -37,7 +37,7 @@ import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.configuration.ClientDetailsServiceConfiguration; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; -import org.springframework.security.oauth2.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; import org.springframework.security.oauth2.provider.OAuth2RequestValidator; @@ -102,7 +102,7 @@ public void configure(ClientDetailsServiceConfigurer clientDetails) throws Excep @Override protected void configure(HttpSecurity http) throws Exception { - OAuth2AuthorizationServerConfigurer configurer = new OAuth2AuthorizationServerConfigurer(); + AuthorizationServerSecurityConfigurer configurer = new AuthorizationServerSecurityConfigurer(); configurer.clientDetailsService(clientDetailsService); configure(configurer); if (tokenStore != null) { @@ -121,7 +121,7 @@ protected void configure(HttpSecurity http) throws Exception { http.setSharedObject(ClientDetailsService.class, clientDetailsService); } - protected void configure(OAuth2AuthorizationServerConfigurer oauthServer) throws Exception { + protected void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { for (AuthorizationServerConfigurer configurer : configurers) { configurer.configure(oauthServer); } @@ -216,8 +216,8 @@ public TokenGranter tokenGranter() throws Exception { return authorizationServerConfigurer().getTokenGranter(); } - private OAuth2AuthorizationServerConfigurer authorizationServerConfigurer() throws Exception { - return getHttp().getConfigurer(OAuth2AuthorizationServerConfigurer.class); + private AuthorizationServerSecurityConfigurer authorizationServerConfigurer() throws Exception { + return getHttp().getConfigurer(AuthorizationServerSecurityConfigurer.class); } @Configuration diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurer.java index c085daf96..d96dd2153 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurer.java @@ -14,7 +14,7 @@ package org.springframework.security.oauth2.config.annotation.web.configuration; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; -import org.springframework.security.oauth2.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; /** * @author Dave Syer @@ -22,7 +22,7 @@ */ public interface AuthorizationServerConfigurer { - void configure(OAuth2AuthorizationServerConfigurer oauthServer) throws Exception; + void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception; void configure(ClientDetailsServiceConfigurer clients) throws Exception; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurerAdapter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurerAdapter.java index f08de3ecb..bafbd3c45 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurerAdapter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurerAdapter.java @@ -14,7 +14,7 @@ package org.springframework.security.oauth2.config.annotation.web.configuration; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; -import org.springframework.security.oauth2.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; /** * @author Dave Syer @@ -23,7 +23,7 @@ public class AuthorizationServerConfigurerAdapter implements AuthorizationServerConfigurer { @Override - public void configure(OAuth2AuthorizationServerConfigurer oauthServer) throws Exception { + public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { } @Override diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java similarity index 92% rename from spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java rename to spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java index dd2d39402..e06387ea1 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java @@ -72,7 +72,7 @@ * @author Rob Winch * @since 3.2 */ -public final class OAuth2AuthorizationServerConfigurer extends +public final class AuthorizationServerSecurityConfigurer extends SecurityConfigurerAdapter { private AuthenticationEntryPoint authenticationEntryPoint = new OAuth2AuthenticationEntryPoint(); @@ -143,63 +143,63 @@ public UserApprovalHandler getUserApprovalHandler() { return userApprovalHandler; } - public OAuth2AuthorizationServerConfigurer allowFormAuthenticationForClients() { + public AuthorizationServerSecurityConfigurer allowFormAuthenticationForClients() { this.allowFormAuthenticationForClients = true; return this; } - public OAuth2AuthorizationServerConfigurer tokenStore(TokenStore tokenStore) { + public AuthorizationServerSecurityConfigurer tokenStore(TokenStore tokenStore) { this.tokenStore = tokenStore; return this; } - public OAuth2AuthorizationServerConfigurer tokenService(AuthorizationServerTokenServices tokenServices) { + public AuthorizationServerSecurityConfigurer tokenService(AuthorizationServerTokenServices tokenServices) { this.tokenServices = tokenServices; return this; } - public OAuth2AuthorizationServerConfigurer userApprovalHandler(UserApprovalHandler approvalHandler) { + public AuthorizationServerSecurityConfigurer userApprovalHandler(UserApprovalHandler approvalHandler) { this.userApprovalHandler = approvalHandler; return this; } - public OAuth2AuthorizationServerConfigurer realm(String realm) { + public AuthorizationServerSecurityConfigurer realm(String realm) { this.realm = realm; return this; } - public OAuth2AuthorizationServerConfigurer pathMapping(String defaultPath, String customPath) { + public AuthorizationServerSecurityConfigurer pathMapping(String defaultPath, String customPath) { this.patternMap.put(defaultPath, customPath); return this; } - public OAuth2AuthorizationServerConfigurer authenticationEntryPoint( + public AuthorizationServerSecurityConfigurer authenticationEntryPoint( AuthenticationEntryPoint authenticationEntryPoint) { this.authenticationEntryPoint = authenticationEntryPoint; return this; } - public OAuth2AuthorizationServerConfigurer authenticationManager(AuthenticationManager authenticationManager) { + public AuthorizationServerSecurityConfigurer authenticationManager(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; return this; } - public OAuth2AuthorizationServerConfigurer clientDetailsService(ClientDetailsService clientDetailsService) { + public AuthorizationServerSecurityConfigurer clientDetailsService(ClientDetailsService clientDetailsService) { this.clientDetailsService = clientDetailsService; return this; } - public OAuth2AuthorizationServerConfigurer requestFactory(OAuth2RequestFactory requestFactory) { + public AuthorizationServerSecurityConfigurer requestFactory(OAuth2RequestFactory requestFactory) { this.requestFactory = requestFactory; return this; } - public OAuth2AuthorizationServerConfigurer requestValidator(OAuth2RequestValidator requestValidator) { + public AuthorizationServerSecurityConfigurer requestValidator(OAuth2RequestValidator requestValidator) { this.requestValidator = requestValidator; return this; } - public OAuth2AuthorizationServerConfigurer authorizationCodeServices(AuthorizationCodeServices authorizationCodeServices) { + public AuthorizationServerSecurityConfigurer authorizationCodeServices(AuthorizationCodeServices authorizationCodeServices) { this.authorizationCodeServices = authorizationCodeServices; return this; } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java index c936d6a60..207bb9915 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java @@ -39,7 +39,7 @@ import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfiguration; 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.configurers.OAuth2AuthorizationServerConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint; import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; @@ -122,7 +122,7 @@ protected static class AuthorizationServerExtras extends AuthorizationServerConf private ApplicationContext context; @Override - public void configure(OAuth2AuthorizationServerConfigurer oauthServer) throws Exception { + public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { oauthServer.tokenStore(tokenStore).realm("sparklr2/client"); } @@ -156,7 +156,7 @@ protected static class AuthorizationServerJdbc extends AuthorizationServerConfig private ApplicationContext context; @Override - public void configure(OAuth2AuthorizationServerConfigurer oauthServer) throws Exception { + public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { oauthServer.tokenStore(new JdbcTokenStore(dataSource())).realm("sparklr2/client"); } @@ -190,7 +190,7 @@ protected static class AuthorizationServerJwt extends AuthorizationServerConfigu private JwtTokenServices tokenServices = new JwtTokenServices(); @Override - public void configure(OAuth2AuthorizationServerConfigurer oauthServer) throws Exception { + public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { oauthServer.tokenService(tokenServices).realm("sparklr2/client"); } @@ -219,7 +219,7 @@ protected static class AuthorizationServerApproval extends AuthorizationServerCo private ApplicationContext context; @Override - public void configure(OAuth2AuthorizationServerConfigurer oauthServer) throws Exception { + public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { oauthServer.tokenStore(tokenStore); } @@ -248,7 +248,7 @@ protected static class AuthorizationServerTypes extends AuthorizationServerConfi // TODO: actually configure a token granter @Override - protected void configure(OAuth2AuthorizationServerConfigurer oauthServer) throws Exception { + protected void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { } } From 55a40b934bcb437938fde338ca0d9c426b39b963 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 8 Apr 2014 11:13:43 +0100 Subject: [PATCH 212/831] Add some javadocs clarifying throwOnError --- .../OAuth2SecurityExpressionMethods.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethods.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethods.java index 5b2cb90d7..f70aad150 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethods.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethods.java @@ -11,7 +11,6 @@ * specific language governing permissions and limitations under the License. */ - package org.springframework.security.oauth2.provider.expression; import java.util.Arrays; @@ -59,6 +58,10 @@ public OAuth2SecurityExpressionMethods(Authentication authentication) { * access = "#oauth2.throwOnError(#oauth2.hasScope('read') or (#oauth2.hasScope('other') and hasRole('ROLE_USER'))" * * + * N.B. normally this method will be automatically wrapped around all your access expressions. You could use it + * explicitly to get more control, or if you have registered your own ExpressionParser you might need + * it. + * * @param decision the existing access decision * @return true if the OAuth2 token has one of these scopes * @throws InsufficientScopeException if the scope is invalid and we the flag is set to throw the exception @@ -125,8 +128,7 @@ public boolean hasAnyScope(String... scopes) { * access = "#oauth2.hasScopeMatching('.*_admin:manage_scopes')))" * * - * @param scopeRegex - * the scope regex to match + * @param scopeRegex the scope regex to match * @return true if the OAuth2 authentication has the required scope */ public boolean hasScopeMatching(String scopeRegex) { @@ -140,11 +142,9 @@ public boolean hasScopeMatching(String scopeRegex) { * access = "#oauth2.hasAnyScopeMatching('admin:manage_scopes','.*_admin:manage_scopes','.*_admin:read_scopes')))" * * - * @param roles - * the scopes regex to match + * @param roles the scopes regex to match * @return true if the OAuth2 token has one of these scopes - * @throws AccessDeniedException - * if the scope is invalid and we the flag is set to throw the exception + * @throws AccessDeniedException if the scope is invalid and we the flag is set to throw the exception */ public boolean hasAnyScopeMatching(String... scopesRegex) { From a83aa0f58cf169a07aaa55d2ffaeb3402b56df97 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 8 Apr 2014 11:14:02 +0100 Subject: [PATCH 213/831] Add support for TokenGranter in AuthorizationServerSecurityConfigurer --- .../configurers/AuthorizationServerSecurityConfigurer.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java index e06387ea1..9297d45e0 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java @@ -184,6 +184,11 @@ public AuthorizationServerSecurityConfigurer authenticationManager(Authenticatio return this; } + public AuthorizationServerSecurityConfigurer tokenGranter(TokenGranter tokenGranter) { + this.tokenGranter = tokenGranter; + return this; + } + public AuthorizationServerSecurityConfigurer clientDetailsService(ClientDetailsService clientDetailsService) { this.clientDetailsService = clientDetailsService; return this; From 0830da23e7acc892fe50447be5b7c170cf1d1dca Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 8 Apr 2014 14:13:25 +0100 Subject: [PATCH 214/831] Add docs for configuration of grant types See gh-168 --- docs/oauth2.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/docs/oauth2.md b/docs/oauth2.md index cc07044cc..13d211e41 100644 --- a/docs/oauth2.md +++ b/docs/oauth2.md @@ -60,16 +60,13 @@ In XML there is an `` element that is used in a similar w ### Grant Types -// TODO: Java config for grant types... +The grant types supported by the `AuthorizationEndpoint` can be configured via the `AuthorizationServerSecurityConfigurer`. The following properties affect grant types: -The authorization code grant type is configured via the `authorization-code` child element of the `authorization-server` element. The `authorization-code` element supports the following attributes: +* `authenticationManager`: by default all grant types are supported except password grants, which are switched on by injecting an `AuthenticationManager`. +* `authorizationCodeServices`: defines the authorization code services (instance of `org.springframework.security.oauth2.provider.code.AuthorizationCodeServices`) for the auth code grant +* `tokenGranter`: the `TokenGranter` (taking full control of the granting and ignoring the other properties above) -* `disabled`: Boolean value specifying whether the authorization code mechanism is disabled. This effectively disables the authorization code grant mechanism. -* `services-ref`: The reference to the bean that defines the authorization code services (instance of `org.springframework.security.oauth2.provider.code.AuthorizationCodeServices`) -* `user-approval-page`: The URL of the page that handles the user approval form. -* `approval-parameter-name`: The name of the form parameter that is used to indicate user approval of the client authentication request. - -Other grant types are also included as child elements of the `authorization-server`. +In XML grant types are included as child elements of the `authorization-server`. ### Configuring Client Details @@ -183,15 +180,18 @@ Once you've supplied all the configuration for the resources, you can now access ### Persisting Tokens in a Client A client does not *need* to persist tokens, but it can be nice for users to not be required to approve a new token grant every time the client app is restarted. The [`ClientTokenServices`](/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/ClientTokenServices.java) interface defines the operations that are necessary to persist OAuth 2.0 tokens for specific users. There is a JDBC implementation provided, but you can if you prefer implement your own service for storing the access tokens and associated authentication instances in a persistent database. -If you want to use this feature you need provide a specially configured [`AccessTokenProviderChain`][AccessTokenProviderChain] to your [`OAuth2RestTemplate`][OAuth2RestTemplate] e.g. - - +If you want to use this feature you need provide a specially configured `TokenProvider` to the `OAuth2RestTemplate` e.g. - - - - - +```java +@Bean +@Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES) +public OAuth2RestOperations restTemplate() { + OAuth2RestTemplate template = new OAuth2RestTemplate(resource(), new DefaultOAuth2ClientContext(accessTokenRequest)); + AccessTokenProviderChain provider = new AccessTokenProviderChain(Arrays.asList(new AuthorizationCodeAccessTokenProvider())); + provider.setClientTokenServices(clientTokenServices()); + return template; +} +``` ## Customizations for Clients of External OAuth2 Providers From 8e9a45905bd6d4bba82b4862b4c7b40056f304e6 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 8 Apr 2014 12:29:35 +0100 Subject: [PATCH 215/831] Ensure AuthorizationEndpoint has an ApprovalStore by default --- .../AuthorizationServerConfiguration.java | 8 +++++++ ...AuthorizationServerSecurityConfigurer.java | 7 +++++- ...AuthorizationServerConfigurationTests.java | 22 +++++++++++++++++-- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java index c364d52bd..745c3ce2b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java @@ -137,6 +137,7 @@ public AuthorizationEndpoint authorizationEndpoint() throws Exception { authorizationEndpoint.setOAuth2RequestValidator(oauth2RequestValidator()); authorizationEndpoint.setUserApprovalHandler(userApprovalHandler()); authorizationEndpoint.setImplicitGrantService(implicitGrantService()); + authorizationEndpoint.setApprovalStore(approvalStore()); return authorizationEndpoint; } @@ -185,6 +186,13 @@ public UserApprovalHandler userApprovalHandler() throws Exception { return authorizationServerConfigurer().getUserApprovalHandler(); } + @Bean + @Lazy + @Scope(proxyMode = ScopedProxyMode.INTERFACES) + public ApprovalStore approvalStore() throws Exception { + return authorizationServerConfigurer().getApprovalStore(); + } + @Bean public WhitelabelApprovalEndpoint whitelabelApprovalEndpoint() { return new WhitelabelApprovalEndpoint(); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java index 9297d45e0..98be63bb5 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java @@ -163,6 +163,11 @@ public AuthorizationServerSecurityConfigurer userApprovalHandler(UserApprovalHan return this; } + public AuthorizationServerSecurityConfigurer approvalStore(ApprovalStore approvalStore) { + this.approvalStore = approvalStore; + return this; + } + public AuthorizationServerSecurityConfigurer realm(String realm) { this.realm = realm; return this; @@ -304,7 +309,7 @@ private TokenStore tokenStore() { } private ApprovalStore approvalStore() { - if (tokenStore() != null) { + if (approvalStore==null && tokenStore() != null) { TokenApprovalStore tokenApprovalStore = new TokenApprovalStore(); tokenApprovalStore.setTokenStore(tokenStore()); this.approvalStore = tokenApprovalStore; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java index 207bb9915..861967078 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java @@ -41,7 +41,11 @@ import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; +import org.springframework.security.oauth2.provider.approval.TokenApprovalStore; +import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenGranter; import org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint; +import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; import org.springframework.security.oauth2.provider.token.JdbcTokenStore; import org.springframework.security.oauth2.provider.token.JwtTokenServices; @@ -108,7 +112,14 @@ public void testDefaults() { @Configuration @EnableWebMvcSecurity @EnableAuthorizationServer - protected static class AuthorizationServerUnconfigured { + protected static class AuthorizationServerUnconfigured implements Runnable { + @Autowired + private AuthorizationEndpoint endpoint; + @Override + public void run() { + // There should be an approval store by default (a TokenApprovalStore) + assertTrue(ReflectionTestUtils.getField(endpoint, "approvalStore") instanceof TokenApprovalStore); + } } @Configuration @@ -246,9 +257,16 @@ public void run() { @EnableWebMvcSecurity protected static class AuthorizationServerTypes extends AuthorizationServerConfiguration { - // TODO: actually configure a token granter + @Autowired + private AuthorizationServerTokenServices tokenServices; + @Autowired + private ClientDetailsService clientDetailsService; + @Autowired + private OAuth2RequestFactory requestFactory; + @Override protected void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { + oauthServer.tokenGranter(new ClientCredentialsTokenGranter(tokenServices, clientDetailsService, requestFactory)); } } From dbfbbe1933e11b6c88a66e9e1122ac65a5a743cf Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 8 Apr 2014 16:09:41 +0100 Subject: [PATCH 216/831] Re-order auth server docs --- docs/oauth2.md | 50 +++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/docs/oauth2.md b/docs/oauth2.md index 13d211e41..779e28938 100644 --- a/docs/oauth2.md +++ b/docs/oauth2.md @@ -17,21 +17,6 @@ This user guide is divided into two parts, the first for the OAuth 2.0 provider, The OAuth 2.0 provider mechanism is responsible for exposing OAuth 2.0 protected resources. The configuration involves establishing the OAuth 2.0 clients that can access its protected resources on behalf of a user. The provider does this by managing and verifying the OAuth 2.0 tokens that can be used to access the protected resources. Where applicable, the provider must also supply an interface for the user to confirm that a client can be granted access to the protected resources (i.e. a confirmation page). -### Managing Clients - -The entry point into your database of clients is defined by the [`ClientDetailsService`][ClientDetailsService]. You must define your own `ClientDetailsService` that will load [`ClientDetails`][ClientDetails] by the . Note the existence of an [in-memory implementation][InMemoryClientDetailsService] of `ClientDetailsService`. - -When implementing your `ClientDetailsService` consider returning instances of (or extending) [`BaseClientDetails`][BaseClientDetails]. - -### Managing Tokens - -The [`AuthorizationServerTokenServices`][AuthorizationServerTokenServices] interface defines the operations that are necessary to manage OAuth 2.0 tokens. Note the following: - -* When an access token is created, the authentication must be stored so that the subsequent access token can reference it. -* The access token is used to load the authentication that was used to authorize its creation. - -When creating your `AuthorizationServerTokenServices` implementation, you may want to consider using the [`DefaultTokenServices`][DefaultTokenServices] which creates tokens via random value and handles everything except for the persistence of the tokens which it delegates to a `TokenStore`. The default store is an [in-memory implementation][InMemoryTokenStore], but there is also a [jdbc version](JdbcTokenStore) that may be suitable for your needs. - ## OAuth 2.0 Provider Implementation The provider role in OAuth 2.0 is actually split between Authorization Service and Resource Service, and while these sometimes reside in the same application, with Spring Security OAuth you have the option to split them across two applications, and also to have multiple Resource Services that share an Authorization Service. The requests for the tokens are handled by Spring MVC controller endpoints, and access to protected resources is handled by standard Spring Security request filters. The following endpoints are required in the Spring Security filter chain in order to implement OAuth 2.0 Authorization Server: @@ -58,16 +43,6 @@ An important aspect of the provider configuration is the way that an authorizati In XML there is an `` element that is used in a similar way to configure the OAuth 2.0 Authorization Server. -### Grant Types - -The grant types supported by the `AuthorizationEndpoint` can be configured via the `AuthorizationServerSecurityConfigurer`. The following properties affect grant types: - -* `authenticationManager`: by default all grant types are supported except password grants, which are switched on by injecting an `AuthenticationManager`. -* `authorizationCodeServices`: defines the authorization code services (instance of `org.springframework.security.oauth2.provider.code.AuthorizationCodeServices`) for the auth code grant -* `tokenGranter`: the `TokenGranter` (taking full control of the granting and ignoring the other properties above) - -In XML grant types are included as child elements of the `authorization-server`. - ### Configuring Client Details The `ClientDetailsServiceConfigurer` (a callback from your `AuthorizationServerConfigurer`) can be used used to define an in-memory or JDBC implementation of the client details service. Important attributes of a client are @@ -78,6 +53,31 @@ The `ClientDetailsServiceConfigurer` (a callback from your `AuthorizationServerC * `authorizedGrantTypes`: Grasnt types that are authorized for the client to use. Default value is empty. * `authorities`: Authorities that are granted to the client (regular Spring Security authorities). +Client details can be updated in a running application by access the underlying store directly (e.g. database tables in the case of `JdbcClientDetailsService`) or through the `ClientDetailsManager` interface (which both implementations or `ClientDetailsService` also implement). + +### Managing Tokens + +The [`AuthorizationServerTokenServices`][AuthorizationServerTokenServices] interface defines the operations that are necessary to manage OAuth 2.0 tokens. Note the following: + +* When an access token is created, the authentication must be stored so that the subsequent access token can reference it. +* The access token is used to load the authentication that was used to authorize its creation. + +When creating your `AuthorizationServerTokenServices` implementation, you may want to consider using the [`DefaultTokenServices`][DefaultTokenServices] which creates tokens via random value and handles everything except for the persistence of the tokens which it delegates to a `TokenStore`. The default store is an [in-memory implementation][InMemoryTokenStore], but there is also a [jdbc version](JdbcTokenStore) that may be suitable for your needs. + +### Grant Types + +The grant types supported by the `AuthorizationEndpoint` can be +configured via the `AuthorizationServerSecurityConfigurer`. By default +all grant types are supported except password (see below for details of how to switch it on). The +following properties affect grant types: + +* `authenticationManager`: password grants are switched on by injecting an `AuthenticationManager`. +* `authorizationCodeServices`: defines the authorization code services (instance of `org.springframework.security.oauth2.provider.code.AuthorizationCodeServices`) for the auth code grant +* `implicitGrantService`: manages state during the imlpicit grant. +* `tokenGranter`: the `TokenGranter` (taking full control of the granting and ignoring the other properties above) + +In XML grant types are included as child elements of the `authorization-server`. + ### Configuring the Endpoint URLs The `AuthorizationServerSecurityConfigurer` has a `pathMapping()` method. It takes two arguments: From 2cd02fff04384dd311770a62e49ce4a20973cfff Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 8 Apr 2014 17:31:22 +0100 Subject: [PATCH 217/831] Extract ApprovalStore from AuthorizationEndpoint into UserApprovalHandler The presence of the ApprovalStore in AuthorizationEndpoint was awkward and it was only ever going to be needed if the UserApprovalHandler used it as well. The best solution seems to be to add another method to UserApprovalHandler to generate the model for asking for user approval (it's definitely in the same area of responsibility). --- .../sparklr/config/OAuth2ServerConfig.java | 6 ++ .../AuthorizationServerConfiguration.java | 39 ++------ ...AuthorizationServerSecurityConfigurer.java | 12 ++- .../ApprovalStoreUserApprovalHandler.java | 25 +++++- .../approval/DefaultUserApprovalHandler.java | 11 +++ .../TokenStoreUserApprovalHandler.java | 14 +++ .../approval/UserApprovalHandler.java | 26 ++++-- .../endpoint/AuthorizationEndpoint.java | 43 ++------- .../oauth2/provider/token/TokenStore.java | 18 ++-- ...AuthorizationServerConfigurationTests.java | 90 +++++++++++++++++-- .../endpoint/AuthorizationEndpointTests.java | 18 ++-- 11 files changed, 200 insertions(+), 102 deletions(-) diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java index 85586df54..763f54008 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java @@ -48,6 +48,12 @@ public class OAuth2ServerConfig { private static final String SPARKLR_RESOURCE_ID = "sparklr"; + + // TODO: add this automatically as a default? + @Bean + public TokenStore tokenStore() { + return new InMemoryTokenStore(); + } @Configuration @Order(10) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java index 745c3ce2b..1e2b1b0ad 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java @@ -21,17 +21,13 @@ import javax.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; -import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.ScopedProxyMode; import org.springframework.core.annotation.Order; -import org.springframework.core.type.AnnotationMetadata; import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @@ -87,6 +83,9 @@ public class AuthorizationServerConfiguration extends WebSecurityConfigurerAdapt @Autowired(required = false) private TokenStore tokenStore; + @Autowired(required = false) + private ApprovalStore approvalStore; + @Configuration protected static class ClientDetailsAuthenticationManagerConfiguration extends GlobalAuthenticationConfigurerAdapter { @@ -108,6 +107,9 @@ protected void configure(HttpSecurity http) throws Exception { if (tokenStore != null) { configurer.tokenStore(tokenStore); } + if (approvalStore != null) { + configurer.approvalStore(approvalStore); + } http.apply(configurer); String tokenEndpointPath = oauth2EndpointHandlerMapping().getPath("/oauth/token"); // @formatter:off @@ -137,7 +139,6 @@ public AuthorizationEndpoint authorizationEndpoint() throws Exception { authorizationEndpoint.setOAuth2RequestValidator(oauth2RequestValidator()); authorizationEndpoint.setUserApprovalHandler(userApprovalHandler()); authorizationEndpoint.setImplicitGrantService(implicitGrantService()); - authorizationEndpoint.setApprovalStore(approvalStore()); return authorizationEndpoint; } @@ -181,18 +182,11 @@ public OAuth2RequestValidator oauth2RequestValidator() throws Exception { @Bean @Lazy - @Scope(proxyMode = ScopedProxyMode.INTERFACES) + @Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) public UserApprovalHandler userApprovalHandler() throws Exception { return authorizationServerConfigurer().getUserApprovalHandler(); } - @Bean - @Lazy - @Scope(proxyMode = ScopedProxyMode.INTERFACES) - public ApprovalStore approvalStore() throws Exception { - return authorizationServerConfigurer().getApprovalStore(); - } - @Bean public WhitelabelApprovalEndpoint whitelabelApprovalEndpoint() { return new WhitelabelApprovalEndpoint(); @@ -229,23 +223,16 @@ private AuthorizationServerSecurityConfigurer authorizationServerConfigurer() th } @Configuration - @Import(TokenStoreRegistrar.class) protected static class EndpointsConfiguration { @Autowired private AuthorizationEndpoint authorizationEndpoint; - @Autowired(required = false) - private ApprovalStore approvalStore; - @Autowired private FrameworkEndpointHandlerMapping mapping; @PostConstruct public void init() { - if (approvalStore != null) { - authorizationEndpoint.setApprovalStore(approvalStore); - } authorizationEndpoint.setUserApprovalPage(extractPath(mapping, "/oauth/confirm_access")); authorizationEndpoint.setErrorPage(extractPath(mapping, "/oauth/error")); } @@ -260,16 +247,4 @@ private String extractPath(FrameworkEndpointHandlerMapping mapping, String page) } - protected static class TokenStoreRegistrar implements ImportBeanDefinitionRegistrar { - - @Override - public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { - if (!registry.containsBeanDefinition(TOKEN_STORE_BEAN_NAME) - && !registry.containsBeanDefinition(APPROVAL_STORE_BEAN_NAME)) { - registry.registerBeanDefinition(TOKEN_STORE_BEAN_NAME, new RootBeanDefinition(InMemoryTokenStore.class)); - } - } - - } - } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java index 98be63bb5..5826229e5 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java @@ -111,6 +111,8 @@ public final class AuthorizationServerSecurityConfigurer extends private boolean allowFormAuthenticationForClients = false; + private boolean approvalStoreDisabled; + private ClientDetailsService clientDetails() { return getBuilder().getSharedObject(ClientDetailsService.class); } @@ -164,10 +166,18 @@ public AuthorizationServerSecurityConfigurer userApprovalHandler(UserApprovalHan } public AuthorizationServerSecurityConfigurer approvalStore(ApprovalStore approvalStore) { + if (approvalStoreDisabled) { + throw new IllegalStateException("ApprovalStore was disabled"); + } this.approvalStore = approvalStore; return this; } + public AuthorizationServerSecurityConfigurer approvalStoreDisabled() { + this.approvalStoreDisabled = true; + return this; + } + public AuthorizationServerSecurityConfigurer realm(String realm) { this.realm = realm; return this; @@ -309,7 +319,7 @@ private TokenStore tokenStore() { } private ApprovalStore approvalStore() { - if (approvalStore==null && tokenStore() != null) { + if (approvalStore==null && tokenStore() != null && !approvalStoreDisabled) { TokenApprovalStore tokenApprovalStore = new TokenApprovalStore(); tokenApprovalStore.setTokenStore(tokenStore()); this.approvalStore = tokenApprovalStore; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java index d8d033c2d..63b423370 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java @@ -19,7 +19,9 @@ import java.util.Calendar; import java.util.Collection; import java.util.Date; +import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; @@ -132,8 +134,7 @@ public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizati } // Find the stored approvals for that user and client - Collection userApprovals = approvalStore.getApprovals(userAuthentication.getName(), - clientId); + Collection userApprovals = approvalStore.getApprovals(userAuthentication.getName(), clientId); // Look at the scopes and see if they have expired Date today = new Date(); @@ -223,4 +224,24 @@ public AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizati authorizationRequest.setApproved(approved); return authorizationRequest; } + + @Override + public Map getUserApprovalRequest(AuthorizationRequest authorizationRequest, + Authentication userAuthentication) { + Map model = new HashMap(); + model.putAll(authorizationRequest.getRequestParameters()); + Map scopes = new LinkedHashMap(); + for (String scope : authorizationRequest.getScope()) { + scopes.put(OAuth2Utils.SCOPE_PREFIX + scope, "false"); + } + for (Approval approval : approvalStore.getApprovals(userAuthentication.getName(), + authorizationRequest.getClientId())) { + if (authorizationRequest.getScope().contains(approval.getScope())) { + scopes.put(OAuth2Utils.SCOPE_PREFIX + approval.getScope(), + approval.getStatus() == ApprovalStatus.APPROVED ? "true" : "false"); + } + } + model.put("scopes", scopes); + return model; + } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/DefaultUserApprovalHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/DefaultUserApprovalHandler.java index f32ae91ed..4233b6796 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/DefaultUserApprovalHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/DefaultUserApprovalHandler.java @@ -16,6 +16,7 @@ package org.springframework.security.oauth2.provider.approval; +import java.util.HashMap; import java.util.Map; import org.springframework.security.core.Authentication; @@ -59,6 +60,7 @@ public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizati return authorizationRequest; } + @Override public AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { Map approvalParameters = authorizationRequest.getApprovalParameters(); String flag = approvalParameters.get(approvalParameter); @@ -66,5 +68,14 @@ public AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizati authorizationRequest.setApproved(approved); return authorizationRequest; } + + @Override + public Map getUserApprovalRequest(AuthorizationRequest authorizationRequest, + Authentication userAuthentication) { + Map model = new HashMap(); + // In case of a redirect we might want the request parameters to be included + model.putAll(authorizationRequest.getRequestParameters()); + return model; + } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandler.java index e91c020af..98589482e 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandler.java @@ -16,6 +16,7 @@ package org.springframework.security.oauth2.provider.approval; +import java.util.HashMap; import java.util.Map; import java.util.Set; @@ -80,6 +81,7 @@ public void setRequestFactory(OAuth2RequestFactory requestFactory) { this.requestFactory = requestFactory; } + @Override public void afterPropertiesSet() { Assert.state(tokenStore != null, "TokenStore must be provided"); Assert.state(requestFactory != null, "OAuth2RequestFactory must be provided"); @@ -94,10 +96,12 @@ public void afterPropertiesSet() { * * @return Whether the specified request has been approved by the current user. */ + @Override public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { return authorizationRequest.isApproved(); } + @Override public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { boolean approved = false; @@ -151,6 +155,7 @@ public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizati return authorizationRequest; } + @Override public AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { Map approvalParameters = authorizationRequest.getApprovalParameters(); String flag = approvalParameters.get(approvalParameter); @@ -158,4 +163,13 @@ public AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizati authorizationRequest.setApproved(approved); return authorizationRequest; } + + @Override + public Map getUserApprovalRequest(AuthorizationRequest authorizationRequest, + Authentication userAuthentication) { + Map model = new HashMap(); + // In case of a redirect we might want the request parameters to be included + model.putAll(authorizationRequest.getRequestParameters()); + return model; + } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/UserApprovalHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/UserApprovalHandler.java index 20547aacb..7a1131bfd 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/UserApprovalHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/UserApprovalHandler.java @@ -1,5 +1,7 @@ package org.springframework.security.oauth2.provider.approval; +import java.util.Map; + import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.provider.AuthorizationRequest; @@ -12,7 +14,6 @@ */ public interface UserApprovalHandler { - /** *

    * Tests whether the specified authorization request has been approved by the current user (if there is one). @@ -28,15 +29,16 @@ public interface UserApprovalHandler { *

    * Provides a hook for allowing requests to be pre-approved (skipping the User Approval Page). Some implementations * may allow users to store approval decisions so that they only have to approve a site once. This method is called - * in the AuthorizationEndpoint before sending the user to the Approval page. If this method sets oAuth2Request.approved - * to true, the Approval page will be skipped. + * in the AuthorizationEndpoint before sending the user to the Approval page. If this method sets + * oAuth2Request.approved to true, the Approval page will be skipped. *

    * * @param authorizationRequest the authorization request. * @param userAuthentication the user authentication * @return the AuthorizationRequest, modified if necessary */ - AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication); + AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest, + Authentication userAuthentication); /** *

    @@ -50,5 +52,19 @@ public interface UserApprovalHandler { * @param userAuthentication the user authentication * @return the AuthorizationRequest, modified if necessary */ - AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication); + AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizationRequest, + Authentication userAuthentication); + + /** + * Generate a request for the authorization server to ask for the user's approval. Typically this will be rendered + * into a view (HTML etc.) to prompt for the approval, so it needs to contain information about the grant (scopes + * and client id for instance). + * + * @param authorizationRequest the authorization request + * @param userAuthentication the user authentication + * @return a model map for rendering to the user to ask for approval + */ + Map getUserApprovalRequest(AuthorizationRequest authorizationRequest, + Authentication userAuthentication); + } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java index 4baedc3e2..57b72dcca 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java @@ -44,11 +44,8 @@ import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.OAuth2RequestValidator; import org.springframework.security.oauth2.provider.TokenRequest; -import org.springframework.security.oauth2.provider.approval.Approval; -import org.springframework.security.oauth2.provider.approval.ApprovalStore; import org.springframework.security.oauth2.provider.approval.DefaultUserApprovalHandler; import org.springframework.security.oauth2.provider.approval.UserApprovalHandler; -import org.springframework.security.oauth2.provider.approval.Approval.ApprovalStatus; import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices; import org.springframework.security.oauth2.provider.implicit.ImplicitGrantService; @@ -108,18 +105,6 @@ public class AuthorizationEndpoint extends AbstractEndpoint { private String errorPage = "forward:/oauth/error"; - private ApprovalStore approvalStore; - - /** - * Optional approval store (if one is available) will result in approval information being added to the model for - * the confirmation page, and therefore potentially the user being able to approve individual scopes. - * - * @param approvalStore the approvalStore to set - */ - public void setApprovalStore(ApprovalStore approvalStore) { - this.approvalStore = approvalStore; - } - public void setSessionAttributeStore(SessionAttributeStore sessionAttributeStore) { this.sessionAttributeStore = sessionAttributeStore; } @@ -129,8 +114,8 @@ public void setErrorPage(String errorPage) { } @RequestMapping(value = "/oauth/authorize") - public ModelAndView authorize(Map model, @RequestParam - Map parameters, SessionStatus sessionStatus, Principal principal) { + public ModelAndView authorize(Map model, @RequestParam Map parameters, + SessionStatus sessionStatus, Principal principal) { // Pull out the authorization request first, using the OAuth2RequestFactory. All further logic should // query off of the authorization request instead of referring back to the parameters map. The contents of the @@ -194,7 +179,7 @@ public ModelAndView authorize(Map model, @RequestParam // so any auth request parameters passed to approveOrDeny will be ignored and retrieved from the session. model.put("authorizationRequest", authorizationRequest); - return getUserApprovalPageResponse(model, authorizationRequest, principal, client); + return getUserApprovalPageResponse(model, authorizationRequest, (Authentication) principal); } catch (RuntimeException e) { @@ -205,8 +190,8 @@ public ModelAndView authorize(Map model, @RequestParam } @RequestMapping(value = "/oauth/authorize", method = RequestMethod.POST, params = OAuth2Utils.USER_OAUTH_APPROVAL) - public View approveOrDeny(@RequestParam - Map approvalParameters, Map model, SessionStatus sessionStatus, Principal principal) { + public View approveOrDeny(@RequestParam Map approvalParameters, Map model, + SessionStatus sessionStatus, Principal principal) { if (!(principal instanceof Authentication)) { sessionStatus.setComplete(); @@ -255,23 +240,9 @@ public View approveOrDeny(@RequestParam // We need explicit approval from the user. private ModelAndView getUserApprovalPageResponse(Map model, - AuthorizationRequest authorizationRequest, Principal principal, ClientDetails client) { + AuthorizationRequest authorizationRequest, Authentication principal) { logger.debug("Loading user approval page: " + userApprovalPage); - // In case of a redirect we might want the request parameters to be included - model.putAll(authorizationRequest.getRequestParameters()); - if (approvalStore != null) { - Map scopes = new LinkedHashMap(); - for (String scope : authorizationRequest.getScope()) { - scopes.put(OAuth2Utils.SCOPE_PREFIX + scope, "false"); - } - for (Approval approval : approvalStore.getApprovals(principal.getName(), client.getClientId())) { - if (authorizationRequest.getScope().contains(approval.getScope())) { - scopes.put(OAuth2Utils.SCOPE_PREFIX + approval.getScope(), - approval.getStatus() == ApprovalStatus.APPROVED ? "true" : "false"); - } - } - model.put("scopes", scopes); - } + model.putAll(userApprovalHandler.getUserApprovalRequest(authorizationRequest, principal)); return new ModelAndView(userApprovalPage, model); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/TokenStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/TokenStore.java index da106141b..1cf08356d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/TokenStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/TokenStore.java @@ -11,15 +11,15 @@ */ public interface TokenStore { - /** - * Read the authentication stored under the specified token value. - * - * @param token The token value under which the authentication is stored. - * @return The authentication, or null if none. - */ - OAuth2Authentication readAuthentication(OAuth2AccessToken token); - - /** + /** + * Read the authentication stored under the specified token value. + * + * @param token The token value under which the authentication is stored. + * @return The authentication, or null if none. + */ + OAuth2Authentication readAuthentication(OAuth2AccessToken token); + + /** * Read the authentication stored under the specified token value. * * @param token The token value under which the authentication is stored. diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java index 861967078..145b73dcf 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java @@ -12,11 +12,13 @@ */ package org.springframework.security.oauth2.config.annotation; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.util.Arrays; import java.util.List; +import java.util.Map; import javax.sql.DataSource; @@ -34,15 +36,17 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.mock.web.MockServletContext; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfiguration; 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.configurers.AuthorizationServerSecurityConfigurer; +import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; -import org.springframework.security.oauth2.provider.approval.TokenApprovalStore; +import org.springframework.security.oauth2.provider.approval.UserApprovalHandler; import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenGranter; import org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; @@ -71,6 +75,8 @@ public class AuthorizationServerConfigurationTests { public static List parameters() { return Arrays.asList( // @formatter:off new Object[] { BeanCreationException.class, new Class[] { AuthorizationServerUnconfigured.class } }, + new Object[] { null, new Class[] { AuthorizationServerVanilla.class } }, + new Object[] { null, new Class[] { AuthorizationServerDisableApproval.class } }, new Object[] { null, new Class[] { AuthorizationServerExtras.class } }, new Object[] { null, new Class[] { AuthorizationServerJdbc.class } }, new Object[] { null, new Class[] { AuthorizationServerJwt.class } }, @@ -112,16 +118,77 @@ public void testDefaults() { @Configuration @EnableWebMvcSecurity @EnableAuthorizationServer - protected static class AuthorizationServerUnconfigured implements Runnable { + protected static class AuthorizationServerUnconfigured { + } + + @Configuration + @EnableWebMvcSecurity + @EnableAuthorizationServer + protected static class AuthorizationServerVanilla extends AuthorizationServerConfigurerAdapter implements Runnable { @Autowired private AuthorizationEndpoint endpoint; + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + // @formatter:off + clients.inMemory() + .withClient("my-trusted-client") + .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit") + .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") + .scopes("read", "write", "trust") + .accessTokenValiditySeconds(60); + // @formatter:on + } + @Override public void run() { - // There should be an approval store by default (a TokenApprovalStore) - assertTrue(ReflectionTestUtils.getField(endpoint, "approvalStore") instanceof TokenApprovalStore); + // With no explicit approval store we still expect to see scopes in the user approval model + UserApprovalHandler handler = (UserApprovalHandler) ReflectionTestUtils.getField(endpoint, "userApprovalHandler"); + AuthorizationRequest authorizationRequest = new AuthorizationRequest(); + authorizationRequest.setScope(Arrays.asList("read")); + Map request = handler.getUserApprovalRequest(authorizationRequest, new UsernamePasswordAuthenticationToken("user", "password")); + assertTrue(request.containsKey("scopes")); } } + @Configuration + @EnableWebMvcSecurity + @EnableAuthorizationServer + protected static class AuthorizationServerDisableApproval extends AuthorizationServerConfigurerAdapter implements + Runnable { + + @Autowired + private AuthorizationEndpoint endpoint; + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + // @formatter:off + clients.inMemory() + .withClient("my-trusted-client") + .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit") + .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") + .scopes("read", "write", "trust") + .accessTokenValiditySeconds(60); + // @formatter:on + } + + @Override + public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { + oauthServer.approvalStoreDisabled(); + } + + @Override + public void run() { + // There should be no scopes in the approval model + UserApprovalHandler handler = (UserApprovalHandler) ReflectionTestUtils.getField(endpoint, "userApprovalHandler"); + AuthorizationRequest authorizationRequest = new AuthorizationRequest(); + authorizationRequest.setScope(Arrays.asList("read")); + Map request = handler.getUserApprovalRequest(authorizationRequest, new UsernamePasswordAuthenticationToken("user", "password")); + assertFalse(request.containsKey("scopes")); + } + + } + @Configuration @EnableWebMvcSecurity @EnableAuthorizationServer @@ -153,7 +220,8 @@ public void configure(ClientDetailsServiceConfigurer clients) throws Exception { public void run() { assertNotNull(context.getBean("clientDetailsService", ClientDetailsService.class).loadClientByClientId( "my-trusted-client")); - assertNotNull(ReflectionTestUtils.getField(context.getBean(AuthorizationEndpoint.class), "userApprovalHandler")); + assertNotNull(ReflectionTestUtils.getField(context.getBean(AuthorizationEndpoint.class), + "userApprovalHandler")); } } @@ -197,7 +265,7 @@ protected static class AuthorizationServerJwt extends AuthorizationServerConfigu @Autowired private ApplicationContext context; - + private JwtTokenServices tokenServices = new JwtTokenServices(); @Override @@ -228,7 +296,7 @@ protected static class AuthorizationServerApproval extends AuthorizationServerCo @Autowired private ApplicationContext context; - + @Override public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { oauthServer.tokenStore(tokenStore); @@ -248,7 +316,8 @@ public void configure(ClientDetailsServiceConfigurer clients) throws Exception { @Override public void run() { - assertNotNull(ReflectionTestUtils.getField(context.getBean(AuthorizationEndpoint.class), "userApprovalHandler")); + assertNotNull(ReflectionTestUtils.getField(context.getBean(AuthorizationEndpoint.class), + "userApprovalHandler")); } } @@ -259,14 +328,17 @@ protected static class AuthorizationServerTypes extends AuthorizationServerConfi @Autowired private AuthorizationServerTokenServices tokenServices; + @Autowired private ClientDetailsService clientDetailsService; + @Autowired private OAuth2RequestFactory requestFactory; @Override protected void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { - oauthServer.tokenGranter(new ClientCredentialsTokenGranter(tokenServices, clientDetailsService, requestFactory)); + oauthServer.tokenGranter(new ClientCredentialsTokenGranter(tokenServices, clientDetailsService, + requestFactory)); } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java index 184e114e4..2c750b267 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java @@ -43,9 +43,9 @@ import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.TokenGranter; import org.springframework.security.oauth2.provider.TokenRequest; +import org.springframework.security.oauth2.provider.approval.ApprovalStoreUserApprovalHandler; import org.springframework.security.oauth2.provider.approval.DefaultUserApprovalHandler; import org.springframework.security.oauth2.provider.approval.InMemoryApprovalStore; -import org.springframework.security.oauth2.provider.approval.UserApprovalHandler; import org.springframework.security.oauth2.provider.client.BaseClientDetails; import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; import org.springframework.web.bind.support.SimpleSessionStatus; @@ -129,7 +129,9 @@ public void testStartAuthorizationCodeFlow() throws Exception { @Test public void testApprovalStoreAddsScopes() throws Exception { - endpoint.setApprovalStore(new InMemoryApprovalStore()); + ApprovalStoreUserApprovalHandler userApprovalHandler = new ApprovalStoreUserApprovalHandler(); + userApprovalHandler.setApprovalStore(new InMemoryApprovalStore()); + endpoint.setUserApprovalHandler(userApprovalHandler); ModelAndView result = endpoint.authorize(model, getAuthorizationRequest("foo", null, null, "read", Collections.singleton("code")) .getRequestParameters(), sessionStatus, principal); assertEquals("forward:/oauth/confirm_access", result.getViewName()); @@ -196,7 +198,7 @@ public void testAuthorizationCodeWithTrickyQueryParams() throws Exception { @Test public void testAuthorizationCodeError() throws Exception { - endpoint.setUserApprovalHandler(new UserApprovalHandler() { + endpoint.setUserApprovalHandler(new DefaultUserApprovalHandler() { public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { return authorizationRequest; } @@ -247,7 +249,7 @@ public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) { } }); - endpoint.setUserApprovalHandler(new UserApprovalHandler() { + endpoint.setUserApprovalHandler(new DefaultUserApprovalHandler() { public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { return authorizationRequest; } @@ -281,7 +283,7 @@ public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) { return token; } }); - endpoint.setUserApprovalHandler(new UserApprovalHandler() { + endpoint.setUserApprovalHandler(new DefaultUserApprovalHandler() { public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { return authorizationRequest; } @@ -333,7 +335,7 @@ public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) { return token; } }); - endpoint.setUserApprovalHandler(new UserApprovalHandler() { + endpoint.setUserApprovalHandler(new DefaultUserApprovalHandler() { public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { return true; } @@ -366,7 +368,7 @@ public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) { throw new IllegalStateException("Shouldn't be called"); } }); - endpoint.setUserApprovalHandler(new UserApprovalHandler() { + endpoint.setUserApprovalHandler(new DefaultUserApprovalHandler() { public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { return true; } @@ -407,7 +409,7 @@ public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) { @Test public void testImplicitError() throws Exception { - endpoint.setUserApprovalHandler(new UserApprovalHandler() { + endpoint.setUserApprovalHandler(new DefaultUserApprovalHandler() { public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { return authorizationRequest; } From b24d6f81ff22c444f0c78c919c86f50dda9d0580 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 8 Apr 2014 18:01:17 +0100 Subject: [PATCH 218/831] Re-instate automatic @Bean for InMemoryTokenStore --- .../sparklr/config/OAuth2ServerConfig.java | 12 +++-------- .../samples/config/SecurityConfigTests.java | 6 +++--- .../AuthorizationServerConfiguration.java | 21 +++++++++++++++++-- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java index 763f54008..8cb3b82a3 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java @@ -37,7 +37,6 @@ import org.springframework.security.oauth2.provider.OAuth2RequestFactory; import org.springframework.security.oauth2.provider.approval.ApprovalStore; import org.springframework.security.oauth2.provider.approval.TokenApprovalStore; -import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; import org.springframework.security.oauth2.provider.token.TokenStore; /** @@ -49,12 +48,6 @@ public class OAuth2ServerConfig { private static final String SPARKLR_RESOURCE_ID = "sparklr"; - // TODO: add this automatically as a default? - @Bean - public TokenStore tokenStore() { - return new InMemoryTokenStore(); - } - @Configuration @Order(10) protected static class UiResourceConfiguration extends WebSecurityConfigurerAdapter { @@ -110,7 +103,8 @@ public void configure(HttpSecurity http) throws Exception { @EnableAuthorizationServer protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter { - private TokenStore tokenStore = new InMemoryTokenStore(); + @Autowired + private TokenStore tokenStore; @Autowired private OAuth2RequestFactory requestFactory; @@ -124,7 +118,7 @@ protected static class AuthorizationServerConfiguration extends AuthorizationSer @Value("${tonr.redirect:http://localhost:8080/tonr2/sparklr/redirect}") private String tonrRedirectUri; - + @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/samples/config/SecurityConfigTests.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/samples/config/SecurityConfigTests.java index 4274a96ae..4366f2b61 100644 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/samples/config/SecurityConfigTests.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/samples/config/SecurityConfigTests.java @@ -23,7 +23,7 @@ import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.security.oauth.examples.sparklr.config.SecurityConfiguration; -import org.springframework.security.oauth2.provider.token.TokenStore; +import org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint; import org.springframework.security.web.FilterChainProxy; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -46,10 +46,10 @@ public static class Config {} private FilterChainProxy springSecurityFilterChain; @Autowired - private TokenStore tokenStore; + private AuthorizationEndpoint endpoint; @Test public void securityConfigurationLoads() { - assertNotNull(tokenStore); + assertNotNull(endpoint); } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java index 1e2b1b0ad..83190fae1 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java @@ -21,18 +21,23 @@ import javax.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.ScopedProxyMode; import org.springframework.core.annotation.Order; +import org.springframework.core.type.AnnotationMetadata; import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.configuration.ClientDetailsServiceConfiguration; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfiguration.TokenStoreRegistrar; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; @@ -57,7 +62,7 @@ * */ @Configuration -@Import(ClientDetailsServiceConfiguration.class) +@Import({ClientDetailsServiceConfiguration.class, TokenStoreRegistrar.class}) @Order(0) public class AuthorizationServerConfiguration extends WebSecurityConfigurerAdapter { @@ -103,13 +108,13 @@ public void configure(ClientDetailsServiceConfigurer clientDetails) throws Excep protected void configure(HttpSecurity http) throws Exception { AuthorizationServerSecurityConfigurer configurer = new AuthorizationServerSecurityConfigurer(); configurer.clientDetailsService(clientDetailsService); - configure(configurer); if (tokenStore != null) { configurer.tokenStore(tokenStore); } if (approvalStore != null) { configurer.approvalStore(approvalStore); } + configure(configurer); http.apply(configurer); String tokenEndpointPath = oauth2EndpointHandlerMapping().getPath("/oauth/token"); // @formatter:off @@ -247,4 +252,16 @@ private String extractPath(FrameworkEndpointHandlerMapping mapping, String page) } + protected static class TokenStoreRegistrar implements ImportBeanDefinitionRegistrar { + + @Override + public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { + if (!registry.containsBeanDefinition(TOKEN_STORE_BEAN_NAME) + && !registry.containsBeanDefinition(APPROVAL_STORE_BEAN_NAME)) { + registry.registerBeanDefinition(TOKEN_STORE_BEAN_NAME, new RootBeanDefinition(InMemoryTokenStore.class)); + } + } + + } + } From 3e01fa0fe9d007df2ba06cea4127f3d7e3caef87 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 8 Apr 2014 18:16:29 +0100 Subject: [PATCH 219/831] Move setter for AccessTokenConverter down in to JwtTokenEnhancer The existence of 2 instances of AccessTokenConverter was problematic, and one of them didn't have a setter. It made sense to merge the feature down into the JWT token enhancer, keeping that class as an internal imlementation detail but allowing customization. Fixes gh-176 --- spring-security-oauth2/pom.xml | 5 +++ .../provider/token/JwtTokenEnhancer.java | 31 ++++++++++++++++++- .../provider/token/JwtTokenServices.java | 15 +++------ 3 files changed, 40 insertions(+), 11 deletions(-) diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 95a81921e..5b6279304 100644 --- a/spring-security-oauth2/pom.xml +++ b/spring-security-oauth2/pom.xml @@ -218,6 +218,11 @@ 2.0.0 test + + org.springframework.boot + spring-boot-starter + 1.0.0.RELEASE + diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancer.java index 931ac5b9d..91f469dd7 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancer.java @@ -41,7 +41,7 @@ * @author Dave Syer * @author Luke Taylor */ -public class JwtTokenEnhancer implements TokenEnhancer, InitializingBean { +public class JwtTokenEnhancer implements TokenEnhancer, AccessTokenConverter, InitializingBean { /** * Field name for token id. @@ -61,6 +61,35 @@ public class JwtTokenEnhancer implements TokenEnhancer, InitializingBean { private String signingKey = verifierKey; private SignatureVerifier verifier; + + /** + * @param tokenConverter the tokenConverter to set + */ + public void setAccessTokenConverter(AccessTokenConverter tokenConverter) { + this.tokenConverter = tokenConverter; + } + + /** + * @return the tokenConverter in use + */ + public AccessTokenConverter getAccessTokenConverter() { + return tokenConverter; + } + + @Override + public Map convertAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) { + return tokenConverter.convertAccessToken(token, authentication); + } + + @Override + public OAuth2AccessToken extractAccessToken(String value, Map map) { + return tokenConverter.extractAccessToken(value, map); + } + + @Override + public OAuth2Authentication extractAuthentication(Map map) { + return tokenConverter.extractAuthentication(map); + } /** * Get the verification key for the token signatures. diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenServices.java index cf367f610..c71367be8 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenServices.java @@ -49,8 +49,6 @@ public class JwtTokenServices implements AuthorizationServerTokenServices, Resou */ public static final String TOKEN_ID = "jti"; - private AccessTokenConverter tokenConverter = new DefaultAccessTokenConverter(); - private ClientDetailsService clientDetailsService; private TokenEnhancer accessTokenEnhancer; @@ -93,17 +91,14 @@ public void setReuseRefreshToken(boolean reuseRefreshToken) { public void setTokenEnhancer(TokenEnhancer accessTokenEnhancer) { this.accessTokenEnhancer = accessTokenEnhancer; } - + /** - * A converter of access tokens to and from a map representation. Can be used to add and subtract fields from the - * JWT. - * * @param tokenConverter the tokenConverter to set */ public void setAccessTokenConverter(AccessTokenConverter tokenConverter) { - this.tokenConverter = tokenConverter; + this.jwtTokenEnhancer.setAccessTokenConverter(tokenConverter); } - + /** * The validity (in seconds) of the refresh token. * @@ -168,11 +163,11 @@ public void afterPropertiesSet() throws Exception { } public OAuth2Authentication loadAuthentication(String token) throws AuthenticationException { - return tokenConverter.extractAuthentication(decode(token)); + return jwtTokenEnhancer.extractAuthentication(decode(token)); } public OAuth2AccessToken readAccessToken(String token) { - return tokenConverter.extractAccessToken(token, decode(token)); + return jwtTokenEnhancer.extractAccessToken(token, decode(token)); } public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication) throws AuthenticationException { From 27279348dfe51a4b6dca349e31e66c7eddc60061 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 9 Apr 2014 10:39:15 +0100 Subject: [PATCH 220/831] Add JwtTokenStore This is a simple implementation of TokenStore (which doesn't really store tokens but knows how to decode enough of them to make DefaultTokenServices useful). I think it might make JwtTokenServices obsolete but I'll leave both in for now (and remove one before the next release probably). See gh-176 --- .../sparklr/config/OAuth2ServerConfig.java | 8 +- .../AuthorizationServerConfiguration.java | 23 +- ...AuthorizationServerSecurityConfigurer.java | 9 +- .../provider/token/AccessTokenConverter.java | 10 + .../token/DefaultAccessTokenConverter.java | 14 +- .../provider/token/DefaultTokenServices.java | 198 +++++++----------- .../DefaultUserAuthenticationConverter.java | 4 - .../provider/token/JwtTokenEnhancer.java | 22 +- .../oauth2/provider/token/JwtTokenStore.java | 109 ++++++++++ .../token/UserAuthenticationConverter.java | 4 + ...AuthorizationServerConfigurationTests.java | 2 +- .../provider/token/JwtTokenEnhancerTests.java | 31 ++- 12 files changed, 279 insertions(+), 155 deletions(-) create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenStore.java diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java index 8cb3b82a3..cfa5ec03d 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java @@ -37,6 +37,7 @@ import org.springframework.security.oauth2.provider.OAuth2RequestFactory; import org.springframework.security.oauth2.provider.approval.ApprovalStore; import org.springframework.security.oauth2.provider.approval.TokenApprovalStore; +import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; import org.springframework.security.oauth2.provider.token.TokenStore; /** @@ -66,7 +67,7 @@ protected void configure(HttpSecurity http) throws Exception { // @formatter:on } } - + @Configuration @EnableResourceServer protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { @@ -180,6 +181,11 @@ public SparklrUserApprovalHandler userApprovalHandler() throws Exception { return handler; } + @Bean + public TokenStore tokenStore() { + return new InMemoryTokenStore(); + } + @Bean public ApprovalStore approvalStore() throws Exception { TokenApprovalStore store = new TokenApprovalStore(); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java index 83190fae1..b727f2f51 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java @@ -20,18 +20,19 @@ import javax.annotation.PostConstruct; +import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; -import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.ScopedProxyMode; import org.springframework.core.annotation.Order; -import org.springframework.core.type.AnnotationMetadata; import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @@ -62,7 +63,7 @@ * */ @Configuration -@Import({ClientDetailsServiceConfiguration.class, TokenStoreRegistrar.class}) +@Import({ ClientDetailsServiceConfiguration.class, TokenStoreRegistrar.class }) @Order(0) public class AuthorizationServerConfiguration extends WebSecurityConfigurerAdapter { @@ -252,16 +253,26 @@ private String extractPath(FrameworkEndpointHandlerMapping mapping, String page) } - protected static class TokenStoreRegistrar implements ImportBeanDefinitionRegistrar { + @Configuration + protected static class TokenStoreRegistrar implements BeanDefinitionRegistryPostProcessor { + + private BeanDefinitionRegistry registry; + // Use a BeanFactoryPostProcessor to register a bean definition for a TokenStore in a safe way (without + // pre-empting a bean specified by the user) @Override - public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { if (!registry.containsBeanDefinition(TOKEN_STORE_BEAN_NAME) && !registry.containsBeanDefinition(APPROVAL_STORE_BEAN_NAME)) { registry.registerBeanDefinition(TOKEN_STORE_BEAN_NAME, new RootBeanDefinition(InMemoryTokenStore.class)); } } + @Override + public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { + this.registry = registry; + } + } - + } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java index 5826229e5..c1eca1a5c 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java @@ -57,6 +57,7 @@ import org.springframework.security.oauth2.provider.token.ConsumerTokenServices; import org.springframework.security.oauth2.provider.token.DefaultTokenServices; import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; +import org.springframework.security.oauth2.provider.token.JwtTokenStore; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.DefaultSecurityFilterChain; @@ -155,7 +156,7 @@ public AuthorizationServerSecurityConfigurer tokenStore(TokenStore tokenStore) { return this; } - public AuthorizationServerSecurityConfigurer tokenService(AuthorizationServerTokenServices tokenServices) { + public AuthorizationServerSecurityConfigurer tokenServices(AuthorizationServerTokenServices tokenServices) { this.tokenServices = tokenServices; return this; } @@ -319,7 +320,7 @@ private TokenStore tokenStore() { } private ApprovalStore approvalStore() { - if (approvalStore==null && tokenStore() != null && !approvalStoreDisabled) { + if (approvalStore==null && tokenStore() != null && !isApprovalStoreDisabled()) { TokenApprovalStore tokenApprovalStore = new TokenApprovalStore(); tokenApprovalStore.setTokenStore(tokenStore()); this.approvalStore = tokenApprovalStore; @@ -327,6 +328,10 @@ private ApprovalStore approvalStore() { return this.approvalStore; } + private boolean isApprovalStoreDisabled() { + return approvalStoreDisabled || (tokenStore() instanceof JwtTokenStore); + } + private ClientDetailsService clientDetailsService() { if (clientDetailsService == null) { this.clientDetailsService = new InMemoryClientDetailsService(); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AccessTokenConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AccessTokenConverter.java index 9d40a8be7..cb810237a 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AccessTokenConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AccessTokenConverter.java @@ -25,6 +25,16 @@ */ public interface AccessTokenConverter { + final String AUD = "aud"; + + final String CLIENT_ID = "client_id"; + + final String EXP = "exp"; + + final String JTI = JwtTokenEnhancer.TOKEN_ID; + + final String SCOPE = OAuth2AccessToken.SCOPE; + /** * @param token an access token * @param authentication the current OAuth authentication diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java index 5fa8add79..bd0610bd0 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java @@ -35,16 +35,6 @@ */ public class DefaultAccessTokenConverter implements AccessTokenConverter { - private static final String AUD = "aud"; - - private static final String CLIENT_ID = "client_id"; - - private static final String EXP = "exp"; - - private static final String JTI = JwtTokenEnhancer.TOKEN_ID; - - private static final String SCOPE = OAuth2AccessToken.SCOPE; - private UserAuthenticationConverter userTokenConverter = new DefaultUserAuthenticationConverter(); /** @@ -64,7 +54,9 @@ public void setUserTokenConverter(UserAuthenticationConverter userTokenConverter response.putAll(userTokenConverter.convertUserAuthentication(authentication.getUserAuthentication())); } - response.put(SCOPE, token.getScope()); + if (token.getScope()!=null) { + response.put(SCOPE, token.getScope()); + } if (token.getAdditionalInformation().containsKey(JTI)) { response.put(JTI, token.getAdditionalInformation().get(JTI)); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java index 51d20c996..7e87bd8ad 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java @@ -36,23 +36,21 @@ import org.springframework.util.Assert; /** - * Base implementation for token services using random UUID values for the - * access token and refresh token values. The main extension point for - * customizations is the {@link TokenEnhancer} which will be called after the - * access and refresh tokens have been generated but before they are stored. + * Base implementation for token services using random UUID values for the access token and refresh token values. The + * main extension point for customizations is the {@link TokenEnhancer} which will be called after the access and + * refresh tokens have been generated but before they are stored. *

    - * Persistence is delegated to a {@code TokenStore} implementation and - * customization of the access token to a {@link TokenEnhancer}. + * Persistence is delegated to a {@code TokenStore} implementation and customization of the access token to a + * {@link TokenEnhancer}. * * @author Ryan Heaton * @author Luke Taylor * @author Dave Syer */ -public class DefaultTokenServices implements AuthorizationServerTokenServices, - ResourceServerTokenServices, ConsumerTokenServices, InitializingBean { +public class DefaultTokenServices implements AuthorizationServerTokenServices, ResourceServerTokenServices, + ConsumerTokenServices, InitializingBean { - private int refreshTokenValiditySeconds = 60 * 60 * 24 * 30; // default 30 - // days. + private int refreshTokenValiditySeconds = 60 * 60 * 24 * 30; // default 30 days. private int accessTokenValiditySeconds = 60 * 60 * 12; // default 12 hours. @@ -67,18 +65,15 @@ public class DefaultTokenServices implements AuthorizationServerTokenServices, private TokenEnhancer accessTokenEnhancer; /** - * Initialize these token services. If no random generator is set, one will - * be created. + * Initialize these token services. If no random generator is set, one will be created. */ public void afterPropertiesSet() throws Exception { Assert.notNull(tokenStore, "tokenStore must be set"); } - public OAuth2AccessToken createAccessToken( - OAuth2Authentication authentication) throws AuthenticationException { + public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication) throws AuthenticationException { - OAuth2AccessToken existingAccessToken = tokenStore - .getAccessToken(authentication); + OAuth2AccessToken existingAccessToken = tokenStore.getAccessToken(authentication); OAuth2RefreshToken refreshToken = null; if (existingAccessToken != null) { if (existingAccessToken.isExpired()) { @@ -90,7 +85,8 @@ public OAuth2AccessToken createAccessToken( tokenStore.removeRefreshToken(refreshToken); } tokenStore.removeAccessToken(existingAccessToken); - } else { + } + else { return existingAccessToken; } } @@ -112,8 +108,7 @@ else if (refreshToken instanceof ExpiringOAuth2RefreshToken) { } } - OAuth2AccessToken accessToken = createAccessToken(authentication, - refreshToken); + OAuth2AccessToken accessToken = createAccessToken(authentication, refreshToken); tokenStore.storeAccessToken(accessToken, authentication); // In case it was modified refreshToken = accessToken.getRefreshToken(); @@ -124,27 +119,22 @@ else if (refreshToken instanceof ExpiringOAuth2RefreshToken) { } - public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, - TokenRequest tokenRequest) throws AuthenticationException { + public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, TokenRequest tokenRequest) + throws AuthenticationException { if (!supportRefreshToken) { - throw new InvalidGrantException("Invalid refresh token: " - + refreshTokenValue); + throw new InvalidGrantException("Invalid refresh token: " + refreshTokenValue); } - OAuth2RefreshToken refreshToken = tokenStore - .readRefreshToken(refreshTokenValue); + OAuth2RefreshToken refreshToken = tokenStore.readRefreshToken(refreshTokenValue); if (refreshToken == null) { - throw new InvalidGrantException("Invalid refresh token: " - + refreshTokenValue); + throw new InvalidGrantException("Invalid refresh token: " + refreshTokenValue); } - OAuth2Authentication authentication = tokenStore - .readAuthenticationForRefreshToken(refreshToken); + OAuth2Authentication authentication = tokenStore.readAuthenticationForRefreshToken(refreshToken); String clientId = authentication.getOAuth2Request().getClientId(); if (clientId == null || !clientId.equals(tokenRequest.getClientId())) { - throw new InvalidGrantException( - "Wrong client for this refresh token: " + refreshTokenValue); + throw new InvalidGrantException("Wrong client for this refresh token: " + refreshTokenValue); } // clear out any access tokens already associated with the refresh @@ -153,20 +143,17 @@ public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, if (isExpired(refreshToken)) { tokenStore.removeRefreshToken(refreshToken); - throw new InvalidTokenException("Invalid refresh token (expired): " - + refreshToken); + throw new InvalidTokenException("Invalid refresh token (expired): " + refreshToken); } - authentication = createRefreshedAuthentication(authentication, - tokenRequest.getScope()); + authentication = createRefreshedAuthentication(authentication, tokenRequest.getScope()); if (!reuseRefreshToken) { tokenStore.removeRefreshToken(refreshToken); refreshToken = createRefreshToken(authentication); } - OAuth2AccessToken accessToken = createAccessToken(authentication, - refreshToken); + OAuth2AccessToken accessToken = createAccessToken(authentication, refreshToken); tokenStore.storeAccessToken(accessToken, authentication); if (!reuseRefreshToken) { tokenStore.storeRefreshToken(refreshToken, authentication); @@ -181,26 +168,21 @@ public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) { /** * Create a refreshed authentication. * - * @param authentication - * The authentication. - * @param scope - * The scope for the refreshed token. + * @param authentication The authentication. + * @param scope The scope for the refreshed token. * @return The refreshed authentication. - * @throws InvalidScopeException - * If the scope requested is invalid or wider than the original - * scope. + * @throws InvalidScopeException If the scope requested is invalid or wider than the original scope. */ - private OAuth2Authentication createRefreshedAuthentication( - OAuth2Authentication authentication, Set scope) { + private OAuth2Authentication createRefreshedAuthentication(OAuth2Authentication authentication, Set scope) { OAuth2Authentication narrowed = authentication; if (scope != null && !scope.isEmpty()) { OAuth2Request clientAuth = authentication.getOAuth2Request(); Set originalScope = clientAuth.getScope(); if (originalScope == null || !originalScope.containsAll(scope)) { - throw new InvalidScopeException( - "Unable to narrow the scope of the client authentication to " - + scope + ".", originalScope); - } else { + throw new InvalidScopeException("Unable to narrow the scope of the client authentication to " + scope + + ".", originalScope); + } + else { narrowed = new OAuth2Authentication(clientAuth.narrowScope(scope), authentication.getUserAuthentication()); } @@ -212,8 +194,7 @@ protected boolean isExpired(OAuth2RefreshToken refreshToken) { if (refreshToken instanceof ExpiringOAuth2RefreshToken) { ExpiringOAuth2RefreshToken expiringToken = (ExpiringOAuth2RefreshToken) refreshToken; return expiringToken.getExpiration() == null - || System.currentTimeMillis() > expiringToken - .getExpiration().getTime(); + || System.currentTimeMillis() > expiringToken.getExpiration().getTime(); } return false; } @@ -222,35 +203,28 @@ public OAuth2AccessToken readAccessToken(String accessToken) { return tokenStore.readAccessToken(accessToken); } - public OAuth2Authentication loadAuthentication(String accessTokenValue) - throws AuthenticationException { - OAuth2AccessToken accessToken = tokenStore - .readAccessToken(accessTokenValue); + public OAuth2Authentication loadAuthentication(String accessTokenValue) throws AuthenticationException { + OAuth2AccessToken accessToken = tokenStore.readAccessToken(accessTokenValue); if (accessToken == null) { - throw new InvalidTokenException("Invalid access token: " - + accessTokenValue); - } else if (accessToken.isExpired()) { + throw new InvalidTokenException("Invalid access token: " + accessTokenValue); + } + else if (accessToken.isExpired()) { tokenStore.removeAccessToken(accessToken); - throw new InvalidTokenException("Access token expired: " - + accessTokenValue); + throw new InvalidTokenException("Access token expired: " + accessTokenValue); } - OAuth2Authentication result = tokenStore - .readAuthentication(accessToken); + OAuth2Authentication result = tokenStore.readAuthentication(accessToken); return result; } public String getClientId(String tokenValue) { - OAuth2Authentication authentication = tokenStore - .readAuthentication(tokenValue); + OAuth2Authentication authentication = tokenStore.readAuthentication(tokenValue); if (authentication == null) { - throw new InvalidTokenException("Invalid access token: " - + tokenValue); + throw new InvalidTokenException("Invalid access token: " + tokenValue); } OAuth2Request clientAuth = authentication.getOAuth2Request(); if (clientAuth == null) { - throw new InvalidTokenException( - "Invalid access token (no client id): " + tokenValue); + throw new InvalidTokenException("Invalid access token (no client id): " + tokenValue); } return clientAuth.getClientId(); } @@ -275,47 +249,37 @@ public boolean revokeToken(String tokenValue) { return true; } - private ExpiringOAuth2RefreshToken createRefreshToken( - OAuth2Authentication authentication) { + private ExpiringOAuth2RefreshToken createRefreshToken(OAuth2Authentication authentication) { if (!isSupportRefreshToken(authentication.getOAuth2Request())) { return null; } - int validitySeconds = getRefreshTokenValiditySeconds(authentication - .getOAuth2Request()); - ExpiringOAuth2RefreshToken refreshToken = new DefaultExpiringOAuth2RefreshToken( - UUID.randomUUID().toString(), new Date( - System.currentTimeMillis() + (validitySeconds * 1000L))); + int validitySeconds = getRefreshTokenValiditySeconds(authentication.getOAuth2Request()); + ExpiringOAuth2RefreshToken refreshToken = new DefaultExpiringOAuth2RefreshToken(UUID.randomUUID().toString(), + new Date(System.currentTimeMillis() + (validitySeconds * 1000L))); return refreshToken; } - private OAuth2AccessToken createAccessToken( - OAuth2Authentication authentication, OAuth2RefreshToken refreshToken) { - DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(UUID - .randomUUID().toString()); - int validitySeconds = getAccessTokenValiditySeconds(authentication - .getOAuth2Request()); + private OAuth2AccessToken createAccessToken(OAuth2Authentication authentication, OAuth2RefreshToken refreshToken) { + DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(UUID.randomUUID().toString()); + int validitySeconds = getAccessTokenValiditySeconds(authentication.getOAuth2Request()); if (validitySeconds > 0) { - token.setExpiration(new Date(System.currentTimeMillis() - + (validitySeconds * 1000L))); + token.setExpiration(new Date(System.currentTimeMillis() + (validitySeconds * 1000L))); } token.setRefreshToken(refreshToken); token.setScope(authentication.getOAuth2Request().getScope()); - return accessTokenEnhancer != null ? accessTokenEnhancer.enhance(token, - authentication) : token; + return accessTokenEnhancer != null ? accessTokenEnhancer.enhance(token, authentication) : token; } /** * The access token validity period in seconds * - * @param authorizationRequest - * the current authorization request + * @param authorizationRequest the current authorization request * @return the access token validity period in seconds */ protected int getAccessTokenValiditySeconds(OAuth2Request clientAuth) { if (clientDetailsService != null) { - ClientDetails client = clientDetailsService - .loadClientByClientId(clientAuth.getClientId()); + ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId()); Integer validity = client.getAccessTokenValiditySeconds(); if (validity != null) { return validity; @@ -327,14 +291,12 @@ protected int getAccessTokenValiditySeconds(OAuth2Request clientAuth) { /** * The refresh token validity period in seconds * - * @param authorizationRequest - * the current authorization request + * @param authorizationRequest the current authorization request * @return the refresh token validity period in seconds */ protected int getRefreshTokenValiditySeconds(OAuth2Request clientAuth) { if (clientDetailsService != null) { - ClientDetails client = clientDetailsService - .loadClientByClientId(clientAuth.getClientId()); + ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId()); Integer validity = client.getRefreshTokenValiditySeconds(); if (validity != null) { return validity; @@ -345,28 +307,23 @@ protected int getRefreshTokenValiditySeconds(OAuth2Request clientAuth) { /** * Is a refresh token supported for this client (or the global setting if - * {@link #setClientDetailsService(ClientDetailsService) - * clientDetailsService} is not set. + * {@link #setClientDetailsService(ClientDetailsService) clientDetailsService} is not set. * - * @param authorizationRequest - * the current authorization request + * @param authorizationRequest the current authorization request * @return boolean to indicate if refresh token is supported */ protected boolean isSupportRefreshToken(OAuth2Request clientAuth) { if (clientDetailsService != null) { - ClientDetails client = clientDetailsService - .loadClientByClientId(clientAuth.getClientId()); + ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId()); return client.getAuthorizedGrantTypes().contains("refresh_token"); } return this.supportRefreshToken; } /** - * An access token enhancer that will be applied to a new token before it is - * saved in the token store. + * An access token enhancer that will be applied to a new token before it is saved in the token store. * - * @param accessTokenEnhancer - * the access token enhancer to set + * @param accessTokenEnhancer the access token enhancer to set */ public void setTokenEnhancer(TokenEnhancer accessTokenEnhancer) { this.accessTokenEnhancer = accessTokenEnhancer; @@ -375,21 +332,18 @@ public void setTokenEnhancer(TokenEnhancer accessTokenEnhancer) { /** * The validity (in seconds) of the refresh token. * - * @param refreshTokenValiditySeconds - * The validity (in seconds) of the refresh token. + * @param refreshTokenValiditySeconds The validity (in seconds) of the refresh token. */ public void setRefreshTokenValiditySeconds(int refreshTokenValiditySeconds) { this.refreshTokenValiditySeconds = refreshTokenValiditySeconds; } /** - * The default validity (in seconds) of the access token. Zero or negative - * for non-expiring tokens. If a client details service is set the validity - * period will be read from he client, defaulting to this value if not - * defined by the client. + * The default validity (in seconds) of the access token. Zero or negative for non-expiring tokens. If a client + * details service is set the validity period will be read from he client, defaulting to this value if not defined + * by the client. * - * @param accessTokenValiditySeconds - * The validity (in seconds) of the access token. + * @param accessTokenValiditySeconds The validity (in seconds) of the access token. */ public void setAccessTokenValiditySeconds(int accessTokenValiditySeconds) { this.accessTokenValiditySeconds = accessTokenValiditySeconds; @@ -398,8 +352,7 @@ public void setAccessTokenValiditySeconds(int accessTokenValiditySeconds) { /** * Whether to support the refresh token. * - * @param supportRefreshToken - * Whether to support the refresh token. + * @param supportRefreshToken Whether to support the refresh token. */ public void setSupportRefreshToken(boolean supportRefreshToken) { this.supportRefreshToken = supportRefreshToken; @@ -408,8 +361,7 @@ public void setSupportRefreshToken(boolean supportRefreshToken) { /** * Whether to reuse refresh tokens (until expired). * - * @param reuseRefreshToken - * Whether to reuse refresh tokens (until expired). + * @param reuseRefreshToken Whether to reuse refresh tokens (until expired). */ public void setReuseRefreshToken(boolean reuseRefreshToken) { this.reuseRefreshToken = reuseRefreshToken; @@ -418,23 +370,19 @@ public void setReuseRefreshToken(boolean reuseRefreshToken) { /** * The persistence strategy for token storage. * - * @param tokenStore - * the store for access and refresh tokens. + * @param tokenStore the store for access and refresh tokens. */ public void setTokenStore(TokenStore tokenStore) { this.tokenStore = tokenStore; } /** - * The client details service to use for looking up clients (if necessary). - * Optional if the access token expiry is set globally via - * {@link #setAccessTokenValiditySeconds(int)}. + * The client details service to use for looking up clients (if necessary). Optional if the access token expiry is + * set globally via {@link #setAccessTokenValiditySeconds(int)}. * - * @param clientDetailsService - * the client details service + * @param clientDetailsService the client details service */ - public void setClientDetailsService( - ClientDetailsService clientDetailsService) { + public void setClientDetailsService(ClientDetailsService clientDetailsService) { this.clientDetailsService = clientDetailsService; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultUserAuthenticationConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultUserAuthenticationConverter.java index 42ed6783c..c7da15c17 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultUserAuthenticationConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultUserAuthenticationConverter.java @@ -32,10 +32,6 @@ */ public class DefaultUserAuthenticationConverter implements UserAuthenticationConverter { - private static final String AUTHORITIES = "authorities"; - - private static final String USERNAME = "user_name"; - private Collection defaultAuthorities; /** diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancer.java index 91f469dd7..7133d26eb 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancer.java @@ -13,6 +13,7 @@ package org.springframework.security.oauth2.provider.token; import java.security.Principal; +import java.util.Date; import java.util.LinkedHashMap; import java.util.Map; @@ -28,8 +29,12 @@ import org.springframework.security.jwt.crypto.sign.RsaVerifier; import org.springframework.security.jwt.crypto.sign.SignatureVerifier; import org.springframework.security.jwt.crypto.sign.Signer; +import org.springframework.security.oauth2.common.DefaultExpiringOAuth2RefreshToken; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; +import org.springframework.security.oauth2.common.DefaultOAuth2RefreshToken; +import org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.common.OAuth2RefreshToken; import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; import org.springframework.security.oauth2.common.util.RandomValueStringGenerator; import org.springframework.security.oauth2.provider.OAuth2Authentication; @@ -61,14 +66,14 @@ public class JwtTokenEnhancer implements TokenEnhancer, AccessTokenConverter, In private String signingKey = verifierKey; private SignatureVerifier verifier; - + /** * @param tokenConverter the tokenConverter to set */ public void setAccessTokenConverter(AccessTokenConverter tokenConverter) { this.tokenConverter = tokenConverter; } - + /** * @return the tokenConverter in use */ @@ -162,7 +167,18 @@ public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentica } result.setAdditionalInformation(info); result.setValue(encode(result, authentication)); - return result; + OAuth2RefreshToken refreshToken = result.getRefreshToken(); + if (refreshToken != null) { + DefaultOAuth2AccessToken encodedRefreshToken = new DefaultOAuth2AccessToken(accessToken); + DefaultOAuth2RefreshToken token = new DefaultOAuth2RefreshToken(encode(encodedRefreshToken, authentication)); + if (refreshToken instanceof ExpiringOAuth2RefreshToken) { + Date expiration = ((ExpiringOAuth2RefreshToken) refreshToken).getExpiration(); + encodedRefreshToken.setExpiration(expiration); + token = new DefaultExpiringOAuth2RefreshToken(encode(encodedRefreshToken, authentication), expiration); + } + result.setRefreshToken(token); + } + return result; } protected String encode(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenStore.java new file mode 100644 index 000000000..af64aac62 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenStore.java @@ -0,0 +1,109 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.springframework.security.oauth2.provider.token; + +import java.util.Collection; +import java.util.Collections; + +import org.springframework.security.oauth2.common.DefaultExpiringOAuth2RefreshToken; +import org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.common.OAuth2RefreshToken; +import org.springframework.security.oauth2.provider.OAuth2Authentication; + +/** + * @author Dave Syer + * + */ +public class JwtTokenStore implements TokenStore { + + private JwtTokenEnhancer jwtTokenEnhancer; + + /** + * Create a JwtTokenStore with this token enhancer (must be shared with the DefaultTokenServices if used). + * + * @param jwtTokenEnhancer + */ + public JwtTokenStore(JwtTokenEnhancer jwtTokenEnhancer) { + this.jwtTokenEnhancer = jwtTokenEnhancer; + } + + @Override + public OAuth2Authentication readAuthentication(OAuth2AccessToken token) { + return readAuthentication(token.getValue()); + } + + @Override + public OAuth2Authentication readAuthentication(String token) { + return jwtTokenEnhancer.extractAuthentication(jwtTokenEnhancer.decode(token)); + } + + @Override + public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) { + } + + @Override + public OAuth2AccessToken readAccessToken(String tokenValue) { + return jwtTokenEnhancer.extractAccessToken(tokenValue, jwtTokenEnhancer.decode(tokenValue)); + } + + @Override + public void removeAccessToken(OAuth2AccessToken token) { + } + + @Override + public void storeRefreshToken(OAuth2RefreshToken refreshToken, OAuth2Authentication authentication) { + } + + @Override + public OAuth2RefreshToken readRefreshToken(String tokenValue) { + OAuth2AccessToken encodedRefreshToken = readAccessToken(tokenValue); + ExpiringOAuth2RefreshToken refreshToken = new DefaultExpiringOAuth2RefreshToken(encodedRefreshToken.getValue(), + encodedRefreshToken.getExpiration()); + return refreshToken; + } + + @Override + public OAuth2Authentication readAuthenticationForRefreshToken(OAuth2RefreshToken token) { + return readAuthentication(token.getValue()); + } + + @Override + public void removeRefreshToken(OAuth2RefreshToken token) { + } + + @Override + public void removeAccessTokenUsingRefreshToken(OAuth2RefreshToken refreshToken) { + } + + @Override + public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) { + return null; + } + + @Override + public Collection findTokensByUserName(String userName) { + return Collections.emptySet(); + } + + @Override + public Collection findTokensByClientId(String clientId) { + return Collections.emptySet(); + } + + public void setTokenEnhancer(JwtTokenEnhancer tokenEnhancer) { + this.jwtTokenEnhancer = tokenEnhancer; + } + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/UserAuthenticationConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/UserAuthenticationConverter.java index 42e55991b..4823b0478 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/UserAuthenticationConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/UserAuthenticationConverter.java @@ -25,6 +25,10 @@ */ public interface UserAuthenticationConverter { + final String AUTHORITIES = "authorities"; + + final String USERNAME = "user_name"; + /** * Extract information about the user to be used in an access token (i.e. for resource servers). * diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java index 145b73dcf..315003ad5 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java @@ -270,7 +270,7 @@ protected static class AuthorizationServerJwt extends AuthorizationServerConfigu @Override public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { - oauthServer.tokenService(tokenServices).realm("sparklr2/client"); + oauthServer.tokenServices(tokenServices).realm("sparklr2/client"); } @Override diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancerTests.java index 39f4d13dd..3ebd4c096 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancerTests.java @@ -24,6 +24,7 @@ import org.springframework.security.jwt.JwtHelper; import org.springframework.security.jwt.crypto.sign.RsaVerifier; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; +import org.springframework.security.oauth2.common.DefaultOAuth2RefreshToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; @@ -51,9 +52,35 @@ public void testEnhanceAccessToken() { userAuthentication); OAuth2AccessToken token = tokenEnhancer.enhance(new DefaultOAuth2AccessToken("FOO"), authentication); assertNotNull(token.getValue()); - assertEquals("FOO", token.getAdditionalInformation().get(JwtTokenEnhancer.TOKEN_ID)); + assertEquals("FOO", token.getAdditionalInformation().get(AccessTokenConverter.JTI)); String claims = JwtHelper.decode(token.getValue()).getClaims(); - assertTrue("Wrong claims: " + claims, claims.contains("\"" + JwtTokenEnhancer.TOKEN_ID + "\"")); + assertTrue("Wrong claims: " + claims, claims.contains("\"" + AccessTokenConverter.JTI + "\"")); + assertTrue("Wrong claims: " + claims, claims.contains("\"" + UserAuthenticationConverter.USERNAME + "\"")); + } + + @Test + public void testScopePreserved() { + OAuth2Authentication authentication = new OAuth2Authentication(createOAuth2Request("foo", Collections.singleton("read")), + userAuthentication); + DefaultOAuth2AccessToken original = new DefaultOAuth2AccessToken("FOO"); + original.setScope(authentication.getOAuth2Request().getScope()); + OAuth2AccessToken token = tokenEnhancer.enhance(original, authentication); + assertNotNull(token.getValue()); + assertEquals(Collections.singleton("read"), token.getScope()); + } + + @Test + public void testRefreshTokenAdded() { + OAuth2Authentication authentication = new OAuth2Authentication(createOAuth2Request("foo", Collections.singleton("read")), + userAuthentication); + DefaultOAuth2AccessToken original = new DefaultOAuth2AccessToken("FOO"); + original.setScope(authentication.getOAuth2Request().getScope()); + original.setRefreshToken(new DefaultOAuth2RefreshToken("BAR")); + OAuth2AccessToken token = tokenEnhancer.enhance(original, authentication); + assertNotNull(token.getValue()); + assertNotNull(token.getRefreshToken()); + String claims = JwtHelper.decode(token.getRefreshToken().getValue()).getClaims(); + assertTrue("Wrong claims: " + claims, claims.contains("\"" + AccessTokenConverter.SCOPE + "\"")); } @Test From c0961fd84bcf895cf00e8e03daf131bd326cd3d7 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 9 Apr 2014 17:01:11 +0100 Subject: [PATCH 221/831] Integrate ApprovalStore with JwtTokenStore Implemented remove*() methods as an operation on the ApprovalStore. So for user tokens at least you will not be able to automatically get an access token without explicit approval once those methods have been called. See gh-182 --- .../sparklr/config/OAuth2ServerConfig.java | 2 +- .../examples/sparklr/mvc/AdminController.java | 23 +-- .../oauth2/provider/AdminEndpointsTests.java | 8 +- .../provider/approval/TokenApprovalStore.java | 6 +- .../provider/endpoint/TokenEndpoint.java | 10 +- .../provider/token/DefaultTokenServices.java | 9 -- .../provider/token/InMemoryTokenStore.java | 21 ++- .../oauth2/provider/token/JdbcTokenStore.java | 14 +- .../oauth2/provider/token/JwtTokenStore.java | 61 +++++++- .../oauth2/provider/token/TokenStore.java | 6 +- .../provider/token/JwtTokenStoreTests.java | 137 ++++++++++++++++++ .../provider/token/TokenStoreBaseTests.java | 2 +- 12 files changed, 249 insertions(+), 50 deletions(-) create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenStoreTests.java diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java index cfa5ec03d..643494c3e 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java @@ -91,7 +91,7 @@ public void configure(HttpSecurity http) throws Exception { .antMatchers("/photos/**").access("#oauth2.hasScope('read')") .regexMatchers(HttpMethod.DELETE, "/oauth/users/([^/].*?)/tokens/.*") .access("#oauth2.clientHasRole('ROLE_CLIENT') and (hasRole('ROLE_USER') or #oauth2.isClient()) and #oauth2.hasScope('write')") - .regexMatchers(HttpMethod.GET, "/oauth/users/.*") + .regexMatchers(HttpMethod.GET, "/oauth/clients/([^/].*?)/users/.*") .access("#oauth2.clientHasRole('ROLE_CLIENT') and (hasRole('ROLE_USER') or #oauth2.isClient()) and #oauth2.hasScope('read')") .regexMatchers(HttpMethod.GET, "/oauth/clients/.*") .access("#oauth2.clientHasRole('ROLE_CLIENT') and #oauth2.isClient() and #oauth2.hasScope('read')"); diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AdminController.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AdminController.java index e0dfca049..215b29653 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AdminController.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/AdminController.java @@ -31,7 +31,7 @@ public class AdminController { private ConsumerTokenServices tokenServices; - + private TokenStore tokenStore; private SparklrUserApprovalHandler userApprovalHandler; @@ -48,12 +48,12 @@ public void stopCaching() throws Exception { userApprovalHandler.setUseApprovalStore(false); } - @RequestMapping("/oauth/users/{user}/tokens") + @RequestMapping("/oauth/clients/{client}/users/{user}/tokens") @ResponseBody - public Collection listTokensForUser(@PathVariable String user, Principal principal) - throws Exception { + public Collection listTokensForUser(@PathVariable String client, @PathVariable String user, + Principal principal) throws Exception { checkResourceOwner(user, principal); - return enhance(tokenStore.findTokensByUserName(user)); + return enhance(tokenStore.findTokensByClientIdAndUserName(client, user)); } @RequestMapping(value = "/oauth/users/{user}/tokens/{token}", method = RequestMethod.DELETE) @@ -62,8 +62,9 @@ public ResponseEntity revokeToken(@PathVariable String user, @PathVariable checkResourceOwner(user, principal); if (tokenServices.revokeToken(token)) { return new ResponseEntity(HttpStatus.NO_CONTENT); - } else { - return new ResponseEntity(HttpStatus.NOT_FOUND); + } + else { + return new ResponseEntity(HttpStatus.NOT_FOUND); } } @@ -77,7 +78,11 @@ private Collection enhance(Collection toke Collection result = new ArrayList(); for (OAuth2AccessToken prototype : tokens) { DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(prototype); - String clientId = tokenStore.readAuthentication(token).getOAuth2Request().getClientId(); + OAuth2Authentication authentication = tokenStore.readAuthentication(token); + if (authentication == null) { + continue; + } + String clientId = authentication.getOAuth2Request().getClientId(); if (clientId != null) { Map map = new HashMap(token.getAdditionalInformation()); map.put("client_id", clientId); @@ -111,7 +116,7 @@ public void setUserApprovalHandler(SparklrUserApprovalHandler userApprovalHandle public void setTokenServices(ConsumerTokenServices tokenServices) { this.tokenServices = tokenServices; } - + /** * @param tokenStore the tokenStore to set */ diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/AdminEndpointsTests.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/AdminEndpointsTests.java index cb5045658..e2896c9fa 100644 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/AdminEndpointsTests.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/AdminEndpointsTests.java @@ -38,7 +38,7 @@ public class AdminEndpointsTests { @Test @OAuth2ContextConfiguration(ResourceOwnerReadOnly.class) public void testListTokensByUser() throws Exception { - ResponseEntity result = serverRunning.getForString("/sparklr2/oauth/users/marissa/tokens"); + ResponseEntity result = serverRunning.getForString("/sparklr2/oauth/clients/my-trusted-client/users/marissa/tokens"); assertEquals(HttpStatus.OK, result.getStatusCode()); // System.err.println(result.getBody()); assertTrue(result.getBody().contains(context.getAccessToken().getValue())); @@ -66,7 +66,7 @@ public void testRevokeTokenByUser() throws Exception { // the failure will be detected and a new access token will be obtained. The new access token // only has "write" scope and the requested resource needs "read" scope. So, an insufficient_scope // exception should be thrown. - ResponseEntity result = serverRunning.getForString("/sparklr2/oauth/users/marissa/tokens", headers); + ResponseEntity result = serverRunning.getForString("/sparklr2/oauth/clients/my-client-with-registered-redirect/users/marissa/tokens", headers); fail("Should have thrown an exception"); assertNotNull(result); } catch (InsufficientScopeException ex) { @@ -81,7 +81,7 @@ public void testRevokeTokenByUser() throws Exception { @Test @OAuth2ContextConfiguration(ClientCredentialsReadOnly.class) public void testClientListsTokensOfUser() throws Exception { - ResponseEntity result = serverRunning.getForString("/sparklr2/oauth/users/marissa/tokens"); + ResponseEntity result = serverRunning.getForString("/sparklr2/oauth/clients/my-client-with-registered-redirect/users/marissa/tokens"); assertEquals(HttpStatus.OK, result.getStatusCode()); assertTrue(result.getBody().startsWith("[")); assertTrue(result.getBody().endsWith("]")); @@ -92,7 +92,7 @@ public void testClientListsTokensOfUser() throws Exception { @OAuth2ContextConfiguration(ResourceOwnerReadOnly.class) public void testCannotListTokensOfAnotherUser() throws Exception { try { - serverRunning.getStatusCode("/sparklr2/oauth/users/foo/tokens"); + serverRunning.getStatusCode("/sparklr2/oauth/clients/my-client-with-registered-redirect/users/foo/tokens"); fail("Should have thrown an exception"); } catch (UserDeniedAuthorizationException ex) { // assertEquals(HttpStatus.FORBIDDEN.value(), ex.getHttpErrorCode()); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenApprovalStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenApprovalStore.java index 8dd2c461c..cf1cc2e5f 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenApprovalStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenApprovalStore.java @@ -67,7 +67,7 @@ public boolean addApprovals(Collection approvals) { public boolean revokeApprovals(Collection approvals) { boolean success = true; for (Approval approval : approvals) { - Collection tokens = store.findTokensByUserName(approval.getUserId()); + Collection tokens = store.findTokensByClientIdAndUserName(approval.getClientId(), approval.getUserId()); for (OAuth2AccessToken token : tokens) { OAuth2Authentication authentication = store.readAuthentication(token); if (authentication != null @@ -88,10 +88,10 @@ public boolean revokeApprovals(Collection approvals) { @Override public Collection getApprovals(String userId, String clientId) { Collection result = new HashSet(); - Collection tokens = store.findTokensByUserName(userId); + Collection tokens = store.findTokensByClientIdAndUserName(clientId, userId); for (OAuth2AccessToken token : tokens) { OAuth2Authentication authentication = store.readAuthentication(token); - if (authentication != null && clientId.equals(authentication.getOAuth2Request().getClientId())) { + if (authentication != null) { Date expiresAt = token.getExpiration(); for (String scope : token.getScope()) { result.add(new Approval(userId, clientId, scope, expiresAt, ApprovalStatus.APPROVED)); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java index 2728c5a32..7e1c6132a 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java @@ -88,9 +88,9 @@ public ResponseEntity getAccessToken(Principal principal, @Re // authenticated client throw new InvalidClientException("Given client ID does not match authenticated client"); } - if (authenticatedClient != null) { - oauth2RequestValidator.validateScope(tokenRequest, authenticatedClient); - } + } + if (authenticatedClient != null) { + oauth2RequestValidator.validateScope(tokenRequest, authenticatedClient); } if (!StringUtils.hasText(tokenRequest.getGrantType())) { throw new InvalidRequestException("Missing grant type"); @@ -99,10 +99,10 @@ public ResponseEntity getAccessToken(Principal principal, @Re throw new InvalidGrantException("Implicit grant type not supported from token endpoint"); } - if (isAuthCodeRequest(parameters) || isRefreshTokenRequest(parameters)) { + if (isAuthCodeRequest(parameters)) { // The scope was requested or determined during the authorization step if (!tokenRequest.getScope().isEmpty()) { - logger.debug("Clearing scope of incoming auth code request"); + logger.debug("Clearing scope of incoming token request"); tokenRequest.setScope(Collections. emptySet()); } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java index 7e87bd8ad..500b36aea 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java @@ -13,7 +13,6 @@ package org.springframework.security.oauth2.provider.token; -import java.util.Collection; import java.util.Date; import java.util.Set; import java.util.UUID; @@ -229,14 +228,6 @@ public String getClientId(String tokenValue) { return clientAuth.getClientId(); } - public Collection findTokensByUserName(String userName) { - return tokenStore.findTokensByUserName(userName); - } - - public Collection findTokensByClientId(String clientId) { - return tokenStore.findTokensByClientId(clientId); - } - public boolean revokeToken(String tokenValue) { OAuth2AccessToken accessToken = tokenStore.readAccessToken(tokenValue); if (accessToken == null) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStore.java index c278ee9f9..f7f794870 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStore.java @@ -78,7 +78,6 @@ public int getFlushInterval() { public void clear() { accessTokenStore.clear(); authenticationToAccessTokenStore.clear(); - userNameToAccessTokenStore.clear(); clientIdToAccessTokenStore.clear(); refreshTokenStore.clear(); accessTokenToRefreshTokenStore.clear(); @@ -148,7 +147,7 @@ public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authe this.authenticationStore.put(token.getValue(), authentication); this.authenticationToAccessTokenStore.put(authenticationKeyGenerator.extractKey(authentication), token); if (!authentication.isClientOnly()) { - addToCollection(this.userNameToAccessTokenStore, authentication.getName(), token); + addToCollection(this.userNameToAccessTokenStore, getApprovalKey(authentication), token); } addToCollection(this.clientIdToAccessTokenStore, authentication.getOAuth2Request().getClientId(), token); if (token.getExpiration() != null) { @@ -163,6 +162,16 @@ public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authe } } + private String getApprovalKey(OAuth2Authentication authentication) { + String userName = authentication.getUserAuthentication() == null ? "" : authentication.getUserAuthentication() + .getName(); + return getApprovalKey(authentication.getOAuth2Request().getClientId(), userName); + } + + private String getApprovalKey(String clientId, String userName) { + return clientId + (userName==null ? "" : ":" + userName); + } + private void addToCollection(ConcurrentHashMap> store, String key, OAuth2AccessToken token) { if (!store.containsKey(key)) { @@ -237,14 +246,14 @@ private void removeAccessTokenUsingRefreshToken(String refreshToken) { } } - public Collection findTokensByClientId(String clientId) { - Collection result = clientIdToAccessTokenStore.get(clientId); + public Collection findTokensByClientIdAndUserName(String clientId, String userName) { + Collection result = userNameToAccessTokenStore.get(getApprovalKey(clientId, userName)); return result != null ? Collections. unmodifiableCollection(result) : Collections . emptySet(); } - public Collection findTokensByUserName(String userName) { - Collection result = userNameToAccessTokenStore.get(userName); + public Collection findTokensByClientId(String clientId) { + Collection result = clientIdToAccessTokenStore.get(clientId); return result != null ? Collections. unmodifiableCollection(result) : Collections . emptySet(); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JdbcTokenStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JdbcTokenStore.java index e070c8522..ea897d117 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JdbcTokenStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JdbcTokenStore.java @@ -44,7 +44,7 @@ public class JdbcTokenStore implements TokenStore { private static final String DEFAULT_ACCESS_TOKEN_FROM_AUTHENTICATION_SELECT_STATEMENT = "select token_id, token from oauth_access_token where authentication_id = ?"; - private static final String DEFAULT_ACCESS_TOKENS_FROM_USERNAME_SELECT_STATEMENT = "select token_id, token from oauth_access_token where user_name = ?"; + private static final String DEFAULT_ACCESS_TOKENS_FROM_USERNAME_AND_CLIENT_SELECT_STATEMENT = "select token_id, token from oauth_access_token where user_name = ? and client_id = ?"; private static final String DEFAULT_ACCESS_TOKENS_FROM_CLIENTID_SELECT_STATEMENT = "select token_id, token from oauth_access_token where client_id = ?"; @@ -68,7 +68,7 @@ public class JdbcTokenStore implements TokenStore { private String selectAccessTokenFromAuthenticationSql = DEFAULT_ACCESS_TOKEN_FROM_AUTHENTICATION_SELECT_STATEMENT; - private String selectAccessTokensFromUserNameSql = DEFAULT_ACCESS_TOKENS_FROM_USERNAME_SELECT_STATEMENT; + private String selectAccessTokensFromUserNameAndClientIdSql = DEFAULT_ACCESS_TOKENS_FROM_USERNAME_AND_CLIENT_SELECT_STATEMENT; private String selectAccessTokensFromClientIdSql = DEFAULT_ACCESS_TOKENS_FROM_CLIENTID_SELECT_STATEMENT; @@ -297,12 +297,12 @@ public Collection findTokensByClientId(String clientId) { return accessTokens; } - public Collection findTokensByUserName(String userName) { + public Collection findTokensByClientIdAndUserName(String clientId, String userName) { List accessTokens = new ArrayList(); try { - accessTokens = jdbcTemplate.query(selectAccessTokensFromUserNameSql, new SafeAccessTokenRowMapper(), - userName); + accessTokens = jdbcTemplate.query(selectAccessTokensFromUserNameAndClientIdSql, new SafeAccessTokenRowMapper(), + userName, clientId); } catch (EmptyResultDataAccessException e) { if (LOG.isInfoEnabled()) { @@ -422,8 +422,8 @@ public void setDeleteAccessTokenFromRefreshTokenSql(String deleteAccessTokenFrom this.deleteAccessTokenFromRefreshTokenSql = deleteAccessTokenFromRefreshTokenSql; } - public void setSelectAccessTokensFromUserNameSql(String selectAccessTokensFromUserNameSql) { - this.selectAccessTokensFromUserNameSql = selectAccessTokensFromUserNameSql; + public void setSelectAccessTokensFromUserNameAndClientIdSql(String selectAccessTokensFromUserNameAndClientIdSql) { + this.selectAccessTokensFromUserNameAndClientIdSql = selectAccessTokensFromUserNameAndClientIdSql; } public void setSelectAccessTokensFromClientIdSql(String selectAccessTokensFromClientIdSql) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenStore.java index af64aac62..fa8b8042f 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenStore.java @@ -13,31 +13,56 @@ package org.springframework.security.oauth2.provider.token; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.Date; +import java.util.UUID; +import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.common.DefaultExpiringOAuth2RefreshToken; +import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken; 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.approval.Approval; +import org.springframework.security.oauth2.provider.approval.Approval.ApprovalStatus; +import org.springframework.security.oauth2.provider.approval.ApprovalStore; /** + * A {@link TokenStore} implementation that just reads data from the tokens themselves. Not really a store since it + * never persists anything, and methods like {@link #getAccessToken(OAuth2Authentication)} always return null. But + * nevertheless a useful tool since it translates access tokens to and from authentications. Use this wherever a + * {@link TokenStore} is needed, but remember to use the same {@link JwtTokenEnhancer} instance (or one with the same + * verifier) as was used when the tokens were minted. + * * @author Dave Syer * */ public class JwtTokenStore implements TokenStore { private JwtTokenEnhancer jwtTokenEnhancer; + + private ApprovalStore approvalStore; /** - * Create a JwtTokenStore with this token enhancer (must be shared with the DefaultTokenServices if used). + * Create a JwtTokenStore with this token enhancer (should be shared with the DefaultTokenServices if used). * * @param jwtTokenEnhancer */ public JwtTokenStore(JwtTokenEnhancer jwtTokenEnhancer) { this.jwtTokenEnhancer = jwtTokenEnhancer; } + + /** + * ApprovalStore to be used to validate and restrict refresh tokens. + * + * @param approvalStore the approvalStore to set + */ + public void setApprovalStore(ApprovalStore approvalStore) { + this.approvalStore = approvalStore; + } @Override public OAuth2Authentication readAuthentication(OAuth2AccessToken token) { @@ -60,6 +85,18 @@ public OAuth2AccessToken readAccessToken(String tokenValue) { @Override public void removeAccessToken(OAuth2AccessToken token) { + if (approvalStore!=null) { + OAuth2Authentication auth = readAuthentication(token); + String clientId = auth.getOAuth2Request().getClientId(); + Authentication user = auth.getUserAuthentication(); + if (user!=null) { + Collection approvals = new ArrayList(); + for (String scope : auth.getOAuth2Request().getScope()) { + approvals.add(new Approval(user.getName(), clientId, scope, new Date(), ApprovalStatus.APPROVED)); + } + approvalStore.revokeApprovals(approvals); + } + } } @Override @@ -81,19 +118,23 @@ public OAuth2Authentication readAuthenticationForRefreshToken(OAuth2RefreshToken @Override public void removeRefreshToken(OAuth2RefreshToken token) { + remove(token.getValue()); } @Override public void removeAccessTokenUsingRefreshToken(OAuth2RefreshToken refreshToken) { + removeRefreshToken(refreshToken); } @Override public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) { - return null; + DefaultOAuth2AccessToken original = new DefaultOAuth2AccessToken(UUID.randomUUID().toString()); + original.setScope(authentication.getOAuth2Request().getScope()); + return jwtTokenEnhancer.enhance(original, authentication); } @Override - public Collection findTokensByUserName(String userName) { + public Collection findTokensByClientIdAndUserName(String clientId, String userName) { return Collections.emptySet(); } @@ -106,4 +147,18 @@ public void setTokenEnhancer(JwtTokenEnhancer tokenEnhancer) { this.jwtTokenEnhancer = tokenEnhancer; } + private void remove(String token) { + if (approvalStore!=null) { + OAuth2Authentication auth = readAuthentication(token); + String clientId = auth.getOAuth2Request().getClientId(); + Authentication user = auth.getUserAuthentication(); + if (user!=null) { + Collection approvals = new ArrayList(); + for (String scope : auth.getOAuth2Request().getScope()) { + approvals.add(new Approval(user.getName(), clientId, scope, new Date(), ApprovalStatus.APPROVED)); + } + approvalStore.revokeApprovals(approvals); + } + } + } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/TokenStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/TokenStore.java index 1cf08356d..bab2b9e02 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/TokenStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/TokenStore.java @@ -97,13 +97,15 @@ public interface TokenStore { OAuth2AccessToken getAccessToken(OAuth2Authentication authentication); /** + * @param clientId the client id to search * @param userName the user name to search * @return a collection of access tokens */ - Collection findTokensByUserName(String userName); + Collection findTokensByClientIdAndUserName(String clientId, String userName); /** - * @param clientId the client id + * @param userName the user name to search + * @param clientId the client id to search * @return a collection of access tokens */ Collection findTokensByClientId(String clientId); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenStoreTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenStoreTests.java new file mode 100644 index 000000000..a86268f9b --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenStoreTests.java @@ -0,0 +1,137 @@ +package org.springframework.security.oauth2.provider.token; + +import static org.junit.Assert.assertEquals; + +import java.util.Collections; +import java.util.Date; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; +import org.springframework.security.oauth2.common.DefaultOAuth2RefreshToken; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.RequestTokenFactory; +import org.springframework.security.oauth2.provider.approval.Approval; +import org.springframework.security.oauth2.provider.approval.Approval.ApprovalStatus; +import org.springframework.security.oauth2.provider.approval.InMemoryApprovalStore; + +/** + * @author Dave Syer + * + */ +public class JwtTokenStoreTests { + + private JwtTokenEnhancer enhancer = new JwtTokenEnhancer(); + + private JwtTokenStore tokenStore = new JwtTokenStore(enhancer); + + private InMemoryApprovalStore approvalStore = new InMemoryApprovalStore(); + + private OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "id", null, true, + Collections.singleton("read"), null, null, null, null); + + private OAuth2Authentication expectedAuthentication = new OAuth2Authentication(storedOAuth2Request, + new TestAuthentication("test", true)); + + private OAuth2AccessToken expectedOAuth2AccessToken; + + @Before + public void init() throws Exception { + enhancer.afterPropertiesSet(); + DefaultOAuth2AccessToken original = new DefaultOAuth2AccessToken("testToken"); + original.setScope(expectedAuthentication.getOAuth2Request().getScope()); + expectedOAuth2AccessToken = enhancer.enhance(original, expectedAuthentication); + } + + @Test + public void testScopeExtractedFromAuthentication() throws Exception { + OAuth2AccessToken accessToken = tokenStore.getAccessToken(expectedAuthentication); + assertEquals(expectedOAuth2AccessToken.getScope(), accessToken.getScope()); + } + + @Test + public void testReadAccessToken() throws Exception { + assertEquals(expectedOAuth2AccessToken, tokenStore.readAccessToken(expectedOAuth2AccessToken.getValue())); + } + + @Test + public void testReadRefreshToken() throws Exception { + assertEquals(expectedOAuth2AccessToken, tokenStore.readRefreshToken(expectedOAuth2AccessToken.getValue())); + } + + @Test + public void testReadAuthentication() throws Exception { + checkAuthentications(expectedAuthentication, tokenStore.readAuthentication(expectedOAuth2AccessToken)); + } + + @Test + public void testReadAuthenticationFromString() throws Exception { + checkAuthentications(expectedAuthentication, + tokenStore.readAuthentication(expectedOAuth2AccessToken.getValue())); + } + + @Test + public void testReadAuthenticationForRefreshToken() throws Exception { + checkAuthentications(expectedAuthentication, + tokenStore.readAuthenticationForRefreshToken(new DefaultOAuth2RefreshToken(expectedOAuth2AccessToken + .getValue()))); + } + + @Test + public void removeAccessToken() throws Exception { + tokenStore.setApprovalStore(approvalStore); + approvalStore.addApprovals(Collections.singleton(new Approval("test", "id", "read", new Date(), ApprovalStatus.APPROVED))); + assertEquals(1, approvalStore.getApprovals("test", "id").size()); + tokenStore.removeAccessToken(expectedOAuth2AccessToken); + assertEquals(0, approvalStore.getApprovals("test", "id").size()); + } + + @Test + public void removeRefreshToken() throws Exception { + tokenStore.setApprovalStore(approvalStore); + approvalStore.addApprovals(Collections.singleton(new Approval("test", "id", "read", new Date(), ApprovalStatus.APPROVED))); + assertEquals(1, approvalStore.getApprovals("test", "id").size()); + tokenStore.removeRefreshToken(new DefaultOAuth2RefreshToken(expectedOAuth2AccessToken.getValue())); + assertEquals(0, approvalStore.getApprovals("test", "id").size()); + } + + @Test + public void removeAccessTokenFromRefreshToken() throws Exception { + tokenStore.setApprovalStore(approvalStore); + approvalStore.addApprovals(Collections.singleton(new Approval("test", "id", "read", new Date(), ApprovalStatus.APPROVED))); + assertEquals(1, approvalStore.getApprovals("test", "id").size()); + tokenStore.removeAccessTokenUsingRefreshToken(new DefaultOAuth2RefreshToken(expectedOAuth2AccessToken.getValue())); + assertEquals(0, approvalStore.getApprovals("test", "id").size()); + } + + private void checkAuthentications(OAuth2Authentication expected, OAuth2Authentication actual) { + assertEquals(expected.getOAuth2Request().getScope(), actual.getOAuth2Request().getScope()); + assertEquals(expected.getOAuth2Request().getClientId(), actual.getOAuth2Request().getClientId()); + assertEquals(expected.getUserAuthentication(), actual.getUserAuthentication()); + } + + protected static class TestAuthentication extends AbstractAuthenticationToken { + + private static final long serialVersionUID = 1L; + + private String principal; + + public TestAuthentication(String name, boolean authenticated) { + super(null); + setAuthenticated(authenticated); + this.principal = name; + } + + public Object getCredentials() { + return "N/A"; + } + + public Object getPrincipal() { + return this.principal; + } + } + +} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenStoreBaseTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenStoreBaseTests.java index d0508abd3..db4d28e9e 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenStoreBaseTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenStoreBaseTests.java @@ -103,7 +103,7 @@ public void testFindAccessTokensByUserName() { OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); - Collection actualOAuth2AccessTokens = getTokenStore().findTokensByUserName("test2"); + Collection actualOAuth2AccessTokens = getTokenStore().findTokensByClientIdAndUserName("id", "test2"); assertEquals(1, actualOAuth2AccessTokens.size()); } From 0aef0a7a9144077398c4bca4328acd2fd5d5e7e8 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 9 Apr 2014 17:16:09 +0100 Subject: [PATCH 222/831] Check for approvals in JwtTokenStore before reading refresh token Fixes part of gh-182 --- .../oauth2/provider/approval/Approval.java | 5 ++++ .../oauth2/provider/token/JwtTokenStore.java | 30 +++++++++++++++---- .../provider/token/JwtTokenStoreTests.java | 8 +++++ 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/Approval.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/Approval.java index 6e838ed14..86d83743c 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/Approval.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/Approval.java @@ -126,6 +126,11 @@ public boolean isCurrentlyActive() { return expiresAt != null && expiresAt.after(new Date()); } + @JsonIgnore + public boolean isApproved() { + return isCurrentlyActive() && status==ApprovalStatus.APPROVED; + } + public void setStatus(ApprovalStatus status) { this.status = status; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenStore.java index fa8b8042f..17b71fa0d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenStore.java @@ -17,6 +17,7 @@ import java.util.Collection; import java.util.Collections; import java.util.Date; +import java.util.HashSet; import java.util.UUID; import org.springframework.security.core.Authentication; @@ -43,7 +44,7 @@ public class JwtTokenStore implements TokenStore { private JwtTokenEnhancer jwtTokenEnhancer; - + private ApprovalStore approvalStore; /** @@ -54,7 +55,7 @@ public class JwtTokenStore implements TokenStore { public JwtTokenStore(JwtTokenEnhancer jwtTokenEnhancer) { this.jwtTokenEnhancer = jwtTokenEnhancer; } - + /** * ApprovalStore to be used to validate and restrict refresh tokens. * @@ -85,11 +86,11 @@ public OAuth2AccessToken readAccessToken(String tokenValue) { @Override public void removeAccessToken(OAuth2AccessToken token) { - if (approvalStore!=null) { + if (approvalStore != null) { OAuth2Authentication auth = readAuthentication(token); String clientId = auth.getOAuth2Request().getClientId(); Authentication user = auth.getUserAuthentication(); - if (user!=null) { + if (user != null) { Collection approvals = new ArrayList(); for (String scope : auth.getOAuth2Request().getScope()) { approvals.add(new Approval(user.getName(), clientId, scope, new Date(), ApprovalStatus.APPROVED)); @@ -108,6 +109,23 @@ public OAuth2RefreshToken readRefreshToken(String tokenValue) { OAuth2AccessToken encodedRefreshToken = readAccessToken(tokenValue); ExpiringOAuth2RefreshToken refreshToken = new DefaultExpiringOAuth2RefreshToken(encodedRefreshToken.getValue(), encodedRefreshToken.getExpiration()); + if (approvalStore != null) { + OAuth2Authentication authentication = readAuthentication(tokenValue); + if (authentication.getUserAuthentication() != null) { + String userId = authentication.getUserAuthentication().getName(); + String clientId = authentication.getOAuth2Request().getClientId(); + Collection approvals = approvalStore.getApprovals(userId, clientId); + Collection approvedScopes = new HashSet(); + for (Approval approval : approvals) { + if (approval.isApproved()) { + approvedScopes.add(approval.getScope()); + } + } + if (!approvedScopes.containsAll(authentication.getOAuth2Request().getScope())) { + return null; + } + } + } return refreshToken; } @@ -148,11 +166,11 @@ public void setTokenEnhancer(JwtTokenEnhancer tokenEnhancer) { } private void remove(String token) { - if (approvalStore!=null) { + if (approvalStore != null) { OAuth2Authentication auth = readAuthentication(token); String clientId = auth.getOAuth2Request().getClientId(); Authentication user = auth.getUserAuthentication(); - if (user!=null) { + if (user != null) { Collection approvals = new ArrayList(); for (String scope : auth.getOAuth2Request().getScope()) { approvals.add(new Approval(user.getName(), clientId, scope, new Date(), ApprovalStatus.APPROVED)); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenStoreTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenStoreTests.java index a86268f9b..4b7040ee0 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenStoreTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenStoreTests.java @@ -107,6 +107,14 @@ public void removeAccessTokenFromRefreshToken() throws Exception { assertEquals(0, approvalStore.getApprovals("test", "id").size()); } + @Test + public void testReadRefreshTokenForUnapprovedScope() throws Exception { + tokenStore.setApprovalStore(approvalStore); + approvalStore.addApprovals(Collections.singleton(new Approval("test", "id", "write", new Date(), ApprovalStatus.APPROVED))); + assertEquals(1, approvalStore.getApprovals("test", "id").size()); + assertEquals(null, tokenStore.readRefreshToken(expectedOAuth2AccessToken.getValue())); + } + private void checkAuthentications(OAuth2Authentication expected, OAuth2Authentication actual) { assertEquals(expected.getOAuth2Request().getScope(), actual.getOAuth2Request().getScope()); assertEquals(expected.getOAuth2Request().getClientId(), actual.getOAuth2Request().getClientId()); From c13ef0cebadb476511514211c6d13a7e532af940 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 10 Apr 2014 11:20:12 +0100 Subject: [PATCH 223/831] OAuth2ResourceServerConfigurer -> ResourceServerSecurityConfigurer --- .../examples/sparklr/config/OAuth2ServerConfig.java | 4 ++-- .../web/configuration/ResourceServerConfiguration.java | 4 ++-- .../web/configuration/ResourceServerConfigurer.java | 4 ++-- .../configuration/ResourceServerConfigurerAdapter.java | 4 ++-- ...urer.java => ResourceServerSecurityConfigurer.java} | 10 +++++----- .../provider/approval/InMemoryApprovalStore.java | 4 ++++ .../annotation/ResourceServerConfigurationTests.java | 4 ++-- 7 files changed, 19 insertions(+), 15 deletions(-) rename spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/{OAuth2ResourceServerConfigurer.java => ResourceServerSecurityConfigurer.java} (94%) diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java index 643494c3e..66a50d31d 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java @@ -32,7 +32,7 @@ import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; -import org.springframework.security.oauth2.config.annotation.web.configurers.OAuth2ResourceServerConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; import org.springframework.security.oauth2.provider.approval.ApprovalStore; @@ -73,7 +73,7 @@ protected void configure(HttpSecurity http) throws Exception { protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { @Override - public void configure(OAuth2ResourceServerConfigurer resources) { + public void configure(ResourceServerSecurityConfigurer resources) { resources.resourceId(SPARKLR_RESOURCE_ID); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java index 833892fc8..4c4079588 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java @@ -26,7 +26,7 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity.RequestMatcherConfigurer; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.oauth2.config.annotation.web.configurers.OAuth2ResourceServerConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; import org.springframework.security.oauth2.provider.endpoint.FrameworkEndpointHandlerMapping; import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler; @@ -116,7 +116,7 @@ protected void configure(HttpSecurity http) throws Exception { } // And set the default expression handler in case one isn't explicit elsewhere http.authorizeRequests().expressionHandler(new OAuth2WebSecurityExpressionHandler()); - OAuth2ResourceServerConfigurer resources = new OAuth2ResourceServerConfigurer(); + ResourceServerSecurityConfigurer resources = new ResourceServerSecurityConfigurer(); http.apply(resources); for (ResourceServerConfigurer configurer : configurers) { configurer.configure(resources); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurer.java index b345a0133..bc4ee118d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurer.java @@ -15,7 +15,7 @@ import org.springframework.core.annotation.Order; import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.oauth2.config.annotation.web.configurers.OAuth2ResourceServerConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler; /** @@ -35,7 +35,7 @@ public interface ResourceServerConfigurer { * @param resources configurer for the resource server * @throws Exception if there is a problem */ - void configure(OAuth2ResourceServerConfigurer resources) throws Exception; + void configure(ResourceServerSecurityConfigurer resources) throws Exception; /** * Use this to configure the access rules for secure resources. By default all resources not in "/oauth/**" diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurerAdapter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurerAdapter.java index 7689bb2de..6de516caa 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurerAdapter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurerAdapter.java @@ -13,7 +13,7 @@ package org.springframework.security.oauth2.config.annotation.web.configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.oauth2.config.annotation.web.configurers.OAuth2ResourceServerConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; /** * @author Dave Syer @@ -22,7 +22,7 @@ public class ResourceServerConfigurerAdapter implements ResourceServerConfigurer { @Override - public void configure(OAuth2ResourceServerConfigurer resources) throws Exception { + public void configure(ResourceServerSecurityConfigurer resources) throws Exception { } @Override diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2ResourceServerConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java similarity index 94% rename from spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2ResourceServerConfigurer.java rename to spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java index cd7a3cb06..d84e5e5c5 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/OAuth2ResourceServerConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java @@ -48,7 +48,7 @@ * @author Rob Winch * @since 3.2 */ -public final class OAuth2ResourceServerConfigurer extends +public final class ResourceServerSecurityConfigurer extends SecurityConfigurerAdapter { private AuthenticationEntryPoint authenticationEntryPoint = new OAuth2AuthenticationEntryPoint(); @@ -75,19 +75,19 @@ public TokenStore getTokenStore() { return tokenStore; } - public OAuth2ResourceServerConfigurer tokenStore(TokenStore tokenStore) { + public ResourceServerSecurityConfigurer tokenStore(TokenStore tokenStore) { Assert.state(tokenStore != null, "TokenStore cannot be null"); this.tokenStore = tokenStore; return this; } - public OAuth2ResourceServerConfigurer authenticationManager(AuthenticationManager authenticationManager) { + public ResourceServerSecurityConfigurer authenticationManager(AuthenticationManager authenticationManager) { Assert.state(authenticationManager != null, "AuthenticationManager cannot be null"); this.authenticationManager = authenticationManager; return this; } - public OAuth2ResourceServerConfigurer tokenServices(ResourceServerTokenServices tokenServices) { + public ResourceServerSecurityConfigurer tokenServices(ResourceServerTokenServices tokenServices) { Assert.state(tokenServices != null, "ResourceServerTokenServices cannot be null"); this.resourceTokenServices = tokenServices; return this; @@ -118,7 +118,7 @@ private void registerDefaultAuthenticationEntryPoint(HttpSecurity http) { exceptionHandling.defaultAuthenticationEntryPointFor(postProcess(authenticationEntryPoint), preferredMatcher); } - public OAuth2ResourceServerConfigurer resourceId(String resourceId) { + public ResourceServerSecurityConfigurer resourceId(String resourceId) { this.resourceId = resourceId; return this; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/InMemoryApprovalStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/InMemoryApprovalStore.java index b6d7c3c7e..ef7e69009 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/InMemoryApprovalStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/InMemoryApprovalStore.java @@ -67,6 +67,10 @@ public Collection getApprovals(String userId, String clientId) { approval.setClientId(clientId); return Collections.unmodifiableCollection(getApprovals(approval)); } + + public void clear() { + map.clear(); + } private static class Key { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java index a0ba4610a..a37059866 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java @@ -24,7 +24,7 @@ import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.config.annotation.web.configurers.OAuth2ResourceServerConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.TokenRequest; @@ -94,7 +94,7 @@ protected void configure(HttpSecurity http) throws Exception { .and() .exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler()) .and() - .apply(new OAuth2ResourceServerConfigurer()) + .apply(new ResourceServerSecurityConfigurer()) .tokenStore(tokenStore); // @formatter:on } From cca365ff8a0843291e6683caa76d3e52f611799f Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 10 Apr 2014 11:20:19 +0100 Subject: [PATCH 224/831] Remove some features from JwtTokenStore In particular it doesn't make sense for a JWT "store" to pretend it can get an access token from an authentication (it will never know whether there was a refresh token, or if the token had been enhanced in various ways). --- .../security/oauth2/provider/token/JwtTokenStore.java | 7 ++----- .../security/oauth2/provider/token/JwtTokenStoreTests.java | 4 ++-- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenStore.java index 17b71fa0d..a98d884fd 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenStore.java @@ -18,11 +18,9 @@ import java.util.Collections; import java.util.Date; import java.util.HashSet; -import java.util.UUID; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.common.DefaultExpiringOAuth2RefreshToken; -import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2RefreshToken; @@ -146,9 +144,8 @@ public void removeAccessTokenUsingRefreshToken(OAuth2RefreshToken refreshToken) @Override public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) { - DefaultOAuth2AccessToken original = new DefaultOAuth2AccessToken(UUID.randomUUID().toString()); - original.setScope(authentication.getOAuth2Request().getScope()); - return jwtTokenEnhancer.enhance(original, authentication); + // We don't want to accidentally issue a token, and we have no way to reconstruct the refresh token + return null; } @Override diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenStoreTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenStoreTests.java index 4b7040ee0..c7bd55361 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenStoreTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenStoreTests.java @@ -47,9 +47,9 @@ public void init() throws Exception { } @Test - public void testScopeExtractedFromAuthentication() throws Exception { + public void testAccessTokenCannotBeExtractedFromAuthentication() throws Exception { OAuth2AccessToken accessToken = tokenStore.getAccessToken(expectedAuthentication); - assertEquals(expectedOAuth2AccessToken.getScope(), accessToken.getScope()); + assertEquals(null, accessToken); } @Test From 01ab27ef2f863a4e09e58596260d61619e887c78 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 10 Apr 2014 14:00:28 +0100 Subject: [PATCH 225/831] Ensure framework mappings work with forward and redirect --- ...thorizationServerBeanDefinitionParser.java | 3 + .../FrameworkEndpointHandlerMapping.java | 22 +++++++- .../FrameworkEndpointHandlerMappingTests.java | 56 +++++++++++++++++++ 3 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMappingTests.java 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 5ab2595ab..a9563985c 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 @@ -276,6 +276,9 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P if (StringUtils.hasText(authorizationEndpointUrl)) { mappings.put("/oauth/authorize", new TypedStringValue(authorizationEndpointUrl,String.class)); } + if (StringUtils.hasText(approvalPage)) { + mappings.put("/oauth/confirm_access", new TypedStringValue(approvalPage,String.class)); + } handlerMappingBean.addPropertyValue("mappings", mappings); } if (StringUtils.hasText(approvalParameter) && registerAuthorizationEndpoint) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java index 3227b4067..ccae70d93 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java @@ -28,6 +28,7 @@ import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition; import org.springframework.web.servlet.mvc.method.RequestMappingInfo; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; +import org.springframework.web.servlet.view.UrlBasedViewResolver; /** * A handler mapping for framework endpoints (those annotated with @FrameworkEndpoint). @@ -37,6 +38,10 @@ */ public class FrameworkEndpointHandlerMapping extends RequestMappingHandlerMapping { + private static final String REDIRECT = UrlBasedViewResolver.REDIRECT_URL_PREFIX; + + private static final String FORWARD = UrlBasedViewResolver.FORWARD_URL_PREFIX; + private Map mappings = new HashMap(); private String approvalParameter = OAuth2Utils.USER_OAUTH_APPROVAL; @@ -50,17 +55,28 @@ public class FrameworkEndpointHandlerMapping extends RequestMappingHandlerMappin * @param mappings the mappings to set */ public void setMappings(Map patternMap) { - this.mappings = patternMap; + this.mappings = new HashMap(patternMap); + for (String key : mappings.keySet()) { + String result = mappings.get(key); + if (result.startsWith(FORWARD)) { + result = result.substring(FORWARD.length()); + } + if (result.startsWith(REDIRECT)) { + result = result.substring(REDIRECT.length()); + } + mappings.put(key, result); + } } /** * @return the mapping from default endpoint paths to custom ones (or the default if no customization is known) */ public String getPath(String defaultPath) { + String result = defaultPath; if (mappings.containsKey(defaultPath)) { - return mappings.get(defaultPath); + result = mappings.get(defaultPath); } - return defaultPath; + return result; } public Set getPaths() { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMappingTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMappingTests.java new file mode 100644 index 000000000..e3b89090c --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMappingTests.java @@ -0,0 +1,56 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.springframework.security.oauth2.provider.endpoint; + +import static org.junit.Assert.assertEquals; + +import java.util.Collections; + +import org.junit.Test; + +/** + * @author Dave Syer + * + */ +public class FrameworkEndpointHandlerMappingTests { + + private FrameworkEndpointHandlerMapping mapping = new FrameworkEndpointHandlerMapping(); + + @Test + public void defaults() throws Exception { + assertEquals("/oauth/token", mapping.getPath("/oauth/token")); + assertEquals("/oauth/authorize", mapping.getPath("/oauth/authorize")); + assertEquals("/oauth/error", mapping.getPath("/oauth/error")); + assertEquals("/oauth/confirm_access", mapping.getPath("/oauth/confirm_access")); + } + + @Test + public void mappings() throws Exception { + mapping.setMappings(Collections.singletonMap("/oauth/token", "/token")); + assertEquals("/token", mapping.getPath("/oauth/token")); + } + + @Test + public void forward() throws Exception { + mapping.setMappings(Collections.singletonMap("/oauth/confirm_access", "forward:/approve")); + assertEquals("/approve", mapping.getPath("/oauth/confirm_access")); + } + + @Test + public void redirect() throws Exception { + mapping.setMappings(Collections.singletonMap("/oauth/confirm_access", "redirect:/approve")); + assertEquals("/approve", mapping.getPath("/oauth/confirm_access")); + } + +} From 28aec63a7cbb6f0be6f823fd43e96d3140ba3bdc Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 10 Apr 2014 15:05:17 +0100 Subject: [PATCH 226/831] Add tests deomstrating use of TokenConverter To get a JWT token which is invertible you need to share the JwtTokenEnhancer with the Resource Server. That means in order to enhance the token further you need a chain of converters ending with the JwtTokenEnhancer and/or an AccessTokenConverter inside the JwtTokenEnhancer. See gh-183 --- .../oauth2/provider/RequestTokenFactory.java | 13 +- .../OAuth2AuthenticationManagerTests.java | 2 +- .../TokenServicesWithTokenEnhancerTests.java | 138 ++++++++++++++++++ 3 files changed, 150 insertions(+), 3 deletions(-) create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenServicesWithTokenEnhancerTests.java diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/RequestTokenFactory.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/RequestTokenFactory.java index 9ac364234..2c6eb2979 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/RequestTokenFactory.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/RequestTokenFactory.java @@ -15,6 +15,7 @@ import java.io.Serializable; import java.util.Collection; +import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -29,10 +30,18 @@ public class RequestTokenFactory { public static OAuth2Request createOAuth2Request(Map requestParameters, String clientId, - Collection authorities, boolean approved, Set scope, + Collection authorities, boolean approved, Collection scope, Set resourceIds, String redirectUri, Set responseTypes, Map extensionProperties) { - return new OAuth2Request(requestParameters, clientId, authorities, approved, scope, resourceIds, redirectUri, + return new OAuth2Request(requestParameters, clientId, authorities, approved, new HashSet(scope), resourceIds, redirectUri, responseTypes, extensionProperties); } + public static OAuth2Request createOAuth2Request(String clientId, boolean approved) { + return createOAuth2Request(clientId, approved, null); + } + + public static OAuth2Request createOAuth2Request(String clientId, boolean approved, Collection scope) { + return createOAuth2Request(null, clientId, null, approved, scope, null, null, null, null); + } + } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManagerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManagerTests.java index 0e56ed5b7..9cafecbd8 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManagerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManagerTests.java @@ -37,7 +37,7 @@ public class OAuth2AuthenticationManagerTests { private Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala"); - private OAuth2Authentication authentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "foo", null, false, null, null, null, null, null), userAuthentication); + private OAuth2Authentication authentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request("foo", false), userAuthentication); { manager.setTokenServices(tokenServices); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenServicesWithTokenEnhancerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenServicesWithTokenEnhancerTests.java new file mode 100644 index 000000000..fed14c28d --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenServicesWithTokenEnhancerTests.java @@ -0,0 +1,138 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.springframework.security.oauth2.provider.token; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.config.annotation.builders.InMemoryClientDetailsServiceBuilder; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.RequestTokenFactory; + +/** + * @author Dave Syer + * + */ +public class TokenServicesWithTokenEnhancerTests { + + private DefaultTokenServices tokenServices = new DefaultTokenServices(); + + private JwtTokenEnhancer jwtTokenEnhancer = new JwtTokenEnhancer(); + + private TokenEnhancerChain enhancer = new TokenEnhancerChain(); + + private UsernamePasswordAuthenticationToken user = new UsernamePasswordAuthenticationToken("bob", "N/A", + AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); + + private OAuth2Request request = RequestTokenFactory.createOAuth2Request("client", true, Arrays.asList("read")); + + private OAuth2Authentication authentication = new OAuth2Authentication(request, user); + + @Before + public void init() throws Exception { + tokenServices.setClientDetailsService(new InMemoryClientDetailsServiceBuilder().withClient("client") + .authorizedGrantTypes("authorization_code").scopes("read").secret("secret").and().build()); + enhancer.setTokenEnhancers(Arrays. asList(jwtTokenEnhancer)); + jwtTokenEnhancer.afterPropertiesSet(); + tokenServices.setTokenStore(new JwtTokenStore(jwtTokenEnhancer)); + tokenServices.setTokenEnhancer(enhancer); + } + + @Test + public void scopePreservedWhenTokenCreated() { + assertEquals("[read]", tokenServices.createAccessToken(authentication).getScope().toString()); + tokenServices.getAccessToken(authentication); + } + + @Test + public void scopePreservedWhenTokenDecoded() { + OAuth2AccessToken token = tokenServices.createAccessToken(authentication); + assertEquals("[read]", tokenServices.loadAuthentication(token.getValue()).getOAuth2Request().getScope() + .toString()); + } + + @Test + public void customUserPreservedWhenTokenDecoded() { + DefaultAccessTokenConverter tokenConverter = new DefaultAccessTokenConverter(); + tokenConverter.setUserTokenConverter(new UserAuthenticationConverter() { + + @Override + public Authentication extractAuthentication(Map map) { + return new FooAuthentication((String) map.get("user")); + } + + @Override + public Map convertUserAuthentication(Authentication userAuthentication) { + Map map = new HashMap(); + map.put("user", userAuthentication.getName()); + map.put("foo", "bar"); + return map ; + } + }); + jwtTokenEnhancer.setAccessTokenConverter(tokenConverter); + OAuth2AccessToken token = tokenServices.createAccessToken(authentication); + assertEquals("bob", tokenServices.loadAuthentication(token.getValue()).getUserAuthentication().getName()); + } + + @Test + public void additionalInfoPreservedWhenTokenDecoded() { + TokenEnhancer info = new TokenEnhancer() { + @Override + public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { + DefaultOAuth2AccessToken result = new DefaultOAuth2AccessToken(accessToken); + result.getAdditionalInformation().put("foo", "bar"); + return result; + } + }; + enhancer.setTokenEnhancers(Arrays. asList(info , jwtTokenEnhancer)); + OAuth2AccessToken token = tokenServices.createAccessToken(authentication); + assertEquals("bar", token.getAdditionalInformation().get("foo")); + assertEquals("bar", tokenServices.readAccessToken(token.getValue()).getAdditionalInformation().get("foo")); + } + + @SuppressWarnings("serial") + protected static class FooAuthentication extends AbstractAuthenticationToken { + + private String name; + + public FooAuthentication(String name) { + super(AuthorityUtils.commaSeparatedStringToAuthorityList("USER")); + this.name = name; + } + + @Override + public Object getCredentials() { + return "N/A"; + } + + @Override + public Object getPrincipal() { + return name; + } + + } + +} From 592c00c65998b0538b3690b5823695ac94459364 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 10 Apr 2014 17:08:03 +0100 Subject: [PATCH 227/831] Fix null bug in RequestTokenFactory --- .../security/oauth2/provider/RequestTokenFactory.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/RequestTokenFactory.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/RequestTokenFactory.java index 2c6eb2979..60cbf28cb 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/RequestTokenFactory.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/RequestTokenFactory.java @@ -15,7 +15,7 @@ import java.io.Serializable; import java.util.Collection; -import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; @@ -32,7 +32,7 @@ public class RequestTokenFactory { public static OAuth2Request createOAuth2Request(Map requestParameters, String clientId, Collection authorities, boolean approved, Collection scope, Set resourceIds, String redirectUri, Set responseTypes, Map extensionProperties) { - return new OAuth2Request(requestParameters, clientId, authorities, approved, new HashSet(scope), resourceIds, redirectUri, + return new OAuth2Request(requestParameters, clientId, authorities, approved, scope==null ? null : new LinkedHashSet(scope), resourceIds, redirectUri, responseTypes, extensionProperties); } From 75f0d1c09765522b10e115ed833deccc18ac8cad Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 11 Apr 2014 17:26:40 +0100 Subject: [PATCH 228/831] Switch server IDs for AWS credentials --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index e5654dcd5..13844da4e 100644 --- a/pom.xml +++ b/pom.xml @@ -118,7 +118,7 @@ milestone - spring-milestone + springframework-milestone Spring Milestone Repository s3://maven.springframework.org/milestone @@ -346,13 +346,13 @@ - spring-release + springframework-release Spring Release Repository s3://maven.springframework.org/release - spring-snapshot + springframework-snapshot Spring Snapshot Repository s3://maven.springframework.org/snapshot From 156e1f117e8ac2dfbb473e15569fb8e2019ef9c3 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 14 Apr 2014 19:33:00 -0700 Subject: [PATCH 229/831] Update repository metadata --- pom.xml | 9 ++++----- spring-security-jwt/pom.xml | 11 +++++------ 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/pom.xml b/pom.xml index 13844da4e..a2349ce7c 100644 --- a/pom.xml +++ b/pom.xml @@ -95,18 +95,17 @@ spring-milestone Spring Framework Milestone Repository - http://s3.amazonaws.com/maven.springframework.org/milestone + http://repo.spring.io/milestone spring-release Spring Framework Release Repository - http://maven.springframework.org/release + http://repo.spring.io/release - - repository.springframework.maven.snapshot + spring-snapshot Spring Framework Maven Release Repository - http://maven.springframework.org/snapshot + http://repo.spring.io/snapshot oauth.googlecode.net diff --git a/spring-security-jwt/pom.xml b/spring-security-jwt/pom.xml index 525c8d6db..308e53a73 100755 --- a/spring-security-jwt/pom.xml +++ b/spring-security-jwt/pom.xml @@ -38,7 +38,6 @@ 1.47 - junit junit @@ -83,9 +82,9 @@ - org.springframework.build.aws - org.springframework.build.aws.maven - 3.0.0.RELEASE + org.springframework.build + aws-maven + 5.0.0.RELEASE @@ -135,13 +134,13 @@ - spring-release + springframework-release Spring Release Repository s3://maven.springframework.org/release - spring-snapshot + springframework-snapshot Spring Snapshot Repository s3://maven.springframework.org/snapshot From 16bee3613275737ae459a858d775c5865424c912 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 10 Apr 2014 17:12:03 +0100 Subject: [PATCH 230/831] Remove JwtTokenServices --- .../provider/token/JwtTokenServices.java | 352 ------------------ ...AuthorizationServerConfigurationTests.java | 42 ++- .../provider/token/JwtTokenServicesTests.java | 283 -------------- 3 files changed, 34 insertions(+), 643 deletions(-) delete mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenServices.java delete mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenServicesTests.java diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenServices.java deleted file mode 100644 index c71367be8..000000000 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenServices.java +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Cloud Foundry 2012.02.03 Beta - * Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved. - * - * This product is licensed to you under the Apache License, Version 2.0 (the "License"). - * You may not use this product except in compliance with the License. - * - * This product includes a number of subcomponents with - * separate copyright notices and license terms. Your use of these - * subcomponents is subject to the terms and conditions of the - * subcomponent's license, as noted in the LICENSE file. - */ - -package org.springframework.security.oauth2.provider.token; - -import java.util.Date; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Set; - -import org.springframework.beans.factory.InitializingBean; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.oauth2.common.DefaultExpiringOAuth2RefreshToken; -import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; -import org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken; -import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.common.OAuth2RefreshToken; -import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; -import org.springframework.security.oauth2.common.exceptions.InvalidScopeException; -import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; -import org.springframework.security.oauth2.provider.ClientDetails; -import org.springframework.security.oauth2.provider.ClientDetailsService; -import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.OAuth2Request; -import org.springframework.security.oauth2.provider.TokenRequest; - -/** - * Token services for authorization server and resource server based on JWT encoded token values. There is no need for - * shared storage because all of the state is carried in the token values. - * - * @author Dave Syer - * - */ -public class JwtTokenServices implements AuthorizationServerTokenServices, ResourceServerTokenServices, - InitializingBean { - - /** - * Field name for token id. - */ - public static final String TOKEN_ID = "jti"; - - private ClientDetailsService clientDetailsService; - - private TokenEnhancer accessTokenEnhancer; - - private JwtTokenEnhancer jwtTokenEnhancer = new JwtTokenEnhancer(); - - private int refreshTokenValiditySeconds = 60 * 60 * 24 * 30; // default 30 days. - - private int accessTokenValiditySeconds = 60 * 60 * 12; // default 12 hours. - - private boolean supportRefreshToken = true; - - private boolean reuseRefreshToken = true; - - private AuthenticationKeyGenerator authenticationKeyGenerator = new DefaultAuthenticationKeyGenerator(); - - /** - * Whether to support the refresh token. - * - * @param supportRefreshToken Whether to support the refresh token. - */ - public void setSupportRefreshToken(boolean supportRefreshToken) { - this.supportRefreshToken = supportRefreshToken; - } - - /** - * Whether to reuse refresh tokens (until expired). - * - * @param reuseRefreshToken Whether to reuse refresh tokens (until expired). - */ - public void setReuseRefreshToken(boolean reuseRefreshToken) { - this.reuseRefreshToken = reuseRefreshToken; - } - - /** - * An access token enhancer that will be applied to a new token before it is issued. - * - * @param accessTokenEnhancer the access token enhancer to set - */ - public void setTokenEnhancer(TokenEnhancer accessTokenEnhancer) { - this.accessTokenEnhancer = accessTokenEnhancer; - } - - /** - * @param tokenConverter the tokenConverter to set - */ - public void setAccessTokenConverter(AccessTokenConverter tokenConverter) { - this.jwtTokenEnhancer.setAccessTokenConverter(tokenConverter); - } - - /** - * The validity (in seconds) of the refresh token. - * - * @param refreshTokenValiditySeconds The validity (in seconds) of the refresh token. - */ - public void setRefreshTokenValiditySeconds(int refreshTokenValiditySeconds) { - this.refreshTokenValiditySeconds = refreshTokenValiditySeconds; - } - - /** - * The default validity (in seconds) of the access token. Zero or negative for non-expiring tokens. If a client - * details service is set the validity period will be read from he client, defaulting to this value if not defined - * by the client. - * - * @param accessTokenValiditySeconds The validity (in seconds) of the access token. - */ - public void setAccessTokenValiditySeconds(int accessTokenValiditySeconds) { - this.accessTokenValiditySeconds = accessTokenValiditySeconds; - } - - /** - * The client details service to use for looking up clients (if necessary). Optional if the access token expiry is - * set globally via {@link #setAccessTokenValiditySeconds(int)}. - * - * @param clientDetailsService the client details service - */ - public void setClientDetailsService(ClientDetailsService clientDetailsService) { - this.clientDetailsService = clientDetailsService; - } - - /** - * The key generator that is used to extract a unique identifier for an access token. - * - * @param authenticationKeyGenerator a key generator - */ - public void setAuthenticationKeyGenerator(AuthenticationKeyGenerator authenticationKeyGenerator) { - this.authenticationKeyGenerator = authenticationKeyGenerator; - } - - /** - * The key used for verifying signatures produced by this class. This is not used but is returned from the endpoint - * to allow resource servers to obtain the key. - * - * @param key the signature verification key (typically an RSA public key) - */ - public void setVerifierKey(String key) { - jwtTokenEnhancer.setVerifierKey(key); - } - - /** - * Sets the JWT signing key. It can be either a simple MAC key or an RSA key. RSA keys should be in OpenSSH format, - * as produced by ssh-keygen. - * - * @param key the key to be used for signing JWTs. - */ - public void setSigningKey(String key) { - jwtTokenEnhancer.setSigningKey(key); - } - - public void afterPropertiesSet() throws Exception { - jwtTokenEnhancer.afterPropertiesSet(); - } - - public OAuth2Authentication loadAuthentication(String token) throws AuthenticationException { - return jwtTokenEnhancer.extractAuthentication(decode(token)); - } - - public OAuth2AccessToken readAccessToken(String token) { - return jwtTokenEnhancer.extractAccessToken(token, decode(token)); - } - - public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication) throws AuthenticationException { - DefaultOAuth2AccessToken result = new DefaultOAuth2AccessToken(getAccessToken(authentication)); - result.setRefreshToken(createRefreshToken(authentication)); - return result; - } - - public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, TokenRequest request) - throws AuthenticationException { - - if (!supportRefreshToken) { - throw new InvalidGrantException("Invalid refresh token: " + refreshTokenValue); - } - - OAuth2Authentication authentication = loadAuthentication(refreshTokenValue); - String clientId = authentication.getOAuth2Request().getClientId(); - if (clientId == null || !clientId.equals(request.getClientId())) { - throw new InvalidGrantException("Wrong client for this refresh token: " + refreshTokenValue); - } - - OAuth2AccessToken refreshTokenData = readAccessToken(refreshTokenValue); - if (isExpired(refreshTokenData)) { - throw new InvalidTokenException("Invalid refresh token (expired): " + refreshTokenValue); - } - - authentication = createRefreshedAuthentication(authentication, request.getScope()); - - OAuth2AccessToken accessToken = createAccessToken(authentication); - if (!reuseRefreshToken) { - OAuth2RefreshToken refreshToken = createRefreshToken(authentication); - DefaultOAuth2AccessToken result = new DefaultOAuth2AccessToken(accessToken); - result.setRefreshToken(refreshToken); - } - - return accessToken; - } - - public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) { - - String tokenId = authenticationKeyGenerator.extractKey(authentication); - DefaultOAuth2AccessToken result = new DefaultOAuth2AccessToken(tokenId); - - Map info = new LinkedHashMap(); - info.put(TOKEN_ID, tokenId); - result.setAdditionalInformation(info); - - int validitySeconds = getAccessTokenValiditySeconds(authentication.getOAuth2Request()); - if (validitySeconds > 0) { - result.setExpiration(new Date(System.currentTimeMillis() + (validitySeconds * 1000L))); - } - - result.setScope(authentication.getOAuth2Request().getScope()); - - if (accessTokenEnhancer != null) { - result = new DefaultOAuth2AccessToken(accessTokenEnhancer.enhance(result, authentication)); - } - - result.setValue(encode(result, authentication)); - - return result; - - } - - /** - * Utility method to check if a token is expired. - * - * @param expiringToken an access token - * @return true if it is expired - */ - protected boolean isExpired(OAuth2AccessToken expiringToken) { - return expiringToken.getExpiration() != null - && System.currentTimeMillis() > expiringToken.getExpiration().getTime(); - } - - /** - * Is a refresh token supported for this client (or the global setting if - * {@link #setClientDetailsService(ClientDetailsService) clientDetailsService} is not set. - * @param authorizationRequest the current authorization request - * @return boolean to indicate if refresh token is supported - */ - protected boolean isSupportRefreshToken(OAuth2Request authorizationRequest) { - if (clientDetailsService != null) { - ClientDetails client = clientDetailsService.loadClientByClientId(authorizationRequest.getClientId()); - return client.getAuthorizedGrantTypes().contains("refresh_token"); - } - return this.supportRefreshToken; - } - - /** - * The access token validity period in seconds - * @param authorizationRequest the current authorization request - * @return the access token validity period in seconds - */ - protected int getAccessTokenValiditySeconds(OAuth2Request authorizationRequest) { - if (clientDetailsService != null) { - ClientDetails client = clientDetailsService.loadClientByClientId(authorizationRequest.getClientId()); - Integer validity = client.getAccessTokenValiditySeconds(); - if (validity != null) { - return validity; - } - } - return accessTokenValiditySeconds; - } - - /** - * The refresh token validity period in seconds - * @param authorizationRequest the current authorization request - * @return the refresh token validity period in seconds - */ - protected int getRefreshTokenValiditySeconds(OAuth2Request authorizationRequest) { - if (clientDetailsService != null) { - ClientDetails client = clientDetailsService.loadClientByClientId(authorizationRequest.getClientId()); - Integer validity = client.getRefreshTokenValiditySeconds(); - if (validity != null) { - return validity; - } - } - return refreshTokenValiditySeconds; - } - - /** - * @param accessToken the access token whose value needs to be encoded - * @param authentication the current authentication - * @return an access token value encoding the contents of the input token - */ - private String encode(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { - return jwtTokenEnhancer.encode(accessToken, authentication); - } - - private Map decode(String token) { - return jwtTokenEnhancer.decode(token); - } - - /** - * Create a refreshed authentication taking into account the requested scope and the scope of the original - * authentication. - * - * @param authentication The authentication. - * @param scope The scope for the refreshed token. - * @return The refreshed authentication. - * @throws InvalidScopeException If the scope requested is invalid or wider than the original scope. - */ - private OAuth2Authentication createRefreshedAuthentication(OAuth2Authentication authentication, Set scope) { - OAuth2Authentication narrowed = authentication; - if (scope != null && !scope.isEmpty()) { - OAuth2Request clientAuth = authentication.getOAuth2Request(); - Set originalScope = clientAuth.getScope(); - if (originalScope == null || !originalScope.containsAll(scope)) { - throw new InvalidScopeException("Unable to narrow the scope of the client authentication to " + scope - + ".", originalScope); - } - else { - narrowed = new OAuth2Authentication(clientAuth.narrowScope(scope), - authentication.getUserAuthentication()); - } - } - return narrowed; - } - - /** - * Create a refresh token (if supported) by encoding an authentication, so it can be recovered when needed without - * any need for shared storage. - * - * @param authentication the current authentication - * @return a refresh token with a JWT encoded value - */ - private ExpiringOAuth2RefreshToken createRefreshToken(OAuth2Authentication authentication) { - if (!isSupportRefreshToken(authentication.getOAuth2Request())) { - return null; - } - DefaultOAuth2AccessToken encodedRefreshToken = new DefaultOAuth2AccessToken(getAccessToken(authentication)); - int validitySeconds = getRefreshTokenValiditySeconds(authentication.getOAuth2Request()); - Date expiration = new Date(System.currentTimeMillis() + (validitySeconds * 1000L)); - encodedRefreshToken.setExpiration(expiration); - encodedRefreshToken.setValue(encode(encodedRefreshToken, authentication)); - ExpiringOAuth2RefreshToken refreshToken = new DefaultExpiringOAuth2RefreshToken(encodedRefreshToken.getValue(), - expiration); - return refreshToken; - } - -} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java index 315003ad5..a5cede0a4 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java @@ -50,9 +50,11 @@ import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenGranter; import org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; +import org.springframework.security.oauth2.provider.token.DefaultTokenServices; import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; import org.springframework.security.oauth2.provider.token.JdbcTokenStore; -import org.springframework.security.oauth2.provider.token.JwtTokenServices; +import org.springframework.security.oauth2.provider.token.JwtTokenEnhancer; +import org.springframework.security.oauth2.provider.token.JwtTokenStore; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; @@ -143,10 +145,12 @@ public void configure(ClientDetailsServiceConfigurer clients) throws Exception { @Override public void run() { // With no explicit approval store we still expect to see scopes in the user approval model - UserApprovalHandler handler = (UserApprovalHandler) ReflectionTestUtils.getField(endpoint, "userApprovalHandler"); + UserApprovalHandler handler = (UserApprovalHandler) ReflectionTestUtils.getField(endpoint, + "userApprovalHandler"); AuthorizationRequest authorizationRequest = new AuthorizationRequest(); authorizationRequest.setScope(Arrays.asList("read")); - Map request = handler.getUserApprovalRequest(authorizationRequest, new UsernamePasswordAuthenticationToken("user", "password")); + Map request = handler.getUserApprovalRequest(authorizationRequest, + new UsernamePasswordAuthenticationToken("user", "password")); assertTrue(request.containsKey("scopes")); } } @@ -180,11 +184,13 @@ public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws @Override public void run() { // There should be no scopes in the approval model - UserApprovalHandler handler = (UserApprovalHandler) ReflectionTestUtils.getField(endpoint, "userApprovalHandler"); + UserApprovalHandler handler = (UserApprovalHandler) ReflectionTestUtils.getField(endpoint, + "userApprovalHandler"); AuthorizationRequest authorizationRequest = new AuthorizationRequest(); authorizationRequest.setScope(Arrays.asList("read")); - Map request = handler.getUserApprovalRequest(authorizationRequest, new UsernamePasswordAuthenticationToken("user", "password")); - assertFalse(request.containsKey("scopes")); + Map request = handler.getUserApprovalRequest(authorizationRequest, + new UsernamePasswordAuthenticationToken("user", "password")); + assertFalse(request.containsKey("scopes")); } } @@ -266,11 +272,31 @@ protected static class AuthorizationServerJwt extends AuthorizationServerConfigu @Autowired private ApplicationContext context; - private JwtTokenServices tokenServices = new JwtTokenServices(); + @Autowired + private ClientDetailsService clientDetailsService; @Override public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { - oauthServer.tokenServices(tokenServices).realm("sparklr2/client"); + oauthServer.tokenServices(tokenServices()).realm("sparklr2/client"); + } + + @Bean + public DefaultTokenServices tokenServices() { + DefaultTokenServices services = new DefaultTokenServices(); + services.setClientDetailsService(clientDetailsService); + services.setTokenEnhancer(jwtTokenEnhancer()); + services.setTokenStore(tokenStore()); + return services; + } + + @Bean + public TokenStore tokenStore() { + return new JwtTokenStore(jwtTokenEnhancer()); + } + + @Bean + protected JwtTokenEnhancer jwtTokenEnhancer() { + return new JwtTokenEnhancer(); } @Override diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenServicesTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenServicesTests.java deleted file mode 100644 index a8de53c6e..000000000 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenServicesTests.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Cloud Foundry 2012.02.03 Beta - * Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved. - * - * This product is licensed to you under the Apache License, Version 2.0 (the "License"). - * You may not use this product except in compliance with the License. - * - * This product includes a number of subcomponents with - * separate copyright notices and license terms. Your use of these - * subcomponents is subject to the terms and conditions of the - * subcomponent's license, as noted in the LICENSE file. - */ - -package org.springframework.security.oauth2.provider.token; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.util.Arrays; -import java.util.Collections; -import java.util.Date; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; - -import org.junit.Before; -import org.junit.Test; -import org.springframework.security.authentication.AbstractAuthenticationToken; -import org.springframework.security.jwt.JwtHelper; -import org.springframework.security.jwt.crypto.sign.MacSigner; -import org.springframework.security.oauth2.common.DefaultExpiringOAuth2RefreshToken; -import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; -import org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken; -import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.common.OAuth2RefreshToken; -import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; -import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; -import org.springframework.security.oauth2.provider.AuthorizationRequest; -import org.springframework.security.oauth2.provider.ClientDetails; -import org.springframework.security.oauth2.provider.ClientDetailsService; -import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.OAuth2Request; -import org.springframework.security.oauth2.provider.TokenRequest; -import org.springframework.security.oauth2.provider.client.BaseClientDetails; -import org.springframework.test.util.ReflectionTestUtils; - -/** - * @author Dave Syer - * - */ -public class JwtTokenServicesTests { - - private JwtTokenServices services = new JwtTokenServices(); - - private JwtTokenEnhancer enhancer; - - @Before - public void init() throws Exception { - services.setVerifierKey("FOO"); - services.setSigningKey("FOO"); - services.afterPropertiesSet(); - enhancer = (JwtTokenEnhancer) ReflectionTestUtils.getField(services, "jwtTokenEnhancer"); - } - - @Test - public void testReadAccessToken() throws Exception { - String token = JwtHelper.encode("{\"client_id\":\"client\"}", new MacSigner("FOO")).getEncoded(); - OAuth2AccessToken accessToken = services.readAccessToken(token); - assertEquals(token, accessToken.getValue()); - } - - @Test - public void testLoadAuthentication() throws Exception { - String token = JwtHelper.encode("{\"client_id\":\"client\"}", new MacSigner("FOO")).getEncoded(); - OAuth2Authentication authentication = services.loadAuthentication(token); - assertEquals(null, authentication.getUserAuthentication()); - assertEquals("client", authentication.getOAuth2Request().getClientId()); - } - @Test - public void testLoadAuthenticationWithTokenConverter() throws Exception { - services.setAccessTokenConverter(new DefaultAccessTokenConverter() { - @Override - public OAuth2Authentication extractAuthentication(Map map) { - AuthorizationRequest tokenRequest = new AuthorizationRequest("different",Collections.emptySet()); - return new OAuth2Authentication(tokenRequest.createOAuth2Request(), null); - } - }); - String token = JwtHelper.encode("{\"client_id\":\"client\"}", new MacSigner("FOO")).getEncoded(); - OAuth2Authentication authentication = services.loadAuthentication(token); - assertEquals(null, authentication.getUserAuthentication()); - assertEquals("different", authentication.getOAuth2Request().getClientId()); - } - - @Test - public void testTokenEnhancerUpdatesTokens() throws Exception { - services.setTokenEnhancer(new TokenEnhancer() { - public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { - DefaultOAuth2AccessToken result = new DefaultOAuth2AccessToken(accessToken); - ExpiringOAuth2RefreshToken refreshToken = new DefaultExpiringOAuth2RefreshToken("testToken", new Date( - System.currentTimeMillis() + 100000)); - result.setRefreshToken(refreshToken); - return result; - } - }); - OAuth2Authentication authentication = createAuthentication(); - OAuth2AccessToken original = services.createAccessToken(authentication); - String result = enhancer.encode(original, authentication); - assertEquals(original.getValue(), result); - } - - @Test - public void testJwtTokenEnhancerIdempotent() throws Exception { - OAuth2Authentication authentication = createAuthentication(); - OAuth2AccessToken original = services.createAccessToken(authentication); - services.setTokenEnhancer(enhancer); - OAuth2AccessToken updated = services.createAccessToken(authentication); - assertEquals(original.getValue(), updated.getValue()); - } - - @Test - public void testRefreshedTokenIsEnhanced() throws Exception { - services.setTokenEnhancer(new TokenEnhancer() { - public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { - DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(accessToken); - token.setAdditionalInformation(Collections. singletonMap("foo", "bar")); - return token; - } - }); - - OAuth2AccessToken accessToken = services.createAccessToken(createAuthentication()); - assertEquals("bar", accessToken.getAdditionalInformation().get("foo")); - OAuth2AccessToken refreshedAccessToken = services.refreshAccessToken(accessToken.getRefreshToken().getValue(), - new TokenRequest(null, "id", null, null)); - assertEquals("bar", refreshedAccessToken.getAdditionalInformation().get("foo")); - } - - @Test - public void testRefreshedTokenHasScopes() throws Exception { - ExpiringOAuth2RefreshToken expectedExpiringRefreshToken = (ExpiringOAuth2RefreshToken) services - .createAccessToken(createAuthentication()).getRefreshToken(); - OAuth2AccessToken refreshedAccessToken = services.refreshAccessToken(expectedExpiringRefreshToken.getValue(), - new TokenRequest(null, "id", null, null)); - assertEquals("[read, write]", refreshedAccessToken.getScope().toString()); - } - - @Test - public void testRefreshedTokenNarrowsScopes() throws Exception { - ExpiringOAuth2RefreshToken expectedExpiringRefreshToken = (ExpiringOAuth2RefreshToken) services - .createAccessToken(createAuthentication()).getRefreshToken(); - OAuth2AccessToken refreshedAccessToken = services.refreshAccessToken(expectedExpiringRefreshToken.getValue(), - new TokenRequest(null, "id", Collections.singleton("read"), null)); - assertEquals("[read]", refreshedAccessToken.getScope().toString()); - } - - @Test(expected = InvalidGrantException.class) - public void testRefreshedTokenInvalidWithWrongClient() throws Exception { - ExpiringOAuth2RefreshToken expectedExpiringRefreshToken = (ExpiringOAuth2RefreshToken) services - .createAccessToken(createAuthentication()).getRefreshToken(); - OAuth2AccessToken refreshedAccessToken = services.refreshAccessToken(expectedExpiringRefreshToken.getValue(), - new TokenRequest(null, "wrong", null, null)); - assertEquals("[read, write]", refreshedAccessToken.getScope().toString()); - } - - @Test - public void testUnlimitedTokenExpiry() throws Exception { - services.setAccessTokenValiditySeconds(0); - OAuth2AccessToken accessToken = services.createAccessToken(createAuthentication()); - assertEquals(0, accessToken.getExpiresIn()); - assertEquals(null, accessToken.getExpiration()); - } - - @Test - public void testDefaultTokenExpiry() throws Exception { - services.setAccessTokenValiditySeconds(100); - services.setRefreshTokenValiditySeconds(1000); - OAuth2AccessToken accessToken = services.createAccessToken(createAuthentication()); - assertTrue(100 >= accessToken.getExpiresIn()); - assertTrue(1000 * 1000 >= ((ExpiringOAuth2RefreshToken) accessToken.getRefreshToken()).getExpiration() - .getTime() - System.currentTimeMillis()); - } - - @Test - public void testClientSpecificTokenExpiry() throws Exception { - services.setAccessTokenValiditySeconds(1000); - services.setClientDetailsService(new ClientDetailsService() { - public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exception { - BaseClientDetails client = new BaseClientDetails(); - client.setAccessTokenValiditySeconds(100); - return client; - } - }); - OAuth2AccessToken accessToken = services.createAccessToken(createAuthentication()); - assertTrue(100 >= accessToken.getExpiresIn()); - } - - @Test - public void testClientSpecificRefreshTokenExpiry() throws Exception { - services.setRefreshTokenValiditySeconds(1000); - services.setClientDetailsService(new ClientDetailsService() { - public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exception { - BaseClientDetails client = new BaseClientDetails(); - client.setRefreshTokenValiditySeconds(100); - client.setAuthorizedGrantTypes(Arrays.asList("authorization_code", "refresh_token")); - return client; - } - }); - OAuth2AccessToken accessToken = services.createAccessToken(createAuthentication()); - DefaultExpiringOAuth2RefreshToken refreshToken = (DefaultExpiringOAuth2RefreshToken) accessToken - .getRefreshToken(); - Date expectedExpiryDate = new Date(System.currentTimeMillis() + 102 * 1000L); - assertTrue(expectedExpiryDate.after(refreshToken.getExpiration())); - } - - @Test - public void testOneAccessTokenPerAuthentication() throws Exception { - OAuth2Authentication authentication = createAuthentication(); - // TODO: occasionally fails because expiry time is different (millis) - OAuth2AccessToken first = services.createAccessToken(authentication); - OAuth2AccessToken second = services.createAccessToken(authentication); - assertEquals(first, second); - } - - @Test - public void testOneAccessTokenPerUniqueAuthentication() throws Exception { - String clientId = "id"; - services.createAccessToken(new OAuth2Authentication( - createOAuth2Request(clientId, Collections.singleton("read")), new TestAuthentication("test2", false))); - services.createAccessToken(new OAuth2Authentication(createOAuth2Request(clientId, - Collections.singleton("write")), new TestAuthentication("test2", false))); - } - - @Test - public void testRefreshTokenMaintainsState() throws Exception { - services.setSupportRefreshToken(true); - OAuth2AccessToken accessToken = services.createAccessToken(createAuthentication()); - OAuth2RefreshToken expectedExpiringRefreshToken = accessToken.getRefreshToken(); - OAuth2AccessToken refreshedAccessToken = services.refreshAccessToken(expectedExpiringRefreshToken.getValue(), - new TokenRequest(null, "id", null, null)); - assertNotNull(refreshedAccessToken); - } - - @Test - public void testNotReuseRefreshTokenMaintainsState() throws Exception { - services.setSupportRefreshToken(true); - services.setReuseRefreshToken(false); - OAuth2AccessToken accessToken = services.createAccessToken(createAuthentication()); - OAuth2RefreshToken expectedExpiringRefreshToken = accessToken.getRefreshToken(); - OAuth2AccessToken refreshedAccessToken = services.refreshAccessToken(expectedExpiringRefreshToken.getValue(), - new TokenRequest(null, "id", null, null)); - assertNotNull(refreshedAccessToken); - } - - private OAuth2Authentication createAuthentication() { - return new OAuth2Authentication(createOAuth2Request("id", - new LinkedHashSet(Arrays.asList("read", "write"))), new TestAuthentication("test2", false)); - } - - private OAuth2Request createOAuth2Request(String clientId, Set scope) { - return new OAuth2Request(Collections. emptyMap(), clientId, null, true, scope, null, null, - null, null); - } - - @SuppressWarnings("serial") - protected static class TestAuthentication extends AbstractAuthenticationToken { - private String principal; - - public TestAuthentication(String name, boolean authenticated) { - super(null); - setAuthenticated(authenticated); - this.principal = name; - } - - public Object getCredentials() { - return null; - } - - public Object getPrincipal() { - return this.principal; - } - } - -} From bf1e2bdf77bf62d8bffa36f4a933b8b7858e6878 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 10 Apr 2014 17:36:26 +0100 Subject: [PATCH 231/831] Add AuthorizationServerTokenServices bean --- .../AuthorizationServerConfiguration.java | 10 +++++++++- .../web/configuration/ResourceServerConfiguration.java | 6 +++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java index b727f2f51..b606047af 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java @@ -53,6 +53,7 @@ import org.springframework.security.oauth2.provider.endpoint.WhitelabelApprovalEndpoint; import org.springframework.security.oauth2.provider.endpoint.WhitelabelErrorEndpoint; import org.springframework.security.oauth2.provider.implicit.ImplicitGrantService; +import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; import org.springframework.security.oauth2.provider.token.ConsumerTokenServices; import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; import org.springframework.security.oauth2.provider.token.TokenStore; @@ -157,11 +158,18 @@ public ImplicitGrantService implicitGrantService() throws Exception { @Bean @Lazy - @Scope(proxyMode = ScopedProxyMode.INTERFACES) + @Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) public ConsumerTokenServices consumerTokenServices() throws Exception { return authorizationServerConfigurer().getConsumerTokenServices(); } + @Bean + @Lazy + @Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) + public AuthorizationServerTokenServices authorizationServerTokenServices() throws Exception { + return authorizationServerConfigurer().getTokenServices(); + } + @Bean public TokenEndpoint tokenEndpoint() throws Exception { TokenEndpoint tokenEndpoint = new TokenEndpoint(); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java index 4c4079588..77e5311d7 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java @@ -60,11 +60,11 @@ public void setConfigurers(List configurers) { this.configurers = configurers; } - private static class NotOAuthRequstMatcher implements RequestMatcher { + private static class NotOAuthRequestMatcher implements RequestMatcher { private FrameworkEndpointHandlerMapping mapping; - public NotOAuthRequstMatcher(FrameworkEndpointHandlerMapping mapping) { + public NotOAuthRequestMatcher(FrameworkEndpointHandlerMapping mapping) { this.mapping = mapping; } @@ -96,7 +96,7 @@ protected void configure(HttpSecurity http) throws Exception { RequestMatcherConfigurer requests = http.requestMatchers(); if (frameworkEndpointHandlerMapping != null) { // Assume we are in an Authorization Server - requests.requestMatchers(new NotOAuthRequstMatcher(frameworkEndpointHandlerMapping)); + requests.requestMatchers(new NotOAuthRequestMatcher(frameworkEndpointHandlerMapping)); } // @formatter:off http From 092dabbf31e711ea74b4921e3b48c74e63d8855c Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 10 Apr 2014 18:12:28 +0100 Subject: [PATCH 232/831] Add TokenEnhancer to AuthorizationServerSecurityConfigurer --- .../AuthorizationServerSecurityConfigurer.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java index c1eca1a5c..c83a4fb77 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java @@ -58,6 +58,7 @@ import org.springframework.security.oauth2.provider.token.DefaultTokenServices; import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; import org.springframework.security.oauth2.provider.token.JwtTokenStore; +import org.springframework.security.oauth2.provider.token.TokenEnhancer; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.DefaultSecurityFilterChain; @@ -90,6 +91,8 @@ public final class AuthorizationServerSecurityConfigurer extends private TokenStore tokenStore; + private TokenEnhancer tokenEnhancer; + private ApprovalStore approvalStore; private TokenGranter tokenGranter; @@ -126,6 +129,10 @@ public TokenStore getTokenStore() { return tokenStore; } + public TokenEnhancer getTokenEnhancer() { + return tokenEnhancer; + } + public ApprovalStore getApprovalStore() { return approvalStore; } @@ -156,6 +163,11 @@ public AuthorizationServerSecurityConfigurer tokenStore(TokenStore tokenStore) { return this; } + public AuthorizationServerSecurityConfigurer tokenEnhancer(TokenEnhancer tokenEnhancer) { + this.tokenEnhancer = tokenEnhancer; + return this; + } + public AuthorizationServerSecurityConfigurer tokenServices(AuthorizationServerTokenServices tokenServices) { this.tokenServices = tokenServices; return this; @@ -308,6 +320,7 @@ private AuthorizationServerTokenServices tokenServices(HttpSecurity http) { tokenServices.setTokenStore(tokenStore()); tokenServices.setSupportRefreshToken(true); tokenServices.setClientDetailsService(clientDetails()); + tokenServices.setTokenEnhancer(this.tokenEnhancer); this.tokenServices = tokenServices; return tokenServices; } From d58d5032f8631cb2fee090c815efb8f9d89f6f91 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 11 Apr 2014 09:54:37 +0100 Subject: [PATCH 233/831] Trap infinite loop in lazy proxies --- .../AuthorizationServerConfiguration.java | 39 +++++++++++++++ ...AuthorizationServerConfigurationTests.java | 49 +++++++++++++------ 2 files changed, 72 insertions(+), 16 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java index b606047af..df48ff7a3 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java @@ -20,8 +20,12 @@ import javax.annotation.PostConstruct; +import org.springframework.aop.TargetSource; +import org.springframework.aop.framework.Advised; +import org.springframework.aop.target.AbstractBeanFactoryBasedTargetSource; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; @@ -57,6 +61,7 @@ import org.springframework.security.oauth2.provider.token.ConsumerTokenServices; import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; import org.springframework.security.oauth2.provider.token.TokenStore; +import org.springframework.stereotype.Component; /** * @author Rob Winch @@ -283,4 +288,38 @@ public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) t } + /** + * If the user inadvertently autowires one of the lazy beans and then injects it back into the configurer they are + * going to create a proxy with a cyclic target. This processor ensures that at least there won't be a + * StackOverflowError (although the IllegalStateException comes too late to fail fast on startup). See + * https://jira.spring.io/browse/SPR-11684 + * + * @author Dave Syer + * + */ + @Component + protected static class CyclicProxyDetector implements BeanPostProcessor { + + @Override + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + return bean; + } + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + if (bean instanceof Advised) { + Advised advised = (Advised) bean; + TargetSource targetSource = advised.getTargetSource(); + if (targetSource != null && targetSource instanceof AbstractBeanFactoryBasedTargetSource) { + AbstractBeanFactoryBasedTargetSource source = (AbstractBeanFactoryBasedTargetSource) targetSource; + if (beanName.equals(source.getTargetBeanName())) { + throw new IllegalStateException("Cyclic proxy references itself as target: " + beanName); + } + } + } + return bean; + } + + } + } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java index a5cede0a4..0b6f2c560 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java @@ -77,6 +77,7 @@ public class AuthorizationServerConfigurationTests { public static List parameters() { return Arrays.asList( // @formatter:off new Object[] { BeanCreationException.class, new Class[] { AuthorizationServerUnconfigured.class } }, + new Object[] { BeanCreationException.class, new Class[] { AuthorizationServerCycle.class } }, new Object[] { null, new Class[] { AuthorizationServerVanilla.class } }, new Object[] { null, new Class[] { AuthorizationServerDisableApproval.class } }, new Object[] { null, new Class[] { AuthorizationServerExtras.class } }, @@ -155,6 +156,34 @@ public void run() { } } + @Configuration + @EnableWebMvcSecurity + @EnableAuthorizationServer + protected static class AuthorizationServerCycle extends AuthorizationServerConfigurerAdapter implements Runnable { + @Autowired + private AuthorizationServerTokenServices tokenServices; + + @Override + public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { + oauthServer.tokenServices(tokenServices); // Bang! (Cyclic proxy) + } + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + // @formatter:off + clients.inMemory() + .withClient("my-trusted-client") + .authorizedGrantTypes("password"); + // @formatter:on + } + + @Override + public void run() { + tokenServices.createAccessToken(null); + } + + } + @Configuration @EnableWebMvcSecurity @EnableAuthorizationServer @@ -169,10 +198,7 @@ public void configure(ClientDetailsServiceConfigurer clients) throws Exception { // @formatter:off clients.inMemory() .withClient("my-trusted-client") - .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit") - .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") - .scopes("read", "write", "trust") - .accessTokenValiditySeconds(60); + .authorizedGrantTypes("password"); // @formatter:on } @@ -250,10 +276,7 @@ public void configure(ClientDetailsServiceConfigurer clients) throws Exception { // @formatter:off clients.jdbc(dataSource()) .withClient("my-trusted-client") - .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit") - .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") - .scopes("read", "write", "trust") - .accessTokenValiditySeconds(60); + .authorizedGrantTypes("password"); // @formatter:on } @@ -304,10 +327,7 @@ public void configure(ClientDetailsServiceConfigurer clients) throws Exception { // @formatter:off clients.inMemory() .withClient("my-trusted-client") - .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit") - .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") - .scopes("read", "write", "trust") - .accessTokenValiditySeconds(60); + .authorizedGrantTypes("password"); // @formatter:on } @@ -333,10 +353,7 @@ public void configure(ClientDetailsServiceConfigurer clients) throws Exception { // @formatter:off clients.inMemory() .withClient("my-trusted-client") - .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit") - .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") - .scopes("read", "write", "trust") - .accessTokenValiditySeconds(60); + .authorizedGrantTypes("password"); // @formatter:on } From e634d1d95e933432f653286c6e9d9578434707a3 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 11 Apr 2014 17:10:49 +0100 Subject: [PATCH 234/831] Consolidate some @Autowiring --- .../AuthorizationServerConfiguration.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java index df48ff7a3..72c954a2d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java @@ -245,14 +245,12 @@ private AuthorizationServerSecurityConfigurer authorizationServerConfigurer() th protected static class EndpointsConfiguration { @Autowired - private AuthorizationEndpoint authorizationEndpoint; - - @Autowired - private FrameworkEndpointHandlerMapping mapping; - + private AuthorizationServerConfiguration configuration; @PostConstruct - public void init() { - authorizationEndpoint.setUserApprovalPage(extractPath(mapping, "/oauth/confirm_access")); + public void init() throws Exception { + AuthorizationEndpoint authorizationEndpoint = configuration.authorizationEndpoint(); + FrameworkEndpointHandlerMapping mapping = configuration.authorizationServerConfigurer().getFrameworkEndpointHandlerMapping(); + authorizationEndpoint .setUserApprovalPage(extractPath(mapping , "/oauth/confirm_access")); authorizationEndpoint.setErrorPage(extractPath(mapping, "/oauth/error")); } From 06d140cf582b976e5d8543e3e899d5ed67bbe16c Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 11 Apr 2014 17:25:32 +0100 Subject: [PATCH 235/831] Factor out @Bean FrameworkEndpointHandlerMapping --- .../configuration/AuthorizationServerConfiguration.java | 7 ++++--- .../web/configuration/ResourceServerConfiguration.java | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java index 72c954a2d..e4d1a8372 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java @@ -123,7 +123,7 @@ protected void configure(HttpSecurity http) throws Exception { } configure(configurer); http.apply(configurer); - String tokenEndpointPath = oauth2EndpointHandlerMapping().getPath("/oauth/token"); + String tokenEndpointPath = configurer.getFrameworkEndpointHandlerMapping().getPath("/oauth/token"); // @formatter:off http .authorizeRequests() @@ -237,7 +237,7 @@ public TokenGranter tokenGranter() throws Exception { return authorizationServerConfigurer().getTokenGranter(); } - private AuthorizationServerSecurityConfigurer authorizationServerConfigurer() throws Exception { + protected AuthorizationServerSecurityConfigurer authorizationServerConfigurer() throws Exception { return getHttp().getConfigurer(AuthorizationServerSecurityConfigurer.class); } @@ -246,11 +246,12 @@ protected static class EndpointsConfiguration { @Autowired private AuthorizationServerConfiguration configuration; + @PostConstruct public void init() throws Exception { AuthorizationEndpoint authorizationEndpoint = configuration.authorizationEndpoint(); FrameworkEndpointHandlerMapping mapping = configuration.authorizationServerConfigurer().getFrameworkEndpointHandlerMapping(); - authorizationEndpoint .setUserApprovalPage(extractPath(mapping , "/oauth/confirm_access")); + authorizationEndpoint.setUserApprovalPage(extractPath(mapping , "/oauth/confirm_access")); authorizationEndpoint.setErrorPage(extractPath(mapping, "/oauth/error")); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java index 77e5311d7..1726ca766 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java @@ -46,7 +46,7 @@ public class ResourceServerConfiguration extends WebSecurityConfigurerAdapter { private TokenStore tokenStore; @Autowired(required = false) - private FrameworkEndpointHandlerMapping frameworkEndpointHandlerMapping; + private AuthorizationServerConfiguration authorizationServerConfiguration; private List configurers = Collections.emptyList(); @@ -94,9 +94,10 @@ private String getRequestPath(HttpServletRequest request) { @Override protected void configure(HttpSecurity http) throws Exception { RequestMatcherConfigurer requests = http.requestMatchers(); - if (frameworkEndpointHandlerMapping != null) { + if (authorizationServerConfiguration != null) { // Assume we are in an Authorization Server - requests.requestMatchers(new NotOAuthRequestMatcher(frameworkEndpointHandlerMapping)); + requests.requestMatchers(new NotOAuthRequestMatcher(authorizationServerConfiguration + .authorizationServerConfigurer().getFrameworkEndpointHandlerMapping())); } // @formatter:off http From d85528de281230bd0b366464aa17c1c474f6e3e4 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Sat, 12 Apr 2014 07:22:29 +0100 Subject: [PATCH 236/831] Factor out non-filter concerns into *Endpoints* There should be no need for @Lazy @Scope @Beans and most of the old AuthorizationServerConfiguration was nothing to do with Security, so we have split out the non-security concerns and made a new method in the configurer. --- docs/oauth2.md | 7 +- .../sparklr/config/OAuth2ServerConfig.java | 65 ++-- ...ava => ApplicationConfigurationTests.java} | 2 +- .../AuthorizationServerConfiguration.java | 324 ---------------- .../AuthorizationServerConfigurer.java | 3 + .../AuthorizationServerConfigurerAdapter.java | 5 + ...orizationServerEndpointsConfiguration.java | 204 ++++++++++ ...horizationServerSecurityConfiguration.java | 90 +++++ .../EnableAuthorizationServer.java | 2 +- .../ResourceServerConfiguration.java | 11 +- ...uthorizationServerEndpointsConfigurer.java | 347 ++++++++++++++++++ ...AuthorizationServerSecurityConfigurer.java | 325 +--------------- ...AuthorizationServerConfigurationTests.java | 43 ++- .../ResourceServerConfigurationTests.java | 59 ++- 14 files changed, 756 insertions(+), 731 deletions(-) rename samples/oauth2/sparklr/src/test/java/org/springframework/security/samples/config/{SecurityConfigTests.java => ApplicationConfigurationTests.java} (97%) delete mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerEndpointsConfiguration.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerEndpointsConfigurer.java diff --git a/docs/oauth2.md b/docs/oauth2.md index 779e28938..29217f902 100644 --- a/docs/oauth2.md +++ b/docs/oauth2.md @@ -37,7 +37,8 @@ As you configure the Authorization Server, you have to consider the grant type t The `@EnableAuthorizationServer` annotation is used to configure the OAuth 2.0 Authorization Server mechanism, together with any `@Beans` that implement `AuthorizationServerConfigurer` (there is a hander adapter implementation with empty methods). The following features are delegated to separate configurers that are created by Spring and passed into the `AuthorizationServerConfigurer`: * `ClientDetailsServiceConfigurer`: a configurer that defines the client details service. Client details can be initialized, or you can just refer to an existing store. -* `AuthorizationServerSecurityConfigurer`: defines the authorization and token endpoints and the token services. +* `AuthorizationServerSecurityConfigurer`: defines the security constraints on the token endpoint. +* `AuthorizationServerEndpointsConfigurer`: defines the authorization and token endpoints and the token services. An important aspect of the provider configuration is the way that an authorization code is supplied to an OAuth client (in the authorization code grant). A authorization code is obtained by the OAuth client by directing the end-user to an authorization page where the user can enter her credentials, resulting in a redirection from the provider authorization server back to the OAuth client with the authorization code. Examples of this are elaborated in the OAuth 2 specification. @@ -67,7 +68,7 @@ When creating your `AuthorizationServerTokenServices` implementation, you may wa ### Grant Types The grant types supported by the `AuthorizationEndpoint` can be -configured via the `AuthorizationServerSecurityConfigurer`. By default +configured via the `AuthorizationServerEndpointsConfigurer`. By default all grant types are supported except password (see below for details of how to switch it on). The following properties affect grant types: @@ -80,7 +81,7 @@ In XML grant types are included as child elements of the `authorization-server`. ### Configuring the Endpoint URLs -The `AuthorizationServerSecurityConfigurer` has a `pathMapping()` method. It takes two arguments: +The `AuthorizationServerEndpointsConfigurer` has a `pathMapping()` method. It takes two arguments: * The default (framework implementation) URL path for the endpoint * The custom path required (starting with a "/") diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java index 66a50d31d..acaa0b682 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java @@ -20,6 +20,9 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Lazy; +import org.springframework.context.annotation.Scope; +import org.springframework.context.annotation.ScopedProxyMode; import org.springframework.core.annotation.Order; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; @@ -31,12 +34,14 @@ 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.config.annotation.web.configuration.ResourceServerConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; import org.springframework.security.oauth2.provider.approval.ApprovalStore; import org.springframework.security.oauth2.provider.approval.TokenApprovalStore; +import org.springframework.security.oauth2.provider.approval.UserApprovalHandler; import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; import org.springframework.security.oauth2.provider.token.TokenStore; @@ -48,7 +53,7 @@ public class OAuth2ServerConfig { private static final String SPARKLR_RESOURCE_ID = "sparklr"; - + @Configuration @Order(10) protected static class UiResourceConfiguration extends WebSecurityConfigurerAdapter { @@ -67,7 +72,7 @@ protected void configure(HttpSecurity http) throws Exception { // @formatter:on } } - + @Configuration @EnableResourceServer protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { @@ -108,18 +113,15 @@ protected static class AuthorizationServerConfiguration extends AuthorizationSer private TokenStore tokenStore; @Autowired - private OAuth2RequestFactory requestFactory; + private UserApprovalHandler userApprovalHandler; @Autowired @Qualifier("authenticationManagerBean") private AuthenticationManager authenticationManager; - @Autowired - private ClientDetailsService clientDetailsService; - @Value("${tonr.redirect:http://localhost:8080/tonr2/sparklr/redirect}") private String tonrRedirectUri; - + @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { @@ -171,21 +173,35 @@ public void configure(ClientDetailsServiceConfigurer clients) throws Exception { // @formatter:on } - @Bean - public SparklrUserApprovalHandler userApprovalHandler() throws Exception { - SparklrUserApprovalHandler handler = new SparklrUserApprovalHandler(); - handler.setApprovalStore(approvalStore()); - handler.setRequestFactory(requestFactory); - handler.setClientDetailsService(clientDetailsService); - handler.setUseApprovalStore(true); - return handler; - } - @Bean public TokenStore tokenStore() { return new InMemoryTokenStore(); } + @Override + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + endpoints.tokenStore(tokenStore).userApprovalHandler(userApprovalHandler) + .authenticationManager(authenticationManager); + } + + @Override + public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { + oauthServer.realm("sparklr2/client"); + } + + } + + protected static class Stuff { + + @Autowired + private ClientDetailsService clientDetailsService; + + @Autowired + private TokenStore tokenStore; + + @Autowired + private OAuth2RequestFactory requestFactory; + @Bean public ApprovalStore approvalStore() throws Exception { TokenApprovalStore store = new TokenApprovalStore(); @@ -193,12 +209,17 @@ public ApprovalStore approvalStore() throws Exception { return store; } - @Override - public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { - oauthServer.tokenStore(tokenStore).userApprovalHandler(userApprovalHandler()) - .authenticationManager(authenticationManager).realm("sparklr2/client"); + @Bean + @Lazy + @Scope(proxyMode=ScopedProxyMode.TARGET_CLASS) + public SparklrUserApprovalHandler userApprovalHandler() throws Exception { + SparklrUserApprovalHandler handler = new SparklrUserApprovalHandler(); + handler.setApprovalStore(approvalStore()); + handler.setRequestFactory(requestFactory); + handler.setClientDetailsService(clientDetailsService); + handler.setUseApprovalStore(true); + return handler; } - } } diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/samples/config/SecurityConfigTests.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/samples/config/ApplicationConfigurationTests.java similarity index 97% rename from samples/oauth2/sparklr/src/test/java/org/springframework/security/samples/config/SecurityConfigTests.java rename to samples/oauth2/sparklr/src/test/java/org/springframework/security/samples/config/ApplicationConfigurationTests.java index 4366f2b61..c0ebc612e 100644 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/samples/config/SecurityConfigTests.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/samples/config/ApplicationConfigurationTests.java @@ -36,7 +36,7 @@ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration @WebAppConfiguration -public class SecurityConfigTests { +public class ApplicationConfigurationTests { @Configuration @ComponentScan(basePackageClasses = SecurityConfiguration.class) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java deleted file mode 100644 index e4d1a8372..000000000 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfiguration.java +++ /dev/null @@ -1,324 +0,0 @@ -/* - * Copyright 2002-2013 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.web.configuration; - -import java.util.Collections; -import java.util.List; - -import javax.annotation.PostConstruct; - -import org.springframework.aop.TargetSource; -import org.springframework.aop.framework.Advised; -import org.springframework.aop.target.AbstractBeanFactoryBasedTargetSource; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; -import org.springframework.beans.factory.support.RootBeanDefinition; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; -import org.springframework.context.annotation.Lazy; -import org.springframework.context.annotation.Scope; -import org.springframework.context.annotation.ScopedProxyMode; -import org.springframework.core.annotation.Order; -import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.oauth2.config.annotation.configuration.ClientDetailsServiceConfiguration; -import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; -import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfiguration.TokenStoreRegistrar; -import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; -import org.springframework.security.oauth2.provider.ClientDetailsService; -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.approval.ApprovalStore; -import org.springframework.security.oauth2.provider.approval.UserApprovalHandler; -import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; -import org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint; -import org.springframework.security.oauth2.provider.endpoint.FrameworkEndpointHandlerMapping; -import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint; -import org.springframework.security.oauth2.provider.endpoint.WhitelabelApprovalEndpoint; -import org.springframework.security.oauth2.provider.endpoint.WhitelabelErrorEndpoint; -import org.springframework.security.oauth2.provider.implicit.ImplicitGrantService; -import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; -import org.springframework.security.oauth2.provider.token.ConsumerTokenServices; -import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; -import org.springframework.security.oauth2.provider.token.TokenStore; -import org.springframework.stereotype.Component; - -/** - * @author Rob Winch - * @author Dave Syer - * - */ -@Configuration -@Import({ ClientDetailsServiceConfiguration.class, TokenStoreRegistrar.class }) -@Order(0) -public class AuthorizationServerConfiguration extends WebSecurityConfigurerAdapter { - - /** - * The static bean name for a TokenStore if any. If the use creates his own bean with the same name, or else an - * ApprovalStore named {@link #APPROVAL_STORE_BEAN_NAME}, then Spring will create an {@link InMemoryTokenStore}. - * - */ - public static final String TOKEN_STORE_BEAN_NAME = "tokenStore"; - - /** - * The static bean name for a {@link ApprovalStore} if any. Spring will not create one, but it will also not create - * a {@link TokenStore} bean if there is an approval store present. - */ - public static final String APPROVAL_STORE_BEAN_NAME = "approvalStore"; - - @Autowired - private List configurers = Collections.emptyList(); - - @Autowired - private ClientDetailsService clientDetailsService; - - @Autowired(required = false) - private TokenStore tokenStore; - - @Autowired(required = false) - private ApprovalStore approvalStore; - - @Configuration - protected static class ClientDetailsAuthenticationManagerConfiguration extends - GlobalAuthenticationConfigurerAdapter { - - } - - @Autowired - public void configure(ClientDetailsServiceConfigurer clientDetails) throws Exception { - for (AuthorizationServerConfigurer configurer : configurers) { - configurer.configure(clientDetails); - } - } - - @Override - protected void configure(HttpSecurity http) throws Exception { - AuthorizationServerSecurityConfigurer configurer = new AuthorizationServerSecurityConfigurer(); - configurer.clientDetailsService(clientDetailsService); - if (tokenStore != null) { - configurer.tokenStore(tokenStore); - } - if (approvalStore != null) { - configurer.approvalStore(approvalStore); - } - configure(configurer); - http.apply(configurer); - String tokenEndpointPath = configurer.getFrameworkEndpointHandlerMapping().getPath("/oauth/token"); - // @formatter:off - http - .authorizeRequests() - .antMatchers(tokenEndpointPath).fullyAuthenticated() - .and() - .requestMatchers() - .antMatchers(tokenEndpointPath); - // @formatter:on - http.setSharedObject(ClientDetailsService.class, clientDetailsService); - } - - protected void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { - for (AuthorizationServerConfigurer configurer : configurers) { - configurer.configure(oauthServer); - } - } - - @Bean - public AuthorizationEndpoint authorizationEndpoint() throws Exception { - AuthorizationEndpoint authorizationEndpoint = new AuthorizationEndpoint(); - authorizationEndpoint.setTokenGranter(tokenGranter()); - authorizationEndpoint.setClientDetailsService(clientDetailsService); - authorizationEndpoint.setAuthorizationCodeServices(authorizationCodeServices()); - authorizationEndpoint.setOAuth2RequestFactory(oauth2RequestFactory()); - authorizationEndpoint.setOAuth2RequestValidator(oauth2RequestValidator()); - authorizationEndpoint.setUserApprovalHandler(userApprovalHandler()); - authorizationEndpoint.setImplicitGrantService(implicitGrantService()); - return authorizationEndpoint; - } - - @Bean - @Lazy - @Scope(proxyMode = ScopedProxyMode.INTERFACES) - public ImplicitGrantService implicitGrantService() throws Exception { - return authorizationServerConfigurer().getImplicitGrantService(); - } - - @Bean - @Lazy - @Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) - public ConsumerTokenServices consumerTokenServices() throws Exception { - return authorizationServerConfigurer().getConsumerTokenServices(); - } - - @Bean - @Lazy - @Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) - public AuthorizationServerTokenServices authorizationServerTokenServices() throws Exception { - return authorizationServerConfigurer().getTokenServices(); - } - - @Bean - public TokenEndpoint tokenEndpoint() throws Exception { - TokenEndpoint tokenEndpoint = new TokenEndpoint(); - tokenEndpoint.setClientDetailsService(clientDetailsService); - tokenEndpoint.setTokenGranter(tokenGranter()); - tokenEndpoint.setOAuth2RequestFactory(oauth2RequestFactory()); - tokenEndpoint.setOAuth2RequestValidator(oauth2RequestValidator()); - return tokenEndpoint; - } - - @Bean - @Lazy - @Scope(proxyMode = ScopedProxyMode.INTERFACES) - public OAuth2RequestFactory oauth2RequestFactory() throws Exception { - return authorizationServerConfigurer().getOAuth2RequestFactory(); - } - - @Bean - @Lazy - @Scope(proxyMode = ScopedProxyMode.INTERFACES) - public OAuth2RequestValidator oauth2RequestValidator() throws Exception { - return authorizationServerConfigurer().getOAuth2RequestValidator(); - } - - @Bean - @Lazy - @Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) - public UserApprovalHandler userApprovalHandler() throws Exception { - return authorizationServerConfigurer().getUserApprovalHandler(); - } - - @Bean - public WhitelabelApprovalEndpoint whitelabelApprovalEndpoint() { - return new WhitelabelApprovalEndpoint(); - } - - @Bean - public WhitelabelErrorEndpoint whitelabelErrorEndpoint() { - return new WhitelabelErrorEndpoint(); - } - - @Bean - @Lazy - @Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) - public FrameworkEndpointHandlerMapping oauth2EndpointHandlerMapping() throws Exception { - return authorizationServerConfigurer().getFrameworkEndpointHandlerMapping(); - } - - @Bean - @Lazy - @Scope(proxyMode = ScopedProxyMode.INTERFACES) - public AuthorizationCodeServices authorizationCodeServices() throws Exception { - return authorizationServerConfigurer().getAuthorizationCodeServices(); - } - - @Bean - @Lazy - @Scope(proxyMode = ScopedProxyMode.INTERFACES) - public TokenGranter tokenGranter() throws Exception { - return authorizationServerConfigurer().getTokenGranter(); - } - - protected AuthorizationServerSecurityConfigurer authorizationServerConfigurer() throws Exception { - return getHttp().getConfigurer(AuthorizationServerSecurityConfigurer.class); - } - - @Configuration - protected static class EndpointsConfiguration { - - @Autowired - private AuthorizationServerConfiguration configuration; - - @PostConstruct - public void init() throws Exception { - AuthorizationEndpoint authorizationEndpoint = configuration.authorizationEndpoint(); - FrameworkEndpointHandlerMapping mapping = configuration.authorizationServerConfigurer().getFrameworkEndpointHandlerMapping(); - authorizationEndpoint.setUserApprovalPage(extractPath(mapping , "/oauth/confirm_access")); - authorizationEndpoint.setErrorPage(extractPath(mapping, "/oauth/error")); - } - - private String extractPath(FrameworkEndpointHandlerMapping mapping, String page) { - String path = mapping.getPath(page); - if (path.contains(":")) { - return path; - } - return "forward:" + path; - } - - } - - @Configuration - protected static class TokenStoreRegistrar implements BeanDefinitionRegistryPostProcessor { - - private BeanDefinitionRegistry registry; - - // Use a BeanFactoryPostProcessor to register a bean definition for a TokenStore in a safe way (without - // pre-empting a bean specified by the user) - @Override - public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { - if (!registry.containsBeanDefinition(TOKEN_STORE_BEAN_NAME) - && !registry.containsBeanDefinition(APPROVAL_STORE_BEAN_NAME)) { - registry.registerBeanDefinition(TOKEN_STORE_BEAN_NAME, new RootBeanDefinition(InMemoryTokenStore.class)); - } - } - - @Override - public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { - this.registry = registry; - } - - } - - /** - * If the user inadvertently autowires one of the lazy beans and then injects it back into the configurer they are - * going to create a proxy with a cyclic target. This processor ensures that at least there won't be a - * StackOverflowError (although the IllegalStateException comes too late to fail fast on startup). See - * https://jira.spring.io/browse/SPR-11684 - * - * @author Dave Syer - * - */ - @Component - protected static class CyclicProxyDetector implements BeanPostProcessor { - - @Override - public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { - return bean; - } - - @Override - public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - if (bean instanceof Advised) { - Advised advised = (Advised) bean; - TargetSource targetSource = advised.getTargetSource(); - if (targetSource != null && targetSource instanceof AbstractBeanFactoryBasedTargetSource) { - AbstractBeanFactoryBasedTargetSource source = (AbstractBeanFactoryBasedTargetSource) targetSource; - if (beanName.equals(source.getTargetBeanName())) { - throw new IllegalStateException("Cyclic proxy references itself as target: " + beanName); - } - } - } - return bean; - } - - } - -} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurer.java index d96dd2153..518172e64 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurer.java @@ -14,6 +14,7 @@ package org.springframework.security.oauth2.config.annotation.web.configuration; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; /** @@ -26,4 +27,6 @@ public interface AuthorizationServerConfigurer { void configure(ClientDetailsServiceConfigurer clients) throws Exception; + void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception; + } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurerAdapter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurerAdapter.java index bafbd3c45..0b8d6de6b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurerAdapter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurerAdapter.java @@ -14,6 +14,7 @@ package org.springframework.security.oauth2.config.annotation.web.configuration; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; /** @@ -30,4 +31,8 @@ public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws public void configure(ClientDetailsServiceConfigurer clients) throws Exception { } + @Override + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + } + } 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 new file mode 100644 index 000000000..ea77d5eed --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerEndpointsConfiguration.java @@ -0,0 +1,204 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.springframework.security.oauth2.config.annotation.web.configuration; + +import java.util.Collections; +import java.util.List; + +import javax.annotation.PostConstruct; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerEndpointsConfiguration.TokenStoreRegistrar; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; +import org.springframework.security.oauth2.provider.ClientDetailsService; +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.approval.ApprovalStore; +import org.springframework.security.oauth2.provider.approval.UserApprovalHandler; +import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; +import org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint; +import org.springframework.security.oauth2.provider.endpoint.FrameworkEndpointHandlerMapping; +import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint; +import org.springframework.security.oauth2.provider.endpoint.WhitelabelApprovalEndpoint; +import org.springframework.security.oauth2.provider.endpoint.WhitelabelErrorEndpoint; +import org.springframework.security.oauth2.provider.implicit.ImplicitGrantService; +import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; +import org.springframework.security.oauth2.provider.token.ConsumerTokenServices; +import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; +import org.springframework.security.oauth2.provider.token.TokenStore; + +/** + * @author Dave Syer + * + */ +@Configuration +@Import(TokenStoreRegistrar.class) +public class AuthorizationServerEndpointsConfiguration { + + /** + * The static bean name for a TokenStore if any. If the use creates his own bean with the same name, or else an + * ApprovalStore named {@link #APPROVAL_STORE_BEAN_NAME}, then Spring will create an {@link InMemoryTokenStore}. + * + */ + public static final String TOKEN_STORE_BEAN_NAME = "tokenStore"; + + /** + * The static bean name for a {@link ApprovalStore} if any. Spring will not create one, but it will also not create + * a {@link TokenStore} bean if there is an approval store present. + */ + public static final String APPROVAL_STORE_BEAN_NAME = "approvalStore"; + + private AuthorizationServerEndpointsConfigurer endpoints = new AuthorizationServerEndpointsConfigurer(); + + @Autowired + private ClientDetailsService clientDetailsService; + + @Autowired + private List configurers = Collections.emptyList(); + + @Autowired(required = false) + private TokenStore tokenStore; + + @PostConstruct + public void init() throws Exception { + for (AuthorizationServerConfigurer configurer : configurers) { + configurer.configure(endpoints); + } + endpoints.clientDetailsService(clientDetailsService); + if (tokenStore != null) { + endpoints.tokenStore(tokenStore); + } + } + + @Bean + public AuthorizationEndpoint authorizationEndpoint() throws Exception { + AuthorizationEndpoint authorizationEndpoint = new AuthorizationEndpoint(); + FrameworkEndpointHandlerMapping mapping = endpoints.getFrameworkEndpointHandlerMapping(); + authorizationEndpoint.setUserApprovalPage(extractPath(mapping, "/oauth/confirm_access")); + authorizationEndpoint.setErrorPage(extractPath(mapping, "/oauth/error")); + authorizationEndpoint.setTokenGranter(tokenGranter()); + authorizationEndpoint.setClientDetailsService(clientDetailsService); + authorizationEndpoint.setAuthorizationCodeServices(authorizationCodeServices()); + authorizationEndpoint.setOAuth2RequestFactory(oauth2RequestFactory()); + authorizationEndpoint.setOAuth2RequestValidator(oauth2RequestValidator()); + authorizationEndpoint.setUserApprovalHandler(userApprovalHandler()); + authorizationEndpoint.setImplicitGrantService(implicitGrantService()); + return authorizationEndpoint; + } + + @Bean + public ImplicitGrantService implicitGrantService() throws Exception { + return endpoints.getImplicitGrantService(); + } + + @Bean + public ConsumerTokenServices consumerTokenServices() throws Exception { + return endpoints.getConsumerTokenServices(); + } + + @Bean + public AuthorizationServerTokenServices authorizationServerTokenServices() throws Exception { + return endpoints.getTokenServices(); + } + + @Bean + public TokenEndpoint tokenEndpoint() throws Exception { + TokenEndpoint tokenEndpoint = new TokenEndpoint(); + tokenEndpoint.setClientDetailsService(clientDetailsService); + tokenEndpoint.setTokenGranter(tokenGranter()); + tokenEndpoint.setOAuth2RequestFactory(oauth2RequestFactory()); + tokenEndpoint.setOAuth2RequestValidator(oauth2RequestValidator()); + return tokenEndpoint; + } + + @Bean + public OAuth2RequestFactory oauth2RequestFactory() throws Exception { + return endpoints.getOAuth2RequestFactory(); + } + + @Bean + public UserApprovalHandler userApprovalHandler() throws Exception { + return endpoints.getUserApprovalHandler(); + } + + @Bean + public OAuth2RequestValidator oauth2RequestValidator() throws Exception { + return endpoints.getOAuth2RequestValidator(); + } + + @Bean + public WhitelabelApprovalEndpoint whitelabelApprovalEndpoint() { + return new WhitelabelApprovalEndpoint(); + } + + @Bean + public WhitelabelErrorEndpoint whitelabelErrorEndpoint() { + return new WhitelabelErrorEndpoint(); + } + + @Bean + public FrameworkEndpointHandlerMapping oauth2EndpointHandlerMapping() throws Exception { + return endpoints.getFrameworkEndpointHandlerMapping(); + } + + @Bean + public AuthorizationCodeServices authorizationCodeServices() throws Exception { + return endpoints.getAuthorizationCodeServices(); + } + + @Bean + public TokenGranter tokenGranter() throws Exception { + return endpoints.getTokenGranter(); + } + + private String extractPath(FrameworkEndpointHandlerMapping mapping, String page) { + String path = mapping.getPath(page); + if (path.contains(":")) { + return path; + } + return "forward:" + path; + } + + @Configuration + protected static class TokenStoreRegistrar implements BeanDefinitionRegistryPostProcessor { + + private BeanDefinitionRegistry registry; + + // Use a BeanFactoryPostProcessor to register a bean definition for a TokenStore in a safe way (without + // pre-empting a bean specified by the user) + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { + if (!registry.containsBeanDefinition(TOKEN_STORE_BEAN_NAME) + && !registry.containsBeanDefinition(APPROVAL_STORE_BEAN_NAME)) { + registry.registerBeanDefinition(TOKEN_STORE_BEAN_NAME, new RootBeanDefinition(InMemoryTokenStore.class)); + } + } + + @Override + public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { + this.registry = registry; + } + + } + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java new file mode 100644 index 000000000..73fa3fda9 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java @@ -0,0 +1,90 @@ +/* + * Copyright 2002-2013 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.web.configuration; + +import java.util.Collections; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.core.annotation.Order; +import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.configuration.ClientDetailsServiceConfiguration; +import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.endpoint.FrameworkEndpointHandlerMapping; + +/** + * @author Rob Winch + * @author Dave Syer + * + */ +@Configuration +@Order(0) +@Import({ ClientDetailsServiceConfiguration.class, AuthorizationServerEndpointsConfiguration.class }) +public class AuthorizationServerSecurityConfiguration extends WebSecurityConfigurerAdapter { + + @Autowired + private List configurers = Collections.emptyList(); + + @Autowired + private ClientDetailsService clientDetailsService; + + @Autowired + private AuthorizationServerEndpointsConfiguration endpoints; + + @Configuration + protected static class ClientDetailsAuthenticationManagerConfiguration extends + GlobalAuthenticationConfigurerAdapter { + } + + @Autowired + public void configure(ClientDetailsServiceConfigurer clientDetails) throws Exception { + for (AuthorizationServerConfigurer configurer : configurers) { + configurer.configure(clientDetails); + } + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + AuthorizationServerSecurityConfigurer configurer = new AuthorizationServerSecurityConfigurer(); + FrameworkEndpointHandlerMapping handlerMapping = endpoints.oauth2EndpointHandlerMapping(); + http.setSharedObject(FrameworkEndpointHandlerMapping.class, handlerMapping); + configure(configurer); + http.apply(configurer); + String tokenEndpointPath = handlerMapping.getPath("/oauth/token"); + // @formatter:off + http + .authorizeRequests() + .antMatchers(tokenEndpointPath).fullyAuthenticated() + .and() + .requestMatchers() + .antMatchers(tokenEndpointPath); + // @formatter:on + http.setSharedObject(ClientDetailsService.class, clientDetailsService); + } + + protected void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { + for (AuthorizationServerConfigurer configurer : configurers) { + configurer.configure(oauthServer); + } + } + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableAuthorizationServer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableAuthorizationServer.java index 9687a7e57..bed46e8a3 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableAuthorizationServer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableAuthorizationServer.java @@ -42,7 +42,7 @@ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented -@Import(AuthorizationServerConfiguration.class) +@Import({AuthorizationServerEndpointsConfiguration.class, AuthorizationServerSecurityConfiguration.class}) public @interface EnableAuthorizationServer { } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java index 1726ca766..136ec45d3 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java @@ -45,13 +45,13 @@ public class ResourceServerConfiguration extends WebSecurityConfigurerAdapter { @Autowired(required = false) private TokenStore tokenStore; - @Autowired(required = false) - private AuthorizationServerConfiguration authorizationServerConfiguration; - private List configurers = Collections.emptyList(); private AccessDeniedHandler accessDeniedHandler = new OAuth2AccessDeniedHandler(); + @Autowired(required = false) + private AuthorizationServerEndpointsConfiguration endpoints; + /** * @param configurers the configurers to set */ @@ -94,10 +94,9 @@ private String getRequestPath(HttpServletRequest request) { @Override protected void configure(HttpSecurity http) throws Exception { RequestMatcherConfigurer requests = http.requestMatchers(); - if (authorizationServerConfiguration != null) { + if (endpoints != null) { // Assume we are in an Authorization Server - requests.requestMatchers(new NotOAuthRequestMatcher(authorizationServerConfiguration - .authorizationServerConfigurer().getFrameworkEndpointHandlerMapping())); + requests.requestMatchers(new NotOAuthRequestMatcher(endpoints.oauth2EndpointHandlerMapping())); } // @formatter:off http 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 new file mode 100644 index 000000000..a61ac88ce --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerEndpointsConfigurer.java @@ -0,0 +1,347 @@ +/* + * Copyright 2002-2013 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.web.configurers; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.security.authentication.AuthenticationManager; +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.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.client.ClientCredentialsTokenGranter; +import org.springframework.security.oauth2.provider.client.InMemoryClientDetailsService; +import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; +import org.springframework.security.oauth2.provider.code.AuthorizationCodeTokenGranter; +import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices; +import org.springframework.security.oauth2.provider.endpoint.FrameworkEndpointHandlerMapping; +import org.springframework.security.oauth2.provider.implicit.ImplicitGrantService; +import org.springframework.security.oauth2.provider.implicit.ImplicitTokenGranter; +import org.springframework.security.oauth2.provider.implicit.InMemoryImplicitGrantService; +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.AuthorizationServerTokenServices; +import org.springframework.security.oauth2.provider.token.ConsumerTokenServices; +import org.springframework.security.oauth2.provider.token.DefaultTokenServices; +import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; +import org.springframework.security.oauth2.provider.token.JwtTokenStore; +import org.springframework.security.oauth2.provider.token.TokenEnhancer; +import org.springframework.security.oauth2.provider.token.TokenStore; + +/** + * + * @author Rob Winch + * @author Dave Syer + * @since 2.0 + */ +public final class AuthorizationServerEndpointsConfigurer { + + private AuthorizationServerTokenServices tokenServices; + + private ConsumerTokenServices consumerTokenServices; + + private AuthorizationCodeServices authorizationCodeServices; + + private ImplicitGrantService implicitGrantService = new InMemoryImplicitGrantService(); + + private TokenStore tokenStore; + + private TokenEnhancer tokenEnhancer; + + private ApprovalStore approvalStore; + + private TokenGranter tokenGranter; + + private OAuth2RequestFactory requestFactory; + + private OAuth2RequestValidator requestValidator; + + private UserApprovalHandler userApprovalHandler; + + private AuthenticationManager authenticationManager; + + private ClientDetailsService clientDetailsService; + + private Map patternMap = new HashMap(); + + private FrameworkEndpointHandlerMapping frameworkEndpointHandlerMapping; + + private boolean approvalStoreDisabled; + + public AuthorizationServerTokenServices getTokenServices() { + return tokenServices; + } + + public TokenStore getTokenStore() { + return tokenStore; + } + + public TokenEnhancer getTokenEnhancer() { + return tokenEnhancer; + } + + public ApprovalStore getApprovalStore() { + return approvalStore; + } + + public ClientDetailsService getClientDetailsService() { + return clientDetailsService; + } + + public OAuth2RequestFactory getOAuth2RequestFactory() { + return requestFactory(); + } + + public OAuth2RequestValidator getOAuth2RequestValidator() { + return requestValidator(); + } + + public UserApprovalHandler getUserApprovalHandler() { + return userApprovalHandler(); + } + + public AuthorizationServerEndpointsConfigurer tokenStore(TokenStore tokenStore) { + this.tokenStore = tokenStore; + return this; + } + + public AuthorizationServerEndpointsConfigurer tokenEnhancer(TokenEnhancer tokenEnhancer) { + this.tokenEnhancer = tokenEnhancer; + return this; + } + + public AuthorizationServerEndpointsConfigurer tokenServices(AuthorizationServerTokenServices tokenServices) { + this.tokenServices = tokenServices; + return this; + } + + public AuthorizationServerEndpointsConfigurer userApprovalHandler(UserApprovalHandler approvalHandler) { + this.userApprovalHandler = approvalHandler; + return this; + } + + public AuthorizationServerEndpointsConfigurer approvalStore(ApprovalStore approvalStore) { + if (approvalStoreDisabled) { + throw new IllegalStateException("ApprovalStore was disabled"); + } + this.approvalStore = approvalStore; + return this; + } + + public AuthorizationServerEndpointsConfigurer approvalStoreDisabled() { + this.approvalStoreDisabled = true; + return this; + } + + public AuthorizationServerEndpointsConfigurer pathMapping(String defaultPath, String customPath) { + this.patternMap.put(defaultPath, customPath); + return this; + } + + public AuthorizationServerEndpointsConfigurer authenticationManager(AuthenticationManager authenticationManager) { + this.authenticationManager = authenticationManager; + return this; + } + + public AuthorizationServerEndpointsConfigurer tokenGranter(TokenGranter tokenGranter) { + this.tokenGranter = tokenGranter; + return this; + } + + public AuthorizationServerEndpointsConfigurer clientDetailsService(ClientDetailsService clientDetailsService) { + this.clientDetailsService = clientDetailsService; + return this; + } + + public AuthorizationServerEndpointsConfigurer requestFactory(OAuth2RequestFactory requestFactory) { + this.requestFactory = requestFactory; + return this; + } + + public AuthorizationServerEndpointsConfigurer requestValidator(OAuth2RequestValidator requestValidator) { + this.requestValidator = requestValidator; + return this; + } + + public AuthorizationServerEndpointsConfigurer authorizationCodeServices(AuthorizationCodeServices authorizationCodeServices) { + this.authorizationCodeServices = authorizationCodeServices; + return this; + } + + public ConsumerTokenServices getConsumerTokenServices() { + return consumerTokenServices(); + } + + public ImplicitGrantService getImplicitGrantService() { + return implicitGrantService; + } + + public AuthorizationCodeServices getAuthorizationCodeServices() { + return authorizationCodeServices(); + } + + public OAuth2RequestValidator getRequestValidator() { + return requestValidator(); + } + + public TokenGranter getTokenGranter() { + return tokenGranter(); + } + + public FrameworkEndpointHandlerMapping getFrameworkEndpointHandlerMapping() { + return frameworkEndpointHandlerMapping(); + } + + private ConsumerTokenServices consumerTokenServices() { + if (consumerTokenServices == null) { + if (tokenStore() != null) { + DefaultTokenServices defaultTokenServices = new DefaultTokenServices(); + defaultTokenServices.setClientDetailsService(clientDetailsService()); + defaultTokenServices.setTokenStore(tokenStore()); + consumerTokenServices = defaultTokenServices; + } + } + return consumerTokenServices; + } + + private AuthorizationServerTokenServices tokenServices() { + if (tokenServices != null) { + return tokenServices; + } + DefaultTokenServices tokenServices = new DefaultTokenServices(); + tokenServices.setTokenStore(tokenStore()); + tokenServices.setSupportRefreshToken(true); + tokenServices.setClientDetailsService(clientDetailsService()); + tokenServices.setTokenEnhancer(this.tokenEnhancer); + this.tokenServices = tokenServices; + return tokenServices; + } + + private TokenStore tokenStore() { + if (tokenStore == null && approvalStore == null) { + this.tokenStore = new InMemoryTokenStore(); + } + return this.tokenStore; + } + + private ApprovalStore approvalStore() { + if (approvalStore==null && tokenStore() != null && !isApprovalStoreDisabled()) { + TokenApprovalStore tokenApprovalStore = new TokenApprovalStore(); + tokenApprovalStore.setTokenStore(tokenStore()); + this.approvalStore = tokenApprovalStore; + } + return this.approvalStore; + } + + private boolean isApprovalStoreDisabled() { + return approvalStoreDisabled || (tokenStore() instanceof JwtTokenStore); + } + + private ClientDetailsService clientDetailsService() { + if (clientDetailsService == null) { + this.clientDetailsService = new InMemoryClientDetailsService(); + } + return this.clientDetailsService; + } + + private UserApprovalHandler userApprovalHandler() { + if (userApprovalHandler == null) { + if (approvalStore()!=null) { + ApprovalStoreUserApprovalHandler handler = new ApprovalStoreUserApprovalHandler(); + handler.setApprovalStore(approvalStore()); + handler.setRequestFactory(requestFactory()); + handler.setClientDetailsService(clientDetailsService); + this.userApprovalHandler = handler; + } + else if (tokenStore() != null) { + TokenStoreUserApprovalHandler userApprovalHandler = new TokenStoreUserApprovalHandler(); + userApprovalHandler.setTokenStore(tokenStore()); + userApprovalHandler.setClientDetailsService(clientDetailsService()); + userApprovalHandler.setRequestFactory(requestFactory()); + this.userApprovalHandler = userApprovalHandler; + } else { + throw new IllegalStateException("Either a TokenStore or an ApprovalStore must be provided"); + } + } + return this.userApprovalHandler; + } + + private AuthorizationCodeServices authorizationCodeServices() { + if (authorizationCodeServices == null) { + authorizationCodeServices = new InMemoryAuthorizationCodeServices(); + } + return authorizationCodeServices; + } + + private OAuth2RequestFactory requestFactory() { + if (requestFactory != null) { + return requestFactory; + } + requestFactory = new DefaultOAuth2RequestFactory(clientDetailsService()); + return requestFactory; + } + + private OAuth2RequestValidator requestValidator() { + if (requestValidator != null) { + return requestValidator; + } + requestValidator = new DefaultOAuth2RequestValidator(); + return requestValidator; + } + + private TokenGranter tokenGranter() { + if (tokenGranter == null) { + ClientDetailsService clientDetails = clientDetailsService(); + AuthorizationServerTokenServices tokenServices = tokenServices(); + AuthorizationCodeServices authorizationCodeServices = authorizationCodeServices(); + OAuth2RequestFactory requestFactory = requestFactory(); + + List tokenGranters = new ArrayList(); + tokenGranters.add(new AuthorizationCodeTokenGranter(tokenServices, authorizationCodeServices, + clientDetails, requestFactory)); + tokenGranters.add(new RefreshTokenGranter(tokenServices, clientDetails, requestFactory)); + ImplicitTokenGranter implicit = new ImplicitTokenGranter(tokenServices, clientDetails, requestFactory); + implicit.setImplicitGrantService(implicitGrantService); + tokenGranters.add(implicit); + tokenGranters.add(new ClientCredentialsTokenGranter(tokenServices, clientDetails, requestFactory)); + if (authenticationManager != null) { + tokenGranters.add(new ResourceOwnerPasswordTokenGranter(authenticationManager, tokenServices, + clientDetails, requestFactory)); + } + tokenGranter = new CompositeTokenGranter(tokenGranters); + } + return tokenGranter; + } + + private FrameworkEndpointHandlerMapping frameworkEndpointHandlerMapping() { + if (frameworkEndpointHandlerMapping == null) { + frameworkEndpointHandlerMapping = new FrameworkEndpointHandlerMapping(); + frameworkEndpointHandlerMapping.setMappings(patternMap); + } + return frameworkEndpointHandlerMapping; + } +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java index c83a4fb77..cff47c420 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java @@ -15,11 +15,7 @@ */ package org.springframework.security.oauth2.config.annotation.web.configurers; -import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; import org.springframework.http.MediaType; import org.springframework.security.authentication.AuthenticationManager; @@ -27,39 +23,11 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configurers.ExceptionHandlingConfigurer; 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.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.client.ClientCredentialsTokenEndpointFilter; -import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenGranter; import org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService; -import org.springframework.security.oauth2.provider.client.InMemoryClientDetailsService; -import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; -import org.springframework.security.oauth2.provider.code.AuthorizationCodeTokenGranter; -import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices; import org.springframework.security.oauth2.provider.endpoint.FrameworkEndpointHandlerMapping; import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint; -import org.springframework.security.oauth2.provider.implicit.ImplicitGrantService; -import org.springframework.security.oauth2.provider.implicit.ImplicitTokenGranter; -import org.springframework.security.oauth2.provider.implicit.InMemoryImplicitGrantService; -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.AuthorizationServerTokenServices; -import org.springframework.security.oauth2.provider.token.ConsumerTokenServices; -import org.springframework.security.oauth2.provider.token.DefaultTokenServices; -import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; -import org.springframework.security.oauth2.provider.token.JwtTokenStore; -import org.springframework.security.oauth2.provider.token.TokenEnhancer; -import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.DefaultSecurityFilterChain; import org.springframework.security.web.access.AccessDeniedHandler; @@ -72,7 +40,8 @@ /** * * @author Rob Winch - * @since 3.2 + * @author Dave Syer + * @since 2.0 */ public final class AuthorizationServerSecurityConfigurer extends SecurityConfigurerAdapter { @@ -81,162 +50,26 @@ public final class AuthorizationServerSecurityConfigurer extends private AccessDeniedHandler accessDeniedHandler = new OAuth2AccessDeniedHandler(); - private AuthorizationServerTokenServices tokenServices; - - private ConsumerTokenServices consumerTokenServices; - - private AuthorizationCodeServices authorizationCodeServices; - - private ImplicitGrantService implicitGrantService = new InMemoryImplicitGrantService(); - - private TokenStore tokenStore; - - private TokenEnhancer tokenEnhancer; - - private ApprovalStore approvalStore; - - private TokenGranter tokenGranter; - - private OAuth2RequestFactory requestFactory; - - private OAuth2RequestValidator requestValidator; - - private UserApprovalHandler userApprovalHandler; - - private AuthenticationManager authenticationManager; - - private ClientDetailsService clientDetailsService; - private String realm = "oauth2/client"; - private Map patternMap = new HashMap(); - - private FrameworkEndpointHandlerMapping frameworkEndpointHandlerMapping; - private boolean allowFormAuthenticationForClients = false; - private boolean approvalStoreDisabled; - - private ClientDetailsService clientDetails() { - return getBuilder().getSharedObject(ClientDetailsService.class); - } - - public AuthorizationServerTokenServices getTokenServices() { - return tokenServices; - } - - public TokenStore getTokenStore() { - return tokenStore; - } - - public TokenEnhancer getTokenEnhancer() { - return tokenEnhancer; - } - - public ApprovalStore getApprovalStore() { - return approvalStore; - } - - public ClientDetailsService getClientDetailsService() { - return clientDetailsService; - } - - public OAuth2RequestFactory getOAuth2RequestFactory() { - return requestFactory; - } - - public OAuth2RequestValidator getOAuth2RequestValidator() { - return requestValidator; - } - - public UserApprovalHandler getUserApprovalHandler() { - return userApprovalHandler; - } - public AuthorizationServerSecurityConfigurer allowFormAuthenticationForClients() { this.allowFormAuthenticationForClients = true; return this; } - public AuthorizationServerSecurityConfigurer tokenStore(TokenStore tokenStore) { - this.tokenStore = tokenStore; - return this; - } - - public AuthorizationServerSecurityConfigurer tokenEnhancer(TokenEnhancer tokenEnhancer) { - this.tokenEnhancer = tokenEnhancer; - return this; - } - - public AuthorizationServerSecurityConfigurer tokenServices(AuthorizationServerTokenServices tokenServices) { - this.tokenServices = tokenServices; - return this; - } - - public AuthorizationServerSecurityConfigurer userApprovalHandler(UserApprovalHandler approvalHandler) { - this.userApprovalHandler = approvalHandler; - return this; - } - - public AuthorizationServerSecurityConfigurer approvalStore(ApprovalStore approvalStore) { - if (approvalStoreDisabled) { - throw new IllegalStateException("ApprovalStore was disabled"); - } - this.approvalStore = approvalStore; - return this; - } - - public AuthorizationServerSecurityConfigurer approvalStoreDisabled() { - this.approvalStoreDisabled = true; - return this; - } - public AuthorizationServerSecurityConfigurer realm(String realm) { this.realm = realm; return this; } - public AuthorizationServerSecurityConfigurer pathMapping(String defaultPath, String customPath) { - this.patternMap.put(defaultPath, customPath); - return this; - } - public AuthorizationServerSecurityConfigurer authenticationEntryPoint( AuthenticationEntryPoint authenticationEntryPoint) { this.authenticationEntryPoint = authenticationEntryPoint; return this; } - public AuthorizationServerSecurityConfigurer authenticationManager(AuthenticationManager authenticationManager) { - this.authenticationManager = authenticationManager; - return this; - } - - public AuthorizationServerSecurityConfigurer tokenGranter(TokenGranter tokenGranter) { - this.tokenGranter = tokenGranter; - return this; - } - - public AuthorizationServerSecurityConfigurer clientDetailsService(ClientDetailsService clientDetailsService) { - this.clientDetailsService = clientDetailsService; - return this; - } - - public AuthorizationServerSecurityConfigurer requestFactory(OAuth2RequestFactory requestFactory) { - this.requestFactory = requestFactory; - return this; - } - - public AuthorizationServerSecurityConfigurer requestValidator(OAuth2RequestValidator requestValidator) { - this.requestValidator = requestValidator; - return this; - } - - public AuthorizationServerSecurityConfigurer authorizationCodeServices(AuthorizationCodeServices authorizationCodeServices) { - this.authorizationCodeServices = authorizationCodeServices; - return this; - } - @Override public void init(HttpSecurity http) throws Exception { registerDefaultAuthenticationEntryPoint(http); @@ -267,17 +100,11 @@ private void registerDefaultAuthenticationEntryPoint(HttpSecurity http) { @Override public void configure(HttpSecurity http) throws Exception { - this.tokenGranter = tokenGranter(http); - this.consumerTokenServices = consumerTokenServices(http); - this.userApprovalHandler = userApprovalHandler(http); - // ensure this is initialized frameworkEndpointHandlerMapping(); if (allowFormAuthenticationForClients) { clientCredentialsTokenEndpointFilter(http); } - requestValidator(http); - http.exceptionHandling().accessDeniedHandler(accessDeniedHandler); } @@ -291,153 +118,13 @@ private ClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilte http.addFilterBefore(clientCredentialsTokenEndpointFilter, BasicAuthenticationFilter.class); return clientCredentialsTokenEndpointFilter; } - - public ConsumerTokenServices getConsumerTokenServices() { - return consumerTokenServices; - } - - public ImplicitGrantService getImplicitGrantService() { - return implicitGrantService; - } - - private ConsumerTokenServices consumerTokenServices(HttpSecurity http) { - if (consumerTokenServices == null) { - if (tokenStore() != null) { - DefaultTokenServices defaultTokenServices = new DefaultTokenServices(); - defaultTokenServices.setClientDetailsService(clientDetails()); - defaultTokenServices.setTokenStore(tokenStore()); - consumerTokenServices = defaultTokenServices; - } - } - return consumerTokenServices; - } - - private AuthorizationServerTokenServices tokenServices(HttpSecurity http) { - if (tokenServices != null) { - return tokenServices; - } - DefaultTokenServices tokenServices = new DefaultTokenServices(); - tokenServices.setTokenStore(tokenStore()); - tokenServices.setSupportRefreshToken(true); - tokenServices.setClientDetailsService(clientDetails()); - tokenServices.setTokenEnhancer(this.tokenEnhancer); - this.tokenServices = tokenServices; - return tokenServices; - } - - private TokenStore tokenStore() { - if (tokenStore == null && approvalStore == null) { - this.tokenStore = new InMemoryTokenStore(); - } - return this.tokenStore; - } - - private ApprovalStore approvalStore() { - if (approvalStore==null && tokenStore() != null && !isApprovalStoreDisabled()) { - TokenApprovalStore tokenApprovalStore = new TokenApprovalStore(); - tokenApprovalStore.setTokenStore(tokenStore()); - this.approvalStore = tokenApprovalStore; - } - return this.approvalStore; - } - - private boolean isApprovalStoreDisabled() { - return approvalStoreDisabled || (tokenStore() instanceof JwtTokenStore); - } - + private ClientDetailsService clientDetailsService() { - if (clientDetailsService == null) { - this.clientDetailsService = new InMemoryClientDetailsService(); - } - return this.clientDetailsService; - } - - private UserApprovalHandler userApprovalHandler(HttpSecurity http) { - if (userApprovalHandler == null) { - if (approvalStore()!=null) { - ApprovalStoreUserApprovalHandler handler = new ApprovalStoreUserApprovalHandler(); - handler.setApprovalStore(approvalStore()); - handler.setRequestFactory(requestFactory); - handler.setClientDetailsService(clientDetailsService); - this.userApprovalHandler = handler; - } - else if (tokenStore() != null) { - TokenStoreUserApprovalHandler userApprovalHandler = new TokenStoreUserApprovalHandler(); - userApprovalHandler.setTokenStore(tokenStore()); - userApprovalHandler.setClientDetailsService(clientDetails()); - userApprovalHandler.setRequestFactory(requestFactory(http)); - this.userApprovalHandler = userApprovalHandler; - } else { - throw new IllegalStateException("Either a TokenStore or an ApprovalStore must be provided"); - } - } - return this.userApprovalHandler; - } - - public AuthorizationCodeServices getAuthorizationCodeServices() { - return authorizationCodeServices; - } - - private AuthorizationCodeServices authorizationCodeServices(HttpSecurity http) { - if (authorizationCodeServices == null) { - authorizationCodeServices = new InMemoryAuthorizationCodeServices(); - } - return authorizationCodeServices; - } - - private OAuth2RequestFactory requestFactory(HttpSecurity http) { - if (requestFactory != null) { - return requestFactory; - } - requestFactory = new DefaultOAuth2RequestFactory(clientDetails()); - return requestFactory; - } - - private OAuth2RequestValidator requestValidator(HttpSecurity http) { - if (requestValidator != null) { - return requestValidator; - } - requestValidator = new DefaultOAuth2RequestValidator(); - return requestValidator; - } - - public TokenGranter getTokenGranter() { - return tokenGranter; - } - - private TokenGranter tokenGranter(HttpSecurity http) throws Exception { - if (tokenGranter == null) { - ClientDetailsService clientDetails = clientDetails(); - AuthorizationServerTokenServices tokenServices = tokenServices(http); - AuthorizationCodeServices authorizationCodeServices = authorizationCodeServices(http); - OAuth2RequestFactory requestFactory = requestFactory(http); - - List tokenGranters = new ArrayList(); - tokenGranters.add(new AuthorizationCodeTokenGranter(tokenServices, authorizationCodeServices, - clientDetails, requestFactory)); - tokenGranters.add(new RefreshTokenGranter(tokenServices, clientDetails, requestFactory)); - ImplicitTokenGranter implicit = new ImplicitTokenGranter(tokenServices, clientDetails, requestFactory); - implicit.setImplicitGrantService(implicitGrantService); - tokenGranters.add(implicit); - tokenGranters.add(new ClientCredentialsTokenGranter(tokenServices, clientDetails, requestFactory)); - if (authenticationManager != null) { - tokenGranters.add(new ResourceOwnerPasswordTokenGranter(authenticationManager, tokenServices, - clientDetails, requestFactory)); - } - tokenGranter = new CompositeTokenGranter(tokenGranters); - } - return tokenGranter; - } - - public FrameworkEndpointHandlerMapping getFrameworkEndpointHandlerMapping() { - return frameworkEndpointHandlerMapping(); + return getBuilder().getSharedObject(ClientDetailsService.class); } private FrameworkEndpointHandlerMapping frameworkEndpointHandlerMapping() { - if (frameworkEndpointHandlerMapping == null) { - frameworkEndpointHandlerMapping = new FrameworkEndpointHandlerMapping(); - frameworkEndpointHandlerMapping.setMappings(patternMap); - } - return frameworkEndpointHandlerMapping; + return getBuilder().getSharedObject(FrameworkEndpointHandlerMapping.class); } + } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java index 0b6f2c560..0e6dca71a 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java @@ -14,6 +14,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.util.Arrays; @@ -39,9 +40,9 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; -import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfiguration; 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.configurers.AuthorizationServerEndpointsConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.ClientDetailsService; @@ -77,7 +78,7 @@ public class AuthorizationServerConfigurationTests { public static List parameters() { return Arrays.asList( // @formatter:off new Object[] { BeanCreationException.class, new Class[] { AuthorizationServerUnconfigured.class } }, - new Object[] { BeanCreationException.class, new Class[] { AuthorizationServerCycle.class } }, + new Object[] { null, new Class[] { AuthorizationServerCycle.class } }, new Object[] { null, new Class[] { AuthorizationServerVanilla.class } }, new Object[] { null, new Class[] { AuthorizationServerDisableApproval.class } }, new Object[] { null, new Class[] { AuthorizationServerExtras.class } }, @@ -164,8 +165,8 @@ protected static class AuthorizationServerCycle extends AuthorizationServerConfi private AuthorizationServerTokenServices tokenServices; @Override - public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { - oauthServer.tokenServices(tokenServices); // Bang! (Cyclic proxy) + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + endpoints.tokenServices(tokenServices); // cycle leads to null here } @Override @@ -179,7 +180,7 @@ public void configure(ClientDetailsServiceConfigurer clients) throws Exception { @Override public void run() { - tokenServices.createAccessToken(null); + assertNull(tokenServices); } } @@ -203,8 +204,8 @@ public void configure(ClientDetailsServiceConfigurer clients) throws Exception { } @Override - public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { - oauthServer.approvalStoreDisabled(); + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + endpoints.approvalStoreDisabled(); } @Override @@ -231,9 +232,14 @@ protected static class AuthorizationServerExtras extends AuthorizationServerConf @Autowired private ApplicationContext context; + @Override + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + endpoints.tokenStore(tokenStore); + } + @Override public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { - oauthServer.tokenStore(tokenStore).realm("sparklr2/client"); + oauthServer.realm("oauth/sparklr"); } @Override @@ -267,8 +273,8 @@ protected static class AuthorizationServerJdbc extends AuthorizationServerConfig private ApplicationContext context; @Override - public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { - oauthServer.tokenStore(new JdbcTokenStore(dataSource())).realm("sparklr2/client"); + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + endpoints.tokenStore(new JdbcTokenStore(dataSource())); } @Override @@ -299,8 +305,8 @@ protected static class AuthorizationServerJwt extends AuthorizationServerConfigu private ClientDetailsService clientDetailsService; @Override - public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { - oauthServer.tokenServices(tokenServices()).realm("sparklr2/client"); + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + endpoints.tokenServices(tokenServices()); } @Bean @@ -332,7 +338,6 @@ public void configure(ClientDetailsServiceConfigurer clients) throws Exception { } } - @Configuration @EnableWebMvcSecurity @EnableAuthorizationServer @@ -342,10 +347,10 @@ protected static class AuthorizationServerApproval extends AuthorizationServerCo @Autowired private ApplicationContext context; - + @Override - public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { - oauthServer.tokenStore(tokenStore); + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + endpoints.tokenStore(tokenStore); } @Override @@ -367,7 +372,7 @@ public void run() { @Configuration @EnableWebMvcSecurity - protected static class AuthorizationServerTypes extends AuthorizationServerConfiguration { + protected static class AuthorizationServerTypes extends AuthorizationServerConfigurerAdapter { @Autowired private AuthorizationServerTokenServices tokenServices; @@ -379,8 +384,8 @@ protected static class AuthorizationServerTypes extends AuthorizationServerConfi private OAuth2RequestFactory requestFactory; @Override - protected void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { - oauthServer.tokenGranter(new ClientCredentialsTokenGranter(tokenServices, clientDetailsService, + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + endpoints.tokenGranter(new ClientCredentialsTokenGranter(tokenServices, clientDetailsService, requestFactory)); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java index a37059866..cd36c6744 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java @@ -16,22 +16,22 @@ import org.junit.Before; import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.mock.web.MockServletContext; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.authentication.AnonymousAuthenticationProvider; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.client.BaseClientDetails; -import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; -import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler; import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; +import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.result.MockMvcResultMatchers; @@ -44,17 +44,20 @@ * */ public class ResourceServerConfigurationTests { - + private static InMemoryTokenStore tokenStore = new InMemoryTokenStore(); + private OAuth2AccessToken token; - private OAuth2Authentication authentication; - + + private OAuth2Authentication authentication; + @Before public void init() { token = new DefaultOAuth2AccessToken("FOO"); ClientDetails client = new BaseClientDetails("client", null, "read", "client_credentials", "ROLE_CLIENT"); - authentication = new OAuth2Authentication(new TokenRequest(null, "client", null, "client_credentials").createOAuth2Request(client ), null); - tokenStore.clear(); + authentication = new OAuth2Authentication( + new TokenRequest(null, "client", null, "client_credentials").createOAuth2Request(client), null); + tokenStore.clear(); } @Test @@ -67,39 +70,23 @@ public void testDefaults() throws Exception { MockMvc mvc = MockMvcBuilders.webAppContextSetup(context) .addFilters(new DelegatingFilterProxy(context.getBean("springSecurityFilterChain", Filter.class))) .build(); - mvc.perform(MockMvcRequestBuilders.get("/")).andExpect(MockMvcResultMatchers.status().isNotFound()); - mvc.perform(MockMvcRequestBuilders.get("/photos")).andExpect(MockMvcResultMatchers.status().isUnauthorized()); - mvc.perform(MockMvcRequestBuilders.get("/photos").header("Authorization", "Bearer FOO")).andExpect(MockMvcResultMatchers.status().isNotFound()); + mvc.perform(MockMvcRequestBuilders.get("/")).andExpect(MockMvcResultMatchers.status().isUnauthorized()); context.close(); } @Configuration + @EnableResourceServer @EnableWebSecurity protected static class ResourceServerContext { - - @Configuration - protected static class Vanilla extends WebSecurityConfigurerAdapter { - @Override - protected void configure(HttpSecurity http) throws Exception { - // @formatter:off - http - .authorizeRequests() - .expressionHandler(new OAuth2WebSecurityExpressionHandler()) - .antMatchers("/**").fullyAuthenticated() - .and() - .requestMatchers() - .antMatchers("/photos/**") - .and() - .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER) - .and() - .exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler()) - .and() - .apply(new ResourceServerSecurityConfigurer()) - .tokenStore(tokenStore); - // @formatter:on - } + @Autowired + protected void init(AuthenticationManagerBuilder builder) { + builder.authenticationProvider(new AnonymousAuthenticationProvider("default")); } + @Bean + public TokenStore tokenStore() { + return tokenStore; + } } } \ No newline at end of file From cbd0f2e7cac80e9a5834d3a6cd67c62a3f42ef7e Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 14 Apr 2014 10:19:25 +0100 Subject: [PATCH 237/831] Remove some more @Beans from endpoints config --- .../sparklr/config/OAuth2ServerConfig.java | 7 ++----- ...orizationServerEndpointsConfiguration.java | 7 ------- ...AuthorizationServerConfigurationTests.java | 21 +++++++++++++++---- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java index acaa0b682..caf66ec1d 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java @@ -38,10 +38,10 @@ import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; import org.springframework.security.oauth2.provider.ClientDetailsService; -import org.springframework.security.oauth2.provider.OAuth2RequestFactory; import org.springframework.security.oauth2.provider.approval.ApprovalStore; import org.springframework.security.oauth2.provider.approval.TokenApprovalStore; import org.springframework.security.oauth2.provider.approval.UserApprovalHandler; +import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory; import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; import org.springframework.security.oauth2.provider.token.TokenStore; @@ -199,9 +199,6 @@ protected static class Stuff { @Autowired private TokenStore tokenStore; - @Autowired - private OAuth2RequestFactory requestFactory; - @Bean public ApprovalStore approvalStore() throws Exception { TokenApprovalStore store = new TokenApprovalStore(); @@ -215,7 +212,7 @@ public ApprovalStore approvalStore() throws Exception { public SparklrUserApprovalHandler userApprovalHandler() throws Exception { SparklrUserApprovalHandler handler = new SparklrUserApprovalHandler(); handler.setApprovalStore(approvalStore()); - handler.setRequestFactory(requestFactory); + handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService)); handler.setClientDetailsService(clientDetailsService); handler.setUseApprovalStore(true); return handler; 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 ea77d5eed..f39eb1681 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 @@ -106,7 +106,6 @@ public AuthorizationEndpoint authorizationEndpoint() throws Exception { return authorizationEndpoint; } - @Bean public ImplicitGrantService implicitGrantService() throws Exception { return endpoints.getImplicitGrantService(); } @@ -116,7 +115,6 @@ public ConsumerTokenServices consumerTokenServices() throws Exception { return endpoints.getConsumerTokenServices(); } - @Bean public AuthorizationServerTokenServices authorizationServerTokenServices() throws Exception { return endpoints.getTokenServices(); } @@ -131,17 +129,14 @@ public TokenEndpoint tokenEndpoint() throws Exception { return tokenEndpoint; } - @Bean public OAuth2RequestFactory oauth2RequestFactory() throws Exception { return endpoints.getOAuth2RequestFactory(); } - @Bean public UserApprovalHandler userApprovalHandler() throws Exception { return endpoints.getUserApprovalHandler(); } - @Bean public OAuth2RequestValidator oauth2RequestValidator() throws Exception { return endpoints.getOAuth2RequestValidator(); } @@ -161,12 +156,10 @@ public FrameworkEndpointHandlerMapping oauth2EndpointHandlerMapping() throws Exc return endpoints.getFrameworkEndpointHandlerMapping(); } - @Bean public AuthorizationCodeServices authorizationCodeServices() throws Exception { return endpoints.getAuthorizationCodeServices(); } - @Bean public TokenGranter tokenGranter() throws Exception { return endpoints.getTokenGranter(); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java index 0e6dca71a..b2e7c8765 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java @@ -47,6 +47,8 @@ import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; +import org.springframework.security.oauth2.provider.approval.DefaultUserApprovalHandler; +import org.springframework.security.oauth2.provider.approval.TokenApprovalStore; import org.springframework.security.oauth2.provider.approval.UserApprovalHandler; import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenGranter; import org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint; @@ -78,7 +80,7 @@ public class AuthorizationServerConfigurationTests { public static List parameters() { return Arrays.asList( // @formatter:off new Object[] { BeanCreationException.class, new Class[] { AuthorizationServerUnconfigured.class } }, - new Object[] { null, new Class[] { AuthorizationServerCycle.class } }, + new Object[] { BeanCreationException.class, new Class[] { AuthorizationServerCycle.class } }, new Object[] { null, new Class[] { AuthorizationServerVanilla.class } }, new Object[] { null, new Class[] { AuthorizationServerDisableApproval.class } }, new Object[] { null, new Class[] { AuthorizationServerExtras.class } }, @@ -232,11 +234,21 @@ protected static class AuthorizationServerExtras extends AuthorizationServerConf @Autowired private ApplicationContext context; + @Bean + public DefaultUserApprovalHandler userApprovalHandler() { + return new DefaultUserApprovalHandler(); + } + + @Bean + public TokenApprovalStore approvalStore() { + return new TokenApprovalStore(); + } + @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { - endpoints.tokenStore(tokenStore); + endpoints.tokenStore(tokenStore).approvalStore(approvalStore()).userApprovalHandler(userApprovalHandler()); } - + @Override public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { oauthServer.realm("oauth/sparklr"); @@ -338,6 +350,7 @@ public void configure(ClientDetailsServiceConfigurer clients) throws Exception { } } + @Configuration @EnableWebMvcSecurity @EnableAuthorizationServer @@ -347,7 +360,7 @@ protected static class AuthorizationServerApproval extends AuthorizationServerCo @Autowired private ApplicationContext context; - + @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.tokenStore(tokenStore); From ef1662b9ce6db07bb1547a341e1c3e9524adb65d Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 14 Apr 2014 10:29:45 +0100 Subject: [PATCH 238/831] Always register a TokenStore if there is none --- ...orizationServerEndpointsConfiguration.java | 56 +++++++++---------- 1 file changed, 25 insertions(+), 31 deletions(-) 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 f39eb1681..3d88de923 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 @@ -42,7 +42,6 @@ import org.springframework.security.oauth2.provider.endpoint.WhitelabelApprovalEndpoint; import org.springframework.security.oauth2.provider.endpoint.WhitelabelErrorEndpoint; import org.springframework.security.oauth2.provider.implicit.ImplicitGrantService; -import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; import org.springframework.security.oauth2.provider.token.ConsumerTokenServices; import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; import org.springframework.security.oauth2.provider.token.TokenStore; @@ -106,19 +105,6 @@ public AuthorizationEndpoint authorizationEndpoint() throws Exception { return authorizationEndpoint; } - public ImplicitGrantService implicitGrantService() throws Exception { - return endpoints.getImplicitGrantService(); - } - - @Bean - public ConsumerTokenServices consumerTokenServices() throws Exception { - return endpoints.getConsumerTokenServices(); - } - - public AuthorizationServerTokenServices authorizationServerTokenServices() throws Exception { - return endpoints.getTokenServices(); - } - @Bean public TokenEndpoint tokenEndpoint() throws Exception { TokenEndpoint tokenEndpoint = new TokenEndpoint(); @@ -128,19 +114,7 @@ public TokenEndpoint tokenEndpoint() throws Exception { tokenEndpoint.setOAuth2RequestValidator(oauth2RequestValidator()); return tokenEndpoint; } - - public OAuth2RequestFactory oauth2RequestFactory() throws Exception { - return endpoints.getOAuth2RequestFactory(); - } - - public UserApprovalHandler userApprovalHandler() throws Exception { - return endpoints.getUserApprovalHandler(); - } - - public OAuth2RequestValidator oauth2RequestValidator() throws Exception { - return endpoints.getOAuth2RequestValidator(); - } - + @Bean public WhitelabelApprovalEndpoint whitelabelApprovalEndpoint() { return new WhitelabelApprovalEndpoint(); @@ -156,11 +130,32 @@ public FrameworkEndpointHandlerMapping oauth2EndpointHandlerMapping() throws Exc return endpoints.getFrameworkEndpointHandlerMapping(); } - public AuthorizationCodeServices authorizationCodeServices() throws Exception { + @Bean + public ConsumerTokenServices consumerTokenServices() throws Exception { + return endpoints.getConsumerTokenServices(); + } + + private ImplicitGrantService implicitGrantService() throws Exception { + return endpoints.getImplicitGrantService(); + } + + private OAuth2RequestFactory oauth2RequestFactory() throws Exception { + return endpoints.getOAuth2RequestFactory(); + } + + private UserApprovalHandler userApprovalHandler() throws Exception { + return endpoints.getUserApprovalHandler(); + } + + private OAuth2RequestValidator oauth2RequestValidator() throws Exception { + return endpoints.getOAuth2RequestValidator(); + } + + private AuthorizationCodeServices authorizationCodeServices() throws Exception { return endpoints.getAuthorizationCodeServices(); } - public TokenGranter tokenGranter() throws Exception { + private TokenGranter tokenGranter() throws Exception { return endpoints.getTokenGranter(); } @@ -181,8 +176,7 @@ protected static class TokenStoreRegistrar implements BeanDefinitionRegistryPost // pre-empting a bean specified by the user) @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { - if (!registry.containsBeanDefinition(TOKEN_STORE_BEAN_NAME) - && !registry.containsBeanDefinition(APPROVAL_STORE_BEAN_NAME)) { + if (!registry.containsBeanDefinition(TOKEN_STORE_BEAN_NAME)) { registry.registerBeanDefinition(TOKEN_STORE_BEAN_NAME, new RootBeanDefinition(InMemoryTokenStore.class)); } } From 5dcaab98e554f24dc3ffc2f52c6893cfdfe7f30d Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 14 Apr 2014 10:49:47 +0100 Subject: [PATCH 239/831] Use convenience methods in OAuth2RequestFactory where possible --- ...ntAuthenticationProcessingFilterTests.java | 4 +-- .../provider/OAuth2AuthenticationTests.java | 5 ++- .../oauth2/provider/RequestTokenFactory.java | 15 ++++++--- .../AuthorizationCodeServicesBaseTests.java | 32 +++++++++---------- .../AuthorizationCodeTokenGranterTests.java | 4 +-- ...2MethodSecurityExpressionHandlerTests.java | 16 +++++----- .../OAuth2SecurityExpressionMethodsTests.java | 16 +++++----- ...uth2WebSecurityExpressionHandlerTests.java | 4 +-- .../AbstractTestDefaultTokenServices.java | 8 ++--- ...DefaultTokenServicesWithInMemoryTests.java | 20 ++++++++---- .../token/InMemoryTokenStoreTests.java | 6 ++-- .../provider/token/TokenStoreBaseTests.java | 24 +++++++------- .../oauth2/provider/vote/ScopeVoterTests.java | 10 +++--- 13 files changed, 88 insertions(+), 76 deletions(-) diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilterTests.java index 216d554b5..1d6039e0f 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilterTests.java @@ -32,8 +32,8 @@ import org.springframework.security.oauth2.client.http.AccessTokenRequiredException; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.RequestTokenFactory; import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.RequestTokenFactory; import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices; public class OAuth2ClientAuthenticationProcessingFilterTests { @@ -54,7 +54,7 @@ public void testAuthentication() throws Exception { Mockito.when(restTemplate.getAccessToken()).thenReturn(new DefaultOAuth2AccessToken("FOO")); Set scopes = new HashSet(); scopes.addAll(Arrays.asList("read", "write")); - OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "client", null, false, scopes, null, null, null, null); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request("client", false, scopes); this.authentication = new OAuth2Authentication(storedOAuth2Request, null); Mockito.when(tokenServices.loadAuthentication("FOO")).thenReturn(authentication); Authentication authentication = filter.attemptAuthentication(null, null); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/OAuth2AuthenticationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/OAuth2AuthenticationTests.java index 354a37e39..402362ed8 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/OAuth2AuthenticationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/OAuth2AuthenticationTests.java @@ -24,8 +24,7 @@ public class OAuth2AuthenticationTests { @Test @Rollback public void testIsAuthenticated() { - request = RequestTokenFactory.createOAuth2Request(null, "id", null, true, Collections.singleton("read"), null, - null, null, null); + request = RequestTokenFactory.createOAuth2Request("id", true, Collections.singleton("read")); OAuth2Authentication authentication = new OAuth2Authentication(request, userAuthentication); assertTrue(authentication.isAuthenticated()); } @@ -57,7 +56,7 @@ public void testJsonSerialization() throws Exception { @Test public void testSerialization() { OAuth2Authentication holder = new OAuth2Authentication( - new AuthorizationRequest("client", Arrays.asList("read")).createOAuth2Request(), + new AuthorizationRequest("client", Arrays.asList("read")).createOAuth2Request(), new UsernamePasswordAuthenticationToken("user", "pwd")); OAuth2Authentication other = (OAuth2Authentication) SerializationUtils.deserialize(SerializationUtils .serialize(holder)); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/RequestTokenFactory.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/RequestTokenFactory.java index 60cbf28cb..0249795fc 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/RequestTokenFactory.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/RequestTokenFactory.java @@ -15,6 +15,7 @@ import java.io.Serializable; import java.util.Collection; +import java.util.Collections; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; @@ -31,9 +32,10 @@ public class RequestTokenFactory { public static OAuth2Request createOAuth2Request(Map requestParameters, String clientId, Collection authorities, boolean approved, Collection scope, - Set resourceIds, String redirectUri, Set responseTypes, Map extensionProperties) { - return new OAuth2Request(requestParameters, clientId, authorities, approved, scope==null ? null : new LinkedHashSet(scope), resourceIds, redirectUri, - responseTypes, extensionProperties); + Set resourceIds, String redirectUri, Set responseTypes, + Map extensionProperties) { + return new OAuth2Request(requestParameters, clientId, authorities, approved, scope == null ? null + : new LinkedHashSet(scope), resourceIds, redirectUri, responseTypes, extensionProperties); } public static OAuth2Request createOAuth2Request(String clientId, boolean approved) { @@ -41,7 +43,12 @@ public static OAuth2Request createOAuth2Request(String clientId, boolean approve } public static OAuth2Request createOAuth2Request(String clientId, boolean approved, Collection scope) { - return createOAuth2Request(null, clientId, null, approved, scope, null, null, null, null); + return createOAuth2Request(Collections. emptyMap(), clientId, approved, scope); + } + + public static OAuth2Request createOAuth2Request(Map parameters, String clientId, boolean approved, + Collection scope) { + return createOAuth2Request(parameters, clientId, null, approved, scope, null, null, null, null); } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeServicesBaseTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeServicesBaseTests.java index c13dbf6d9..34b320772 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeServicesBaseTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeServicesBaseTests.java @@ -8,8 +8,8 @@ import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.RequestTokenFactory; import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.RequestTokenFactory; public abstract class AuthorizationCodeServicesBaseTests { @@ -17,35 +17,32 @@ public abstract class AuthorizationCodeServicesBaseTests { @Test public void testCreateAuthorizationCode() { - OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null, null); - OAuth2Authentication expectedAuthentication = new OAuth2Authentication( - storedOAuth2Request, new TestAuthentication( - "test2", false)); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request("id", false); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(storedOAuth2Request, + new TestAuthentication("test2", false)); String code = getAuthorizationCodeServices().createAuthorizationCode(expectedAuthentication); assertNotNull(code); - OAuth2Authentication actualAuthentication = getAuthorizationCodeServices() - .consumeAuthorizationCode(code); + OAuth2Authentication actualAuthentication = getAuthorizationCodeServices().consumeAuthorizationCode(code); assertEquals(expectedAuthentication, actualAuthentication); } @Test public void testConsumeRemovesCode() { - OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null, null); - OAuth2Authentication expectedAuthentication = new OAuth2Authentication( - storedOAuth2Request, new TestAuthentication( - "test2", false)); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request("id", false); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(storedOAuth2Request, + new TestAuthentication("test2", false)); String code = getAuthorizationCodeServices().createAuthorizationCode(expectedAuthentication); assertNotNull(code); - OAuth2Authentication actualAuthentication = getAuthorizationCodeServices() - .consumeAuthorizationCode(code); + OAuth2Authentication actualAuthentication = getAuthorizationCodeServices().consumeAuthorizationCode(code); assertEquals(expectedAuthentication, actualAuthentication); try { getAuthorizationCodeServices().consumeAuthorizationCode(code); fail("Should have thrown exception"); - } catch (InvalidGrantException e) { + } + catch (InvalidGrantException e) { // good we expected this } } @@ -55,7 +52,8 @@ public void testConsumeNonExistingCode() { try { getAuthorizationCodeServices().consumeAuthorizationCode("doesnt exist"); fail("Should have thrown exception"); - } catch (InvalidGrantException e) { + } + catch (InvalidGrantException e) { // good we expected this } } @@ -63,7 +61,9 @@ public void testConsumeNonExistingCode() { protected static class TestAuthentication extends AbstractAuthenticationToken { private static final long serialVersionUID = 1L; + private String principal; + public TestAuthentication(String name, boolean authenticated) { super(null); setAuthenticated(authenticated); @@ -73,7 +73,7 @@ public TestAuthentication(String name, boolean authenticated) { public Object getCredentials() { return null; } - + public Object getPrincipal() { return this.principal; } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranterTests.java index a27b75af4..df59c7e3d 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranterTests.java @@ -78,7 +78,7 @@ public void testAuthorizationCodeGrant() { parameters.clear(); parameters.put(OAuth2Utils.CLIENT_ID, "foo"); parameters.put(OAuth2Utils.SCOPE, "scope"); - OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(parameters, "foo", null, true, Collections.singleton("scope"), null, null, null, null); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(parameters, "foo", true, Collections.singleton("scope")); String code = authorizationCodeServices.createAuthorizationCode(new OAuth2Authentication( storedOAuth2Request, userAuthentication)); @@ -100,7 +100,7 @@ public void testAuthorizationParametersPreserved() { parameters.put("foo", "bar"); parameters.put(OAuth2Utils.CLIENT_ID, "foo"); parameters.put(OAuth2Utils.SCOPE, "scope"); - OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(parameters, "foo", null, true, Collections.singleton("scope"), null, null, null, null); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(parameters, "foo", true, Collections.singleton("scope")); Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2MethodSecurityExpressionHandlerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2MethodSecurityExpressionHandlerTests.java index 50c88b48c..a5f6eddc2 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2MethodSecurityExpressionHandlerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2MethodSecurityExpressionHandlerTests.java @@ -104,8 +104,8 @@ public void testOauthClient() throws Exception { @Test public void testScopes() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, - Collections.singleton("read"), null, null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request("foo", false, + Collections.singleton("read")); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); @@ -119,8 +119,8 @@ public void testScopes() throws Exception { @Test public void testScopesRegex() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, - Collections.singleton("ns_admin:read"), null, null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request("foo", false, + Collections.singleton("ns_admin:read")); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); @@ -138,8 +138,8 @@ public void testScopesRegex() throws Exception { @Test(expected = AccessDeniedException.class) public void testScopesRegexThrowsException() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, - Collections.singleton("ns_admin:read"), null, null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request("foo", false, + Collections.singleton("ns_admin:read")); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); @@ -181,8 +181,8 @@ public void testReEvaluationWithDifferentRoot() throws Exception { EvaluationContext context = handler.createEvaluationContext(clientAuthentication, invocation); assertFalse((Boolean) expression.getValue(context)); - OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "foo", null, true, - Collections.singleton("read"), null, null, null, null); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request("foo", true, + Collections.singleton("read")); OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(storedOAuth2Request, null); EvaluationContext anotherContext = handler.createEvaluationContext(oAuth2Authentication, invocation); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethodsTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethodsTests.java index d72244d45..87e400d6f 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethodsTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethodsTests.java @@ -55,7 +55,7 @@ public void testOauthClient() throws Exception { @Test public void testScopes() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request("foo", false, Collections.singleton("read")); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); @@ -65,7 +65,7 @@ public void testScopes() throws Exception { @Test public void testScopesFalse() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request("foo", false, Collections.singleton("read")); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); @@ -75,7 +75,7 @@ public void testScopesFalse() throws Exception { @Test(expected = AccessDeniedException.class) public void testScopesWithException() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request("foo", false, Collections.singleton("read")); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); @@ -86,7 +86,7 @@ public void testScopesWithException() throws Exception { @Test(expected = AccessDeniedException.class) public void testInsufficientScope() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request("foo", false, Collections.singleton("read")); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); @@ -97,7 +97,7 @@ public void testInsufficientScope() throws Exception { @Test public void testSufficientScope() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request("foo", false, Collections.singleton("read")); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); @@ -107,7 +107,7 @@ public void testSufficientScope() throws Exception { @Test public void testSufficientScopeWithNoPreviousScopeDecision() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, true, Collections.singleton("read"), null, null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request("foo", true, Collections.singleton("read")); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); @@ -123,7 +123,7 @@ public void testNonOauthClient() throws Exception { @Test public void testClientOnly() throws Exception { - OAuth2Request request = RequestTokenFactory.createOAuth2Request(null, "foo", null, true, Collections.singleton("read"), null, null, null, null); + OAuth2Request request = RequestTokenFactory.createOAuth2Request("foo", true, Collections.singleton("read")); Authentication userAuthentication = new UsernamePasswordAuthenticationToken("foo", "bar", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"))); @@ -134,7 +134,7 @@ public void testClientOnly() throws Exception { @Test public void testOAuthUser() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, true, Collections.singleton("read"), null, null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request("foo", true, Collections.singleton("read")); Authentication userAuthentication = new UsernamePasswordAuthenticationToken("foo", "bar", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"))); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2WebSecurityExpressionHandlerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2WebSecurityExpressionHandlerTests.java index caeb4eae3..d866755e3 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2WebSecurityExpressionHandlerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2WebSecurityExpressionHandlerTests.java @@ -81,8 +81,8 @@ public void testOauthClient() throws Exception { @Test public void testScopes() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, - Collections.singleton("read"), null, null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request("foo", false, + Collections.singleton("read")); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); FilterInvocation invocation = new FilterInvocation("/foo", "GET"); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractTestDefaultTokenServices.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractTestDefaultTokenServices.java index d465987b3..00924b799 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractTestDefaultTokenServices.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractTestDefaultTokenServices.java @@ -191,14 +191,14 @@ public void testOneAccessTokenPerAuthentication() throws Exception { public void testOneAccessTokenPerUniqueAuthentication() throws Exception { getTokenServices() .createAccessToken( - new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, - Collections.singleton("read"), null, null, null, null), new TestAuthentication("test2", + new OAuth2Authentication(RequestTokenFactory.createOAuth2Request("id", false, + Collections.singleton("read")), new TestAuthentication("test2", false))); assertEquals(1, getAccessTokenCount()); getTokenServices() .createAccessToken( - new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, - Collections.singleton("write"), null, null, null, null), new TestAuthentication( + new OAuth2Authentication(RequestTokenFactory.createOAuth2Request("id", false, + Collections.singleton("write")), new TestAuthentication( "test2", false))); assertEquals(2, getAccessTokenCount()); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithInMemoryTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithInMemoryTests.java index 31a67037a..d9801ff53 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithInMemoryTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithInMemoryTests.java @@ -41,7 +41,8 @@ public class DefaultTokenServicesWithInMemoryTests extends AbstractTestDefaultTo @Test public void testExpiredToken() throws Exception { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request( + "id", false, Collections.singleton("read")), new TestAuthentication("test2", false)); DefaultOAuth2AccessToken firstAccessToken = (DefaultOAuth2AccessToken) getTokenServices().createAccessToken( expectedAuthentication); // Make it expire (and rely on mutable state in volatile token store) @@ -53,7 +54,8 @@ public void testExpiredToken() throws Exception { @Test public void testExpiredRefreshToken() throws Exception { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request( + "id", false, Collections.singleton("read")), new TestAuthentication("test2", false)); DefaultOAuth2AccessToken firstAccessToken = (DefaultOAuth2AccessToken) getTokenServices().createAccessToken( expectedAuthentication); assertNotNull(firstAccessToken.getRefreshToken()); @@ -69,7 +71,8 @@ public void testExpiredRefreshToken() throws Exception { @Test public void testExpiredRefreshTokenIsRenewedWithNewAccessToken() throws Exception { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request( + "id", false, Collections.singleton("read")), new TestAuthentication("test2", false)); DefaultOAuth2AccessToken firstAccessToken = (DefaultOAuth2AccessToken) getTokenServices().createAccessToken( expectedAuthentication); assertNotNull(firstAccessToken.getRefreshToken()); @@ -96,7 +99,8 @@ public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exceptio return client; } }); - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request( + "id", false, Collections.singleton("read")), new TestAuthentication("test2", false)); DefaultOAuth2AccessToken firstAccessToken = (DefaultOAuth2AccessToken) getTokenServices().createAccessToken( expectedAuthentication); OAuth2RefreshToken expectedExpiringRefreshToken = firstAccessToken.getRefreshToken(); @@ -109,8 +113,9 @@ public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exceptio assertEquals("The new access token should have the same refresh token", expectedExpiringRefreshToken.getValue(), secondAccessToken.getRefreshToken().getValue()); // refresh access token with refresh token - - TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap("client_id", "id"), "id", Collections.singleton("read"), null); + + TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap("client_id", "id"), "id", + Collections.singleton("read"), null); getTokenServices().refreshAccessToken(expectedExpiringRefreshToken.getValue(), tokenRequest); assertEquals(1, getAccessTokenCount()); } @@ -127,7 +132,8 @@ public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exceptio return client; } }); - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, Collections.singleton("read"), null, null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request( + "id", false, Collections.singleton("read")), new TestAuthentication("test2", false)); DefaultOAuth2AccessToken token = (DefaultOAuth2AccessToken) getTokenServices().createAccessToken( expectedAuthentication); assertNull(token.getRefreshToken()); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStoreTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStoreTests.java index ab4bbd37f..a6e82d331 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStoreTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStoreTests.java @@ -31,7 +31,7 @@ public void createStore() { @Test public void testTokenCountConsistency() throws Exception { for (int i = 0; i <= 10; i++) { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id" + i, null, false, null, null, null, null, null), new TestAuthentication("test", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request("id" + i, false), new TestAuthentication("test", false)); DefaultOAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken" + i); expectedOAuth2AccessToken.setExpiration(new Date(System.currentTimeMillis() - 1000)); if (i > 1) { @@ -43,7 +43,7 @@ public void testTokenCountConsistency() throws Exception { @Test public void testTokenCountConsistentWithExpiryQueue() throws Exception { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null, null), new TestAuthentication("test", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request("id", false), new TestAuthentication("test", false)); DefaultOAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); expectedOAuth2AccessToken.setExpiration(new Date(System.currentTimeMillis()+10000)); for (int i = 0; i <= 10; i++) { @@ -56,7 +56,7 @@ public void testTokenCountConsistentWithExpiryQueue() throws Exception { public void testAutoFlush() throws Exception { getTokenStore().setFlushInterval(3); for (int i = 0; i <= 10; i++) { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id" + i, null, false, null, null, null, null, null), new TestAuthentication("test", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request("id" + i, false), new TestAuthentication("test", false)); DefaultOAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken" + i); expectedOAuth2AccessToken.setExpiration(new Date(System.currentTimeMillis() - 1000)); if (i > 2) { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenStoreBaseTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenStoreBaseTests.java index db4d28e9e..13e56a548 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenStoreBaseTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenStoreBaseTests.java @@ -28,8 +28,8 @@ 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.RequestTokenFactory; import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.RequestTokenFactory; /** * @author Dave Syer @@ -46,7 +46,7 @@ public void testReadingAuthenticationForTokenThatDoesNotExist() { @Test public void testStoreAccessToken() { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request("id", false), new TestAuthentication("test2", false)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); @@ -60,7 +60,7 @@ public void testStoreAccessToken() { @Test public void testStoreAccessTokenTwice() { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request( "id", false), new TestAuthentication("test2", false)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); @@ -76,13 +76,13 @@ public void testStoreAccessTokenTwice() { @Test public void testRetrieveAccessToken() { //Test approved request - OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "id", null, true, null, null, null, null, null); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request("id", true); OAuth2Authentication authentication = new OAuth2Authentication(storedOAuth2Request, new TestAuthentication("test2", true)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, authentication); //Test unapproved request - storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null, null); + storedOAuth2Request = RequestTokenFactory.createOAuth2Request("id", false); authentication = new OAuth2Authentication(storedOAuth2Request, new TestAuthentication("test2", true)); OAuth2AccessToken actualOAuth2AccessToken = getTokenStore().getAccessToken(authentication); assertEquals(expectedOAuth2AccessToken, actualOAuth2AccessToken); @@ -99,7 +99,7 @@ public void testRetrieveAccessToken() { @Test public void testFindAccessTokensByUserName() { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request("id", false), new TestAuthentication("test2", false)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); @@ -109,7 +109,7 @@ public void testFindAccessTokensByUserName() { @Test public void testFindAccessTokensByClientId() { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request("id", false), new TestAuthentication("test2", false)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); @@ -124,7 +124,7 @@ public void testReadingAccessTokenForTokenThatDoesNotExist() { @Test public void testRefreshTokenIsNotStoredDuringAccessToken() { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request("id", false), new TestAuthentication("test2", false)); DefaultOAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); expectedOAuth2AccessToken.setRefreshToken(new DefaultOAuth2RefreshToken("refreshToken")); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); @@ -139,7 +139,7 @@ public void testRefreshTokenIsNotStoredDuringAccessToken() { public void testStoreRefreshToken() { DefaultOAuth2RefreshToken expectedExpiringRefreshToken = new DefaultExpiringOAuth2RefreshToken("testToken", new Date()); - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request("id", false), new TestAuthentication("test2", false)); getTokenStore().storeRefreshToken(expectedExpiringRefreshToken, expectedAuthentication); OAuth2RefreshToken actualExpiringRefreshToken = getTokenStore().readRefreshToken("testToken"); @@ -158,7 +158,7 @@ public void testReadingRefreshTokenForTokenThatDoesNotExist() { @Test public void testGetAccessTokenForDeletedUser() throws Exception { //Test approved request - OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "id", null, true, null, null, null, null, null); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request("id", true); OAuth2Authentication expectedAuthentication = new OAuth2Authentication(storedOAuth2Request, new TestAuthentication("test", true)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); @@ -166,7 +166,7 @@ public void testGetAccessTokenForDeletedUser() throws Exception { assertEquals(expectedAuthentication, getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue())); //Test unapproved request - storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null, null); + storedOAuth2Request = RequestTokenFactory.createOAuth2Request("id", false); OAuth2Authentication anotherAuthentication = new OAuth2Authentication(storedOAuth2Request, new TestAuthentication("test", true)); assertEquals(expectedOAuth2AccessToken, getTokenStore().getAccessToken(anotherAuthentication)); // The generated key for the authentication is the same as before, but the two auths are not equal. This could @@ -181,7 +181,7 @@ public void testGetAccessTokenForDeletedUser() throws Exception { public void testRemoveRefreshToken() { OAuth2RefreshToken expectedExpiringRefreshToken = new DefaultExpiringOAuth2RefreshToken("testToken", new Date()); - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, null, null, null, null, null), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request("id", false), new TestAuthentication("test2", false)); getTokenStore().storeRefreshToken(expectedExpiringRefreshToken, expectedAuthentication); getTokenStore().removeRefreshToken(expectedExpiringRefreshToken); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/ScopeVoterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/ScopeVoterTests.java index b551445de..e54397109 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/ScopeVoterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/ScopeVoterTests.java @@ -51,7 +51,7 @@ public void testAbstainIfNotOAuth2() throws Exception { @Test public void testDenyIfOAuth2AndExplictlyDenied() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request("foo", false, Collections.singleton("read")); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); assertEquals( @@ -62,7 +62,7 @@ public void testDenyIfOAuth2AndExplictlyDenied() throws Exception { @Test public void testAccessGrantedIfScopesPresent() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request("foo", false, Collections.singleton("read")); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); assertEquals( @@ -74,7 +74,7 @@ public void testAccessGrantedIfScopesPresent() throws Exception { @Test public void testAccessGrantedIfScopesPresentWithPrefix() throws Exception { voter.setScopePrefix("scope="); - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request("foo", false, Collections.singleton("read")); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); assertEquals( @@ -85,7 +85,7 @@ public void testAccessGrantedIfScopesPresentWithPrefix() throws Exception { @Test public void testAccessDeniedIfWrongScopesPresent() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request("foo", false, Collections.singleton("read")); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); voter.setThrowException(false); @@ -97,7 +97,7 @@ public void testAccessDeniedIfWrongScopesPresent() throws Exception { @Test(expected = AccessDeniedException.class) public void testExceptionThrownIfWrongScopesPresent() throws Exception { - OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request(null, "foo", null, false, Collections.singleton("read"), null, null, null, null); + OAuth2Request clientAuthentication = RequestTokenFactory.createOAuth2Request("foo", false, Collections.singleton("read")); Authentication userAuthentication = null; OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(clientAuthentication, userAuthentication); assertEquals( From 697e8d007952c38913228c76356344626446c04f Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 14 Apr 2014 19:32:46 -0700 Subject: [PATCH 240/831] JwtTokenEnhancer -> JwtAccessTokenConverter --- docs/oauth2.md | 8 +++++++- .../oauth2/provider/token/AccessTokenConverter.java | 2 +- ...TokenEnhancer.java => JwtAccessTokenConverter.java} | 10 +++++++--- .../security/oauth2/provider/token/JwtTokenStore.java | 8 ++++---- .../AuthorizationServerConfigurationTests.java | 6 +++--- .../oauth2/provider/token/JwtTokenEnhancerTests.java | 4 ++-- .../oauth2/provider/token/JwtTokenStoreTests.java | 2 +- .../token/TokenServicesWithTokenEnhancerTests.java | 2 +- 8 files changed, 26 insertions(+), 16 deletions(-) rename spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/{JwtTokenEnhancer.java => JwtAccessTokenConverter.java} (95%) diff --git a/docs/oauth2.md b/docs/oauth2.md index 29217f902..9b354da6c 100644 --- a/docs/oauth2.md +++ b/docs/oauth2.md @@ -63,7 +63,13 @@ The [`AuthorizationServerTokenServices`][AuthorizationServerTokenServices] inter * When an access token is created, the authentication must be stored so that the subsequent access token can reference it. * The access token is used to load the authentication that was used to authorize its creation. -When creating your `AuthorizationServerTokenServices` implementation, you may want to consider using the [`DefaultTokenServices`][DefaultTokenServices] which creates tokens via random value and handles everything except for the persistence of the tokens which it delegates to a `TokenStore`. The default store is an [in-memory implementation][InMemoryTokenStore], but there is also a [jdbc version](JdbcTokenStore) that may be suitable for your needs. +When creating your `AuthorizationServerTokenServices` implementation, you may want to consider using the [`DefaultTokenServices`][DefaultTokenServices] which creates tokens via random value and handles everything except for the persistence of the tokens which it delegates to a `TokenStore`. The default store is an [in-memory implementation][InMemoryTokenStore], but there are some other implementations available. Here's a description with some discussion of each of them + +* The default `InMemoryTokenStore` is perfectly fine for a single server (i.e. low traffic and no hot swap to a backup server in the case of failure). Most projects can start here, and maybe operate this way in development mode, to make it easy to start a server with no dependencies. + +* The `JdbcTokenStore` is the [JDBC version](JdbcTokenStore) of the same thing, which stores token data in a relational database. Use the JDBC version if you can share a database between servers, either scaled up instances of the same server if there is only one, or the Authorization and Resources Servers if there are multiple components. To use the `JdbcTokenStore` you need "spring-jdbc" on the classpath. + +* The [JSON Web Token (JWT) version](`JwtTokenStore`) of the store encodes all the data about the grant into the token itself (so no back end store at all which is a significant advantage). One disadvantage is that you can't easily revoke an access token (so they normally are granted with short expiry and the revocation is handled at the refresh token). Another disadvantage is that the tokens can get quite large if you are storing a lot of user credential information in them. The `JwtTokenStore` is not really a "store" in the sense that it doesn't persist any datam but it plays the same role of translating betweeen token values and authentication information in the `DefaultTokenServices`. Note that the `JwtTokenStore` has a dependency on a `JwtAccessTokenConverter`, and the same implementation is needed by both the Authorization Server and the Resource Server (so they can agree on the contents and decode them safely). The tokens are signed by default, and the Resource Server has to be able to verify the signature, so it either needs the same symmetric (signing) key as the Authorization Server (shared secret, or symmetric key), or it needs the public key (verifier key) that matches the private key (signing key) in the Authorization (public-private or asymmetric key). To use the `JwtTokenStore` you need "spring-security-jwt" on your classpath (you can find it in the same github repository as Spring OAuth but with a different release cycle). ### Grant Types diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AccessTokenConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AccessTokenConverter.java index cb810237a..dbb8abd96 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AccessTokenConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AccessTokenConverter.java @@ -31,7 +31,7 @@ public interface AccessTokenConverter { final String EXP = "exp"; - final String JTI = JwtTokenEnhancer.TOKEN_ID; + final String JTI = JwtAccessTokenConverter.TOKEN_ID; final String SCOPE = OAuth2AccessToken.SCOPE; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtAccessTokenConverter.java similarity index 95% rename from spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancer.java rename to spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtAccessTokenConverter.java index 7133d26eb..cc681c06e 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtAccessTokenConverter.java @@ -41,19 +41,23 @@ import org.springframework.util.Assert; /** - * OAuth2 token services that produces JWT encoded token values. + * Helper that translates between JWT encoded token values and OAuth authentication information (in both directions). + * Also acts as a {@link TokenEnhancer} when tokens are granted. + * + * @see TokenEnhancer + * @see AccessTokenConverter * * @author Dave Syer * @author Luke Taylor */ -public class JwtTokenEnhancer implements TokenEnhancer, AccessTokenConverter, InitializingBean { +public class JwtAccessTokenConverter implements TokenEnhancer, AccessTokenConverter, InitializingBean { /** * Field name for token id. */ public static final String TOKEN_ID = "jti"; - private static final Log logger = LogFactory.getLog(JwtTokenEnhancer.class); + private static final Log logger = LogFactory.getLog(JwtAccessTokenConverter.class); private AccessTokenConverter tokenConverter = new DefaultAccessTokenConverter(); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenStore.java index a98d884fd..8374aabda 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenStore.java @@ -33,7 +33,7 @@ * A {@link TokenStore} implementation that just reads data from the tokens themselves. Not really a store since it * never persists anything, and methods like {@link #getAccessToken(OAuth2Authentication)} always return null. But * nevertheless a useful tool since it translates access tokens to and from authentications. Use this wherever a - * {@link TokenStore} is needed, but remember to use the same {@link JwtTokenEnhancer} instance (or one with the same + * {@link TokenStore} is needed, but remember to use the same {@link JwtAccessTokenConverter} instance (or one with the same * verifier) as was used when the tokens were minted. * * @author Dave Syer @@ -41,7 +41,7 @@ */ public class JwtTokenStore implements TokenStore { - private JwtTokenEnhancer jwtTokenEnhancer; + private JwtAccessTokenConverter jwtTokenEnhancer; private ApprovalStore approvalStore; @@ -50,7 +50,7 @@ public class JwtTokenStore implements TokenStore { * * @param jwtTokenEnhancer */ - public JwtTokenStore(JwtTokenEnhancer jwtTokenEnhancer) { + public JwtTokenStore(JwtAccessTokenConverter jwtTokenEnhancer) { this.jwtTokenEnhancer = jwtTokenEnhancer; } @@ -158,7 +158,7 @@ public Collection findTokensByClientId(String clientId) { return Collections.emptySet(); } - public void setTokenEnhancer(JwtTokenEnhancer tokenEnhancer) { + public void setTokenEnhancer(JwtAccessTokenConverter tokenEnhancer) { this.jwtTokenEnhancer = tokenEnhancer; } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java index b2e7c8765..309f31450 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java @@ -56,7 +56,7 @@ import org.springframework.security.oauth2.provider.token.DefaultTokenServices; import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; import org.springframework.security.oauth2.provider.token.JdbcTokenStore; -import org.springframework.security.oauth2.provider.token.JwtTokenEnhancer; +import org.springframework.security.oauth2.provider.token.JwtAccessTokenConverter; import org.springframework.security.oauth2.provider.token.JwtTokenStore; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.test.util.ReflectionTestUtils; @@ -336,8 +336,8 @@ public TokenStore tokenStore() { } @Bean - protected JwtTokenEnhancer jwtTokenEnhancer() { - return new JwtTokenEnhancer(); + protected JwtAccessTokenConverter jwtTokenEnhancer() { + return new JwtAccessTokenConverter(); } @Override diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancerTests.java index 3ebd4c096..3e00ea155 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancerTests.java @@ -36,13 +36,13 @@ */ public class JwtTokenEnhancerTests { - private JwtTokenEnhancer tokenEnhancer; + private JwtAccessTokenConverter tokenEnhancer; private Authentication userAuthentication; @Before public void setUp() throws Exception { - tokenEnhancer = new JwtTokenEnhancer(); + tokenEnhancer = new JwtAccessTokenConverter(); userAuthentication = new TestAuthentication("test2", true); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenStoreTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenStoreTests.java index c7bd55361..79536d60b 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenStoreTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenStoreTests.java @@ -24,7 +24,7 @@ */ public class JwtTokenStoreTests { - private JwtTokenEnhancer enhancer = new JwtTokenEnhancer(); + private JwtAccessTokenConverter enhancer = new JwtAccessTokenConverter(); private JwtTokenStore tokenStore = new JwtTokenStore(enhancer); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenServicesWithTokenEnhancerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenServicesWithTokenEnhancerTests.java index fed14c28d..00e378373 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenServicesWithTokenEnhancerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenServicesWithTokenEnhancerTests.java @@ -40,7 +40,7 @@ public class TokenServicesWithTokenEnhancerTests { private DefaultTokenServices tokenServices = new DefaultTokenServices(); - private JwtTokenEnhancer jwtTokenEnhancer = new JwtTokenEnhancer(); + private JwtAccessTokenConverter jwtTokenEnhancer = new JwtAccessTokenConverter(); private TokenEnhancerChain enhancer = new TokenEnhancerChain(); From 117ff23278b7954efb5507de286b052e89d6f533 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 14 Apr 2014 20:14:24 -0700 Subject: [PATCH 241/831] Raw S3 access to get JWT dependency --- pom.xml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index a2349ce7c..f2dfb59f5 100644 --- a/pom.xml +++ b/pom.xml @@ -93,19 +93,20 @@ bootstrap - spring-milestone + spring-milestones Spring Framework Milestone Repository - http://repo.spring.io/milestone + http://maven.springframework.org.s3.amazonaws.com/milestone - spring-release + spring-releases Spring Framework Release Repository - http://repo.spring.io/release + http://maven.springframework.org.s3.amazonaws.com/release - spring-snapshot - Spring Framework Maven Release Repository - http://repo.spring.io/snapshot + spring-snapshots + Spring Framework Maven Snapshot Repository + http://maven.springframework.org.s3.amazonaws.com/snapshot + true oauth.googlecode.net From c2e3f17b5734a2be346235b193d65ddf9cb6df69 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 14 Apr 2014 20:18:32 -0700 Subject: [PATCH 242/831] Release JWT 1.0.2 --- spring-security-jwt/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-security-jwt/pom.xml b/spring-security-jwt/pom.xml index 308e53a73..4d2a6c984 100755 --- a/spring-security-jwt/pom.xml +++ b/spring-security-jwt/pom.xml @@ -5,7 +5,7 @@ org.springframework.security spring-security-jwt - 1.0.2.BUILD-SNAPSHOT + 1.0.2.RELEASE jar Spring Security JWT Library From 579ea265ca2052be0ca6b25fe4b5755505f204db Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 14 Apr 2014 20:18:56 -0700 Subject: [PATCH 243/831] Update to snapshot --- spring-security-jwt/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-security-jwt/pom.xml b/spring-security-jwt/pom.xml index 4d2a6c984..639ed71e3 100755 --- a/spring-security-jwt/pom.xml +++ b/spring-security-jwt/pom.xml @@ -5,7 +5,7 @@ org.springframework.security spring-security-jwt - 1.0.2.RELEASE + 1.0.3.BUILD-SNAPSHOT jar Spring Security JWT Library From 8d1e947545adad7524f7a5b173a3067efad6c52f Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 15 Apr 2014 05:21:03 -0700 Subject: [PATCH 244/831] Add permitAll() to OPTIONS on token endpoint Fixes gh-184 --- .../AuthorizationServerSecurityConfiguration.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java index 73fa3fda9..5d5c13eeb 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java @@ -22,6 +22,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.core.annotation.Order; +import org.springframework.http.HttpMethod; import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @@ -72,11 +73,14 @@ protected void configure(HttpSecurity http) throws Exception { String tokenEndpointPath = handlerMapping.getPath("/oauth/token"); // @formatter:off http - .authorizeRequests() - .antMatchers(tokenEndpointPath).fullyAuthenticated() - .and() - .requestMatchers() - .antMatchers(tokenEndpointPath); + .authorizeRequests() + .antMatchers(HttpMethod.OPTIONS, tokenEndpointPath).permitAll() + .and() + .authorizeRequests() + .antMatchers(tokenEndpointPath).fullyAuthenticated() + .and() + .requestMatchers() + .antMatchers(tokenEndpointPath); // @formatter:on http.setSharedObject(ClientDetailsService.class, clientDetailsService); } From 61e7720891c924c1de08239618040d9994a8a1e8 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 17 Apr 2014 10:02:17 -0700 Subject: [PATCH 245/831] Refactor TokenServices tests so JWT fits in better --- ...=> AbstractDefaultTokenServicesTests.java} | 196 ++++++------------ ...ctPersistentDefaultTokenServicesTests.java | 121 +++++++++++ ...DefaultTokenServicesWithInMemoryTests.java | 2 +- .../DefaultTokenServicesWithJdbcTests.java | 2 +- .../DefaultTokenServicesWithJwtTests.java | 27 +++ .../provider/token/JwtTokenEnhancerTests.java | 2 +- 6 files changed, 209 insertions(+), 141 deletions(-) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/{AbstractTestDefaultTokenServices.java => AbstractDefaultTokenServicesTests.java} (50%) create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractPersistentDefaultTokenServicesTests.java create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithJwtTests.java diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractTestDefaultTokenServices.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractDefaultTokenServicesTests.java similarity index 50% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractTestDefaultTokenServices.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractDefaultTokenServicesTests.java index 00924b799..18ece652f 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractTestDefaultTokenServices.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractDefaultTokenServicesTests.java @@ -1,7 +1,19 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + package org.springframework.security.oauth2.provider.token; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.util.Arrays; @@ -13,10 +25,8 @@ import org.junit.Test; import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.oauth2.common.DefaultExpiringOAuth2RefreshToken; -import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.common.OAuth2RefreshToken; import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.provider.ClientDetails; @@ -28,9 +38,9 @@ /** * @author Dave Syer - * + * */ -public abstract class AbstractTestDefaultTokenServices { +public abstract class AbstractDefaultTokenServicesTests { private DefaultTokenServices services; @@ -40,75 +50,42 @@ public abstract class AbstractTestDefaultTokenServices { public void setUp() throws Exception { tokenStore = createTokenStore(); services = new DefaultTokenServices(); - getTokenServices().setTokenStore(tokenStore); - getTokenServices().afterPropertiesSet(); - getTokenServices().setSupportRefreshToken(true); - } - - protected abstract TokenStore createTokenStore(); - - @Test - public void testTokenEnhancerUpdatesStoredTokens() throws Exception { - final ExpiringOAuth2RefreshToken refreshToken = new DefaultExpiringOAuth2RefreshToken("testToken", new Date( - System.currentTimeMillis() + 100000)); - getTokenServices().setTokenEnhancer(new TokenEnhancer() { - public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { - DefaultOAuth2AccessToken result = new DefaultOAuth2AccessToken(accessToken); - result.setRefreshToken(refreshToken); - return result; - } - }); - OAuth2Authentication authentication = createAuthentication(); - OAuth2AccessToken original = getTokenServices().createAccessToken(authentication); - assertTrue(original.getRefreshToken().equals(refreshToken)); - OAuth2AccessToken result = tokenStore.getAccessToken(authentication); - assertEquals(original, result); - assertEquals(refreshToken, result.getRefreshToken()); - assertEquals(refreshToken, tokenStore.readRefreshToken(refreshToken.getValue())); + configureTokenServices(services); } @Test - public void testTokenRevoked() throws Exception { - OAuth2Authentication authentication = createAuthentication(); - OAuth2AccessToken original = getTokenServices().createAccessToken(authentication); - tokenStore.removeAccessToken(original); - assertEquals(0, tokenStore.findTokensByClientId(authentication.getOAuth2Request().getClientId()).size()); - } - - @Test - public void testRefreshedTokenIsEnhanced() throws Exception { - getTokenServices().setTokenEnhancer(new TokenEnhancer() { - public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { - DefaultOAuth2AccessToken result = new DefaultOAuth2AccessToken(accessToken); - result.setValue("I'mEnhanced"); - return result; + public void testClientSpecificRefreshTokenExpiry() throws Exception { + getTokenServices().setRefreshTokenValiditySeconds(1000); + getTokenServices().setClientDetailsService(new ClientDetailsService() { + public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exception { + BaseClientDetails client = new BaseClientDetails(); + client.setRefreshTokenValiditySeconds(100); + client.setAuthorizedGrantTypes(Arrays.asList("authorization_code", "refresh_token")); + return client; } }); - OAuth2AccessToken accessToken = getTokenServices().createAccessToken(createAuthentication()); - assertTrue(accessToken.getValue().startsWith("I'mEnhanced")); - TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap("client_id", "id"), "id", null, null); - OAuth2AccessToken refreshedAccessToken = getTokenServices().refreshAccessToken( - accessToken.getRefreshToken().getValue(), tokenRequest); - assertTrue(refreshedAccessToken.getValue().startsWith("I'mEnhanced")); + DefaultExpiringOAuth2RefreshToken refreshToken = (DefaultExpiringOAuth2RefreshToken) accessToken + .getRefreshToken(); + Date expectedExpiryDate = new Date(System.currentTimeMillis() + 102 * 1000L); + assertTrue(expectedExpiryDate.after(refreshToken.getExpiration())); } - @Test - public void testRefreshedTokenHasScopes() throws Exception { - ExpiringOAuth2RefreshToken expectedExpiringRefreshToken = new DefaultExpiringOAuth2RefreshToken("testToken", - new Date(System.currentTimeMillis() + 100000)); - tokenStore.storeRefreshToken(expectedExpiringRefreshToken, createAuthentication()); - TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap("client_id", "id"), "id", null, null); + @Test(expected = InvalidGrantException.class) + public void testRefreshedTokenInvalidWithWrongClient() throws Exception { + ExpiringOAuth2RefreshToken expectedExpiringRefreshToken = (ExpiringOAuth2RefreshToken) getTokenServices() + .createAccessToken(createAuthentication()).getRefreshToken(); + TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap("client_id", "wrong"), "wrong", null, + null); OAuth2AccessToken refreshedAccessToken = getTokenServices().refreshAccessToken( expectedExpiringRefreshToken.getValue(), tokenRequest); - assertEquals("[read, write]", refreshedAccessToken.getScope().toString()); + assertEquals("[read]", refreshedAccessToken.getScope().toString()); } @Test public void testRefreshedTokenHasNarrowedScopes() throws Exception { - ExpiringOAuth2RefreshToken expectedExpiringRefreshToken = new DefaultExpiringOAuth2RefreshToken("testToken", - new Date(System.currentTimeMillis() + 100000)); - tokenStore.storeRefreshToken(expectedExpiringRefreshToken, createAuthentication()); + ExpiringOAuth2RefreshToken expectedExpiringRefreshToken = (ExpiringOAuth2RefreshToken) getTokenServices() + .createAccessToken(createAuthentication()).getRefreshToken(); TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap("client_id", "id"), "id", Collections.singleton("read"), null); OAuth2AccessToken refreshedAccessToken = getTokenServices().refreshAccessToken( @@ -116,16 +93,12 @@ public void testRefreshedTokenHasNarrowedScopes() throws Exception { assertEquals("[read]", refreshedAccessToken.getScope().toString()); } - @Test(expected = InvalidGrantException.class) - public void testRefreshedTokenInvalidWithWrongClient() throws Exception { - ExpiringOAuth2RefreshToken expectedExpiringRefreshToken = new DefaultExpiringOAuth2RefreshToken("testToken", - new Date(System.currentTimeMillis() + 100000)); - tokenStore.storeRefreshToken(expectedExpiringRefreshToken, createAuthentication()); - TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap("client_id", "wrong"), "wrong", null, - null); - OAuth2AccessToken refreshedAccessToken = getTokenServices().refreshAccessToken( - expectedExpiringRefreshToken.getValue(), tokenRequest); - assertEquals("[read]", refreshedAccessToken.getScope().toString()); + @Test + public void testTokenRevoked() throws Exception { + OAuth2Authentication authentication = createAuthentication(); + OAuth2AccessToken original = getTokenServices().createAccessToken(authentication); + getTokenStore().removeAccessToken(original); + assertEquals(0, getTokenStore().findTokensByClientId(authentication.getOAuth2Request().getClientId()).size()); } @Test @@ -158,85 +131,32 @@ public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exceptio } @Test - public void testClientSpecificRefreshTokenExpiry() throws Exception { - getTokenServices().setRefreshTokenValiditySeconds(1000); - getTokenServices().setClientDetailsService(new ClientDetailsService() { - public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exception { - BaseClientDetails client = new BaseClientDetails(); - client.setRefreshTokenValiditySeconds(100); - client.setAuthorizedGrantTypes(Arrays.asList("authorization_code", "refresh_token")); - return client; - } - }); - OAuth2AccessToken accessToken = getTokenServices().createAccessToken(createAuthentication()); - DefaultExpiringOAuth2RefreshToken refreshToken = (DefaultExpiringOAuth2RefreshToken) accessToken - .getRefreshToken(); - Date expectedExpiryDate = new Date(System.currentTimeMillis() + 102 * 1000L); - assertTrue(expectedExpiryDate.after(refreshToken.getExpiration())); - } - - @Test - public void testOneAccessTokenPerAuthentication() throws Exception { - OAuth2Authentication authentication = createAuthentication(); - OAuth2AccessToken first = getTokenServices().createAccessToken(authentication); - assertEquals(1, getAccessTokenCount()); - assertEquals(1, getRefreshTokenCount()); - OAuth2AccessToken second = getTokenServices().createAccessToken(authentication); - assertEquals(first, second); - assertEquals(1, getAccessTokenCount()); - assertEquals(1, getRefreshTokenCount()); - } - - @Test - public void testOneAccessTokenPerUniqueAuthentication() throws Exception { - getTokenServices() - .createAccessToken( - new OAuth2Authentication(RequestTokenFactory.createOAuth2Request("id", false, - Collections.singleton("read")), new TestAuthentication("test2", - false))); - assertEquals(1, getAccessTokenCount()); - getTokenServices() - .createAccessToken( - new OAuth2Authentication(RequestTokenFactory.createOAuth2Request("id", false, - Collections.singleton("write")), new TestAuthentication( - "test2", false))); - assertEquals(2, getAccessTokenCount()); - } - - @Test - public void testRefreshTokenMaintainsState() throws Exception { - getTokenServices().setSupportRefreshToken(true); - OAuth2AccessToken accessToken = getTokenServices().createAccessToken(createAuthentication()); - OAuth2RefreshToken expectedExpiringRefreshToken = accessToken.getRefreshToken(); + public void testRefreshedTokenHasScopes() throws Exception { + ExpiringOAuth2RefreshToken expectedExpiringRefreshToken = (ExpiringOAuth2RefreshToken) getTokenServices() + .createAccessToken(createAuthentication()).getRefreshToken(); TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap("client_id", "id"), "id", null, null); OAuth2AccessToken refreshedAccessToken = getTokenServices().refreshAccessToken( expectedExpiringRefreshToken.getValue(), tokenRequest); - assertNotNull(refreshedAccessToken); - assertEquals(1, getAccessTokenCount()); + assertEquals("[read, write]", refreshedAccessToken.getScope().toString()); } - @Test - public void testNotReuseRefreshTokenMaintainsState() throws Exception { - getTokenServices().setSupportRefreshToken(true); - getTokenServices().setReuseRefreshToken(false); - OAuth2AccessToken accessToken = getTokenServices().createAccessToken(createAuthentication()); - OAuth2RefreshToken expectedExpiringRefreshToken = accessToken.getRefreshToken(); - TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap("client_id", "id"), "id", null, null); - OAuth2AccessToken refreshedAccessToken = getTokenServices().refreshAccessToken( - expectedExpiringRefreshToken.getValue(), tokenRequest); - assertNotNull(refreshedAccessToken); - assertEquals(1, getRefreshTokenCount()); + protected void configureTokenServices(DefaultTokenServices services) throws Exception { + services.setTokenStore(tokenStore); + services.setSupportRefreshToken(true); + services.afterPropertiesSet(); } - private OAuth2Authentication createAuthentication() { + protected abstract TokenStore createTokenStore(); + + protected OAuth2Authentication createAuthentication() { return new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "id", null, false, new LinkedHashSet(Arrays.asList("read", "write")), null, null, null, null), new TestAuthentication("test2", false)); } - protected abstract int getAccessTokenCount(); - - protected abstract int getRefreshTokenCount(); + protected TokenStore getTokenStore() { + return tokenStore; + } protected DefaultTokenServices getTokenServices() { return services; @@ -262,5 +182,5 @@ public Object getPrincipal() { return this.principal; } } - + } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractPersistentDefaultTokenServicesTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractPersistentDefaultTokenServicesTests.java new file mode 100644 index 000000000..4fcac4bb1 --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractPersistentDefaultTokenServicesTests.java @@ -0,0 +1,121 @@ +package org.springframework.security.oauth2.provider.token; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.Collections; +import java.util.Date; + +import org.junit.Test; +import org.springframework.security.oauth2.common.DefaultExpiringOAuth2RefreshToken; +import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; +import org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken; +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.RequestTokenFactory; +import org.springframework.security.oauth2.provider.TokenRequest; + +/** + * @author Dave Syer + * + */ +public abstract class AbstractPersistentDefaultTokenServicesTests extends AbstractDefaultTokenServicesTests { + + @Test + public void testTokenEnhancerUpdatesStoredTokens() throws Exception { + final ExpiringOAuth2RefreshToken refreshToken = new DefaultExpiringOAuth2RefreshToken("testToken", new Date( + System.currentTimeMillis() + 100000)); + getTokenServices().setTokenEnhancer(new TokenEnhancer() { + public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { + DefaultOAuth2AccessToken result = new DefaultOAuth2AccessToken(accessToken); + result.setRefreshToken(refreshToken); + return result; + } + }); + OAuth2Authentication authentication = createAuthentication(); + OAuth2AccessToken original = getTokenServices().createAccessToken(authentication); + assertTrue(original.getRefreshToken().equals(refreshToken)); + OAuth2AccessToken result = getTokenStore().getAccessToken(authentication); + assertEquals(original, result); + assertEquals(refreshToken, result.getRefreshToken()); + assertEquals(refreshToken, getTokenStore().readRefreshToken(refreshToken.getValue())); + } + + @Test + public void testRefreshedTokenIsEnhanced() throws Exception { + getTokenServices().setTokenEnhancer(new TokenEnhancer() { + public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { + DefaultOAuth2AccessToken result = new DefaultOAuth2AccessToken(accessToken); + result.setValue("I'mEnhanced"); + return result; + } + }); + + OAuth2AccessToken accessToken = getTokenServices().createAccessToken(createAuthentication()); + assertTrue(accessToken.getValue().startsWith("I'mEnhanced")); + TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap("client_id", "id"), "id", null, null); + OAuth2AccessToken refreshedAccessToken = getTokenServices().refreshAccessToken( + accessToken.getRefreshToken().getValue(), tokenRequest); + assertTrue(refreshedAccessToken.getValue().startsWith("I'mEnhanced")); + } + + @Test + public void testOneAccessTokenPerAuthentication() throws Exception { + OAuth2Authentication authentication = createAuthentication(); + OAuth2AccessToken first = getTokenServices().createAccessToken(authentication); + assertEquals(1, getAccessTokenCount()); + assertEquals(1, getRefreshTokenCount()); + OAuth2AccessToken second = getTokenServices().createAccessToken(authentication); + assertEquals(first, second); + assertEquals(1, getAccessTokenCount()); + assertEquals(1, getRefreshTokenCount()); + } + + @Test + public void testOneAccessTokenPerUniqueAuthentication() throws Exception { + getTokenServices() + .createAccessToken( + new OAuth2Authentication(RequestTokenFactory.createOAuth2Request("id", false, + Collections.singleton("read")), new TestAuthentication("test2", + false))); + assertEquals(1, getAccessTokenCount()); + getTokenServices() + .createAccessToken( + new OAuth2Authentication(RequestTokenFactory.createOAuth2Request("id", false, + Collections.singleton("write")), new TestAuthentication( + "test2", false))); + assertEquals(2, getAccessTokenCount()); + } + + @Test + public void testRefreshTokenMaintainsState() throws Exception { + getTokenServices().setSupportRefreshToken(true); + OAuth2AccessToken accessToken = getTokenServices().createAccessToken(createAuthentication()); + OAuth2RefreshToken expectedExpiringRefreshToken = accessToken.getRefreshToken(); + TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap("client_id", "id"), "id", null, null); + OAuth2AccessToken refreshedAccessToken = getTokenServices().refreshAccessToken( + expectedExpiringRefreshToken.getValue(), tokenRequest); + assertNotNull(refreshedAccessToken); + assertEquals(1, getAccessTokenCount()); + } + + @Test + public void testNotReuseRefreshTokenMaintainsState() throws Exception { + getTokenServices().setSupportRefreshToken(true); + getTokenServices().setReuseRefreshToken(false); + OAuth2AccessToken accessToken = getTokenServices().createAccessToken(createAuthentication()); + OAuth2RefreshToken expectedExpiringRefreshToken = accessToken.getRefreshToken(); + TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap("client_id", "id"), "id", null, null); + OAuth2AccessToken refreshedAccessToken = getTokenServices().refreshAccessToken( + expectedExpiringRefreshToken.getValue(), tokenRequest); + assertNotNull(refreshedAccessToken); + assertEquals(1, getRefreshTokenCount()); + } + + protected abstract int getAccessTokenCount(); + + protected abstract int getRefreshTokenCount(); + +} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithInMemoryTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithInMemoryTests.java index d9801ff53..71fe892cc 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithInMemoryTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithInMemoryTests.java @@ -32,7 +32,7 @@ * @author Dave Syer * */ -public class DefaultTokenServicesWithInMemoryTests extends AbstractTestDefaultTokenServices { +public class DefaultTokenServicesWithInMemoryTests extends AbstractPersistentDefaultTokenServicesTests { private InMemoryTokenStore tokenStore; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithJdbcTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithJdbcTests.java index 30cde2d72..0862ba0e9 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithJdbcTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithJdbcTests.java @@ -9,7 +9,7 @@ * @author Dave Syer * */ -public class DefaultTokenServicesWithJdbcTests extends AbstractTestDefaultTokenServices { +public class DefaultTokenServicesWithJdbcTests extends AbstractPersistentDefaultTokenServicesTests { private EmbeddedDatabase db; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithJwtTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithJwtTests.java new file mode 100644 index 000000000..53421c054 --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithJwtTests.java @@ -0,0 +1,27 @@ +package org.springframework.security.oauth2.provider.token; + + +/** + * @author Ryan Heaton + * @author Dave Syer + * + */ +public class DefaultTokenServicesWithJwtTests extends AbstractDefaultTokenServicesTests { + + private JwtTokenStore tokenStore; + JwtAccessTokenConverter enhancer = new JwtAccessTokenConverter(); + + @Override + protected TokenStore createTokenStore() { + tokenStore = new JwtTokenStore(enhancer); + return tokenStore; + } + + @Override + protected void configureTokenServices(DefaultTokenServices services) throws Exception { + enhancer.afterPropertiesSet(); + services.setTokenEnhancer(enhancer); + super.configureTokenServices(services); + } + +} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancerTests.java index 3e00ea155..1f8356a3a 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancerTests.java @@ -28,7 +28,7 @@ import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; -import org.springframework.security.oauth2.provider.token.AbstractTestDefaultTokenServices.TestAuthentication; +import org.springframework.security.oauth2.provider.token.AbstractDefaultTokenServicesTests.TestAuthentication; /** * @author Dave Syer From ae6aa8ac45cb8e92a9c415fc42e2b434e4bb9067 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 18 Apr 2014 04:51:43 -0700 Subject: [PATCH 246/831] Use artifactory repos directly --- pom.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index f2dfb59f5..3b16080e3 100644 --- a/pom.xml +++ b/pom.xml @@ -118,9 +118,9 @@ milestone - springframework-milestone + repo.spring.io Spring Milestone Repository - s3://maven.springframework.org/milestone + http://repo.spring.io/libs-milestone-local @@ -346,15 +346,15 @@ - springframework-release + repo.spring.io Spring Release Repository - s3://maven.springframework.org/release + http://repo.spring.io/libs-release-local - springframework-snapshot + repo.spring.io Spring Snapshot Repository - s3://maven.springframework.org/snapshot + http://repo.spring.io/libs-snapshot-local From 46017b2e4b94b719bb7eca933e97e8446491be91 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 18 Apr 2014 04:54:43 -0700 Subject: [PATCH 247/831] [maven-release-plugin] prepare release 2.0.0.RC1 --- pom.xml | 4 ++-- samples/oauth/sparklr/pom.xml | 5 ++--- samples/oauth/tonr/pom.xml | 5 ++--- samples/oauth2/sparklr/pom.xml | 5 ++--- samples/oauth2/tonr/pom.xml | 5 ++--- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 4 ++-- 8 files changed, 14 insertions(+), 18 deletions(-) diff --git a/pom.xml b/pom.xml index 3b16080e3..052d404b7 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.0.BUILD-SNAPSHOT + 2.0.0.RC1 http://static.springframework.org/spring-security/oauth @@ -25,7 +25,7 @@ http://github.com/SpringSource/spring-security-oauth scm:git:git://github.com/SpringSource/spring-security-oauth.git scm:git:ssh://git@github.com/SpringSource/spring-security-oauth.git - HEAD + 2.0.0.RC1 JIRA diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index f53096dea..7956574b4 100644 --- a/samples/oauth/sparklr/pom.xml +++ b/samples/oauth/sparklr/pom.xml @@ -1,12 +1,11 @@ - + 4.0.0 org.springframework.security.oauth spring-security-oauth-parent - 2.0.0.BUILD-SNAPSHOT + 2.0.0.RC1 ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index aff81fae5..4c417b40c 100644 --- a/samples/oauth/tonr/pom.xml +++ b/samples/oauth/tonr/pom.xml @@ -1,12 +1,11 @@ - + 4.0.0 org.springframework.security.oauth spring-security-oauth-parent - 2.0.0.BUILD-SNAPSHOT + 2.0.0.RC1 ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 42cec8296..c2c670d91 100644 --- a/samples/oauth2/sparklr/pom.xml +++ b/samples/oauth2/sparklr/pom.xml @@ -1,12 +1,11 @@ - + 4.0.0 org.springframework.security.oauth spring-security-oauth-parent - 2.0.0.BUILD-SNAPSHOT + 2.0.0.RC1 ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 9975580cf..2db37a727 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -1,12 +1,11 @@ - + 4.0.0 org.springframework.security.oauth spring-security-oauth-parent - 2.0.0.BUILD-SNAPSHOT + 2.0.0.RC1 ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index d88a907a1..8d68cdc3d 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.0.BUILD-SNAPSHOT + 2.0.0.RC1 spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index 473f8e906..7d2d5a09a 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.0.BUILD-SNAPSHOT + 2.0.0.RC1 spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 5b6279304..29fa66bc8 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.0.BUILD-SNAPSHOT + 2.0.0.RC1 spring-security-oauth2 @@ -127,7 +127,7 @@ org.springframework.security spring-security-jwt - ${spring.security.jwt.version} + 1.0.2.RELEASE true From aceebeb052d2e38882e102179488a9c6b0b65789 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 18 Apr 2014 04:54:47 -0700 Subject: [PATCH 248/831] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index 052d404b7..f2ad7be3c 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.0.RC1 + 2.0.1.BUILD-SNAPSHOT http://static.springframework.org/spring-security/oauth @@ -25,7 +25,7 @@ http://github.com/SpringSource/spring-security-oauth scm:git:git://github.com/SpringSource/spring-security-oauth.git scm:git:ssh://git@github.com/SpringSource/spring-security-oauth.git - 2.0.0.RC1 + HEAD JIRA diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index 7956574b4..452c92548 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.0.RC1 + 2.0.1.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index 4c417b40c..a66275bc8 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.0.RC1 + 2.0.1.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index c2c670d91..9944148e6 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.0.RC1 + 2.0.1.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 2db37a727..786cc5140 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.0.RC1 + 2.0.1.BUILD-SNAPSHOT ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index 8d68cdc3d..614ea8696 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.0.RC1 + 2.0.1.BUILD-SNAPSHOT spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index 7d2d5a09a..1e7dbecbe 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.0.RC1 + 2.0.1.BUILD-SNAPSHOT spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 29fa66bc8..589a3589a 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.0.RC1 + 2.0.1.BUILD-SNAPSHOT spring-security-oauth2 From 97e2df11b96a53322577b3cbb67c62bfa51bcd6a Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 18 Apr 2014 06:15:16 -0700 Subject: [PATCH 249/831] Validate client details in DefaultTokenServices.loadAuthentication(token) If the ClientDetailsService is not-null it is used to validate the client still exists and still has access to the scopes in the token. This commit only addresses the existence of the client. Scope checking is something that ought to be ain a strategy and we don't have an appropriate one right now so more thinking required. See gh-185 --- .../provider/token/DefaultTokenServices.java | 10 +++++++ .../AbstractDefaultTokenServicesTests.java | 29 +++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java index 500b36aea..983269d61 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java @@ -29,6 +29,7 @@ import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.ClientRegistrationException; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.TokenRequest; @@ -213,6 +214,15 @@ else if (accessToken.isExpired()) { } OAuth2Authentication result = tokenStore.readAuthentication(accessToken); + if (clientDetailsService != null) { + String clientId = result.getOAuth2Request().getClientId(); + try { + clientDetailsService.loadClientByClientId(clientId); + } + catch (ClientRegistrationException e) { + throw new InvalidTokenException("Client not valid: " + clientId, e); + } + } return result; } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractDefaultTokenServicesTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractDefaultTokenServicesTests.java index 18ece652f..cb8918a44 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractDefaultTokenServicesTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractDefaultTokenServicesTests.java @@ -14,12 +14,14 @@ package org.springframework.security.oauth2.provider.token; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.LinkedHashSet; +import java.util.concurrent.atomic.AtomicBoolean; import org.junit.Before; import org.junit.Test; @@ -28,9 +30,11 @@ import org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; 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.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.ClientRegistrationException; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.RequestTokenFactory; import org.springframework.security.oauth2.provider.TokenRequest; @@ -71,6 +75,27 @@ public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exceptio assertTrue(expectedExpiryDate.after(refreshToken.getExpiration())); } + @Test(expected = InvalidTokenException.class) + public void testClientInvalidated() throws Exception { + final AtomicBoolean deleted = new AtomicBoolean(); + getTokenServices().setClientDetailsService(new ClientDetailsService() { + public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exception { + if (deleted.get()) { + throw new ClientRegistrationException("No such client: " + clientId); + } + BaseClientDetails client = new BaseClientDetails(); + client.setRefreshTokenValiditySeconds(100); + client.setAuthorizedGrantTypes(Arrays.asList("authorization_code", "refresh_token")); + return client; + } + }); + OAuth2AccessToken token = getTokenServices() + .createAccessToken(createAuthentication()); + deleted.set(true); + OAuth2Authentication authentication = getTokenServices().loadAuthentication(token.getValue()); + assertNotNull(authentication.getOAuth2Request()); + } + @Test(expected = InvalidGrantException.class) public void testRefreshedTokenInvalidWithWrongClient() throws Exception { ExpiringOAuth2RefreshToken expectedExpiringRefreshToken = (ExpiringOAuth2RefreshToken) getTokenServices() @@ -142,7 +167,7 @@ public void testRefreshedTokenHasScopes() throws Exception { protected void configureTokenServices(DefaultTokenServices services) throws Exception { services.setTokenStore(tokenStore); - services.setSupportRefreshToken(true); + services.setSupportRefreshToken(true); services.afterPropertiesSet(); } @@ -182,5 +207,5 @@ public Object getPrincipal() { return this.principal; } } - + } From 80520be27a8d1b5af98adb671b7ed8ddbda4a051 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 18 Apr 2014 07:46:05 -0700 Subject: [PATCH 250/831] Fix wrong version id in poms --- pom.xml | 2 +- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index f2ad7be3c..3b16080e3 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.1.BUILD-SNAPSHOT + 2.0.0.BUILD-SNAPSHOT http://static.springframework.org/spring-security/oauth diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index 452c92548..86f09c156 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.1.BUILD-SNAPSHOT + 2.0.0.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index a66275bc8..2de3a9ae1 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.1.BUILD-SNAPSHOT + 2.0.0.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 9944148e6..fea01b7d4 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.1.BUILD-SNAPSHOT + 2.0.0.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 786cc5140..66328cf18 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.1.BUILD-SNAPSHOT + 2.0.0.BUILD-SNAPSHOT ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index 614ea8696..d88a907a1 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.1.BUILD-SNAPSHOT + 2.0.0.BUILD-SNAPSHOT spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index 1e7dbecbe..473f8e906 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.1.BUILD-SNAPSHOT + 2.0.0.BUILD-SNAPSHOT spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 589a3589a..765baaa39 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.1.BUILD-SNAPSHOT + 2.0.0.BUILD-SNAPSHOT spring-security-oauth2 From d3819e2e5414019ab9e5cb1207fc6a54f239dd55 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 18 Apr 2014 15:57:58 -0700 Subject: [PATCH 251/831] Add utility endpoints for token consumers (resource servers) Added /oauth/check_token (POST token=$TOKEN) and /oauth/token_key for token decoding and (JWT only by default) token key sharing. The check_token endpoint always requires client credentials and Basic auth. The token_key endpoint requires client credentials for a shared key and is open if the key is public. Even when authenticated both endpoints are locked down (denyAll()) by default and have to be unlocked by adding tokenKeyAccess() or checkTokenAccess() to the AuthorizationServerSecurityConfigurer. A side effect is a change to the configuration semantics. Formerly apps could declare a @Bean of type TokenStore and not have to explicitly add it to the AuthorizationServerEndpointsConfigurer. Now it has to be added explicitly, unless as a bonus, the AuthorizationServerEndpointsConfigurer has an explicit AccessTokenConverter that is a JwtAccessTokenConverter, in which case the JwtTokenStore is added automatically. --- ...orizationServerEndpointsConfiguration.java | 50 ++++--- ...horizationServerSecurityConfiguration.java | 10 +- .../ResourceServerConfiguration.java | 15 +- ...uthorizationServerEndpointsConfigurer.java | 88 ++++++++--- ...AuthorizationServerSecurityConfigurer.java | 24 ++- .../provider/endpoint/CheckTokenEndpoint.java | 99 +++++++++++++ .../provider/endpoint/TokenKeyEndpoint.java | 64 ++++++++ .../token/JwtAccessTokenConverter.java | 10 +- .../provider/token/RemoteTokenServices.java | 139 ++++++++++++++++++ .../provider/token/JwtTokenEnhancerTests.java | 7 +- 10 files changed, 451 insertions(+), 55 deletions(-) create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/CheckTokenEndpoint.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenKeyEndpoint.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/RemoteTokenServices.java 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 3d88de923..832f2fca2 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 @@ -19,31 +19,34 @@ import javax.annotation.PostConstruct; import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; -import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; -import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerEndpointsConfiguration.TokenStoreRegistrar; +import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerEndpointsConfiguration.TokenKeyEndpointRegistrar; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; import org.springframework.security.oauth2.provider.ClientDetailsService; 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.approval.ApprovalStore; import org.springframework.security.oauth2.provider.approval.UserApprovalHandler; import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; import org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint; +import org.springframework.security.oauth2.provider.endpoint.CheckTokenEndpoint; import org.springframework.security.oauth2.provider.endpoint.FrameworkEndpointHandlerMapping; import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint; +import org.springframework.security.oauth2.provider.endpoint.TokenKeyEndpoint; import org.springframework.security.oauth2.provider.endpoint.WhitelabelApprovalEndpoint; import org.springframework.security.oauth2.provider.endpoint.WhitelabelErrorEndpoint; import org.springframework.security.oauth2.provider.implicit.ImplicitGrantService; import org.springframework.security.oauth2.provider.token.ConsumerTokenServices; import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; +import org.springframework.security.oauth2.provider.token.JwtAccessTokenConverter; import org.springframework.security.oauth2.provider.token.TokenStore; /** @@ -51,7 +54,7 @@ * */ @Configuration -@Import(TokenStoreRegistrar.class) +@Import(TokenKeyEndpointRegistrar.class) public class AuthorizationServerEndpointsConfiguration { /** @@ -61,12 +64,6 @@ public class AuthorizationServerEndpointsConfiguration { */ public static final String TOKEN_STORE_BEAN_NAME = "tokenStore"; - /** - * The static bean name for a {@link ApprovalStore} if any. Spring will not create one, but it will also not create - * a {@link TokenStore} bean if there is an approval store present. - */ - public static final String APPROVAL_STORE_BEAN_NAME = "approvalStore"; - private AuthorizationServerEndpointsConfigurer endpoints = new AuthorizationServerEndpointsConfigurer(); @Autowired @@ -75,18 +72,12 @@ public class AuthorizationServerEndpointsConfiguration { @Autowired private List configurers = Collections.emptyList(); - @Autowired(required = false) - private TokenStore tokenStore; - @PostConstruct public void init() throws Exception { for (AuthorizationServerConfigurer configurer : configurers) { configurer.configure(endpoints); } endpoints.clientDetailsService(clientDetailsService); - if (tokenStore != null) { - endpoints.tokenStore(tokenStore); - } } @Bean @@ -114,7 +105,14 @@ public TokenEndpoint tokenEndpoint() throws Exception { tokenEndpoint.setOAuth2RequestValidator(oauth2RequestValidator()); return tokenEndpoint; } - + + @Bean + public CheckTokenEndpoint checkTokenEndpoint() { + CheckTokenEndpoint endpoint = new CheckTokenEndpoint(endpoints.getResourceServerTokenServices()); + endpoint.setAccessTokenConverter(endpoints.getAccessTokenConverter()); + return endpoint; + } + @Bean public WhitelabelApprovalEndpoint whitelabelApprovalEndpoint() { return new WhitelabelApprovalEndpoint(); @@ -135,10 +133,15 @@ public ConsumerTokenServices consumerTokenServices() throws Exception { return endpoints.getConsumerTokenServices(); } + @Bean + public TokenStore tokenStore() throws Exception { + return endpoints.getTokenStore(); + } + private ImplicitGrantService implicitGrantService() throws Exception { return endpoints.getImplicitGrantService(); } - + private OAuth2RequestFactory oauth2RequestFactory() throws Exception { return endpoints.getOAuth2RequestFactory(); } @@ -168,16 +171,17 @@ private String extractPath(FrameworkEndpointHandlerMapping mapping, String page) } @Configuration - protected static class TokenStoreRegistrar implements BeanDefinitionRegistryPostProcessor { + protected static class TokenKeyEndpointRegistrar implements BeanDefinitionRegistryPostProcessor { private BeanDefinitionRegistry registry; - // Use a BeanFactoryPostProcessor to register a bean definition for a TokenStore in a safe way (without - // pre-empting a bean specified by the user) @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { - if (!registry.containsBeanDefinition(TOKEN_STORE_BEAN_NAME)) { - registry.registerBeanDefinition(TOKEN_STORE_BEAN_NAME, new RootBeanDefinition(InMemoryTokenStore.class)); + String[] names = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, JwtAccessTokenConverter.class); + if (names.length > 0) { + BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(TokenKeyEndpoint.class); + builder.addConstructorArgReference(names[0]); + registry.registerBeanDefinition(TokenKeyEndpoint.class.getName(), builder.getBeanDefinition()); } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java index 5d5c13eeb..161c9f5a6 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java @@ -22,7 +22,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.core.annotation.Order; -import org.springframework.http.HttpMethod; import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @@ -71,16 +70,17 @@ protected void configure(HttpSecurity http) throws Exception { configure(configurer); http.apply(configurer); String tokenEndpointPath = handlerMapping.getPath("/oauth/token"); + String tokenKeyPath = handlerMapping.getPath("/oauth/token_key"); + String checkTokenPath = handlerMapping.getPath("/oauth/check_token"); // @formatter:off http - .authorizeRequests() - .antMatchers(HttpMethod.OPTIONS, tokenEndpointPath).permitAll() - .and() .authorizeRequests() .antMatchers(tokenEndpointPath).fullyAuthenticated() + .antMatchers(tokenKeyPath).access(configurer.getTokenKeyAccess()) + .antMatchers(checkTokenPath).access(configurer.getCheckTokenAccess()) .and() .requestMatchers() - .antMatchers(tokenEndpointPath); + .antMatchers(tokenEndpointPath, tokenKeyPath, checkTokenPath); // @formatter:on http.setSharedObject(ClientDetailsService.class, clientDetailsService); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java index 136ec45d3..369ac50cb 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java @@ -30,6 +30,7 @@ import org.springframework.security.oauth2.provider.endpoint.FrameworkEndpointHandlerMapping; import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler; +import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.security.web.util.matcher.RequestMatcher; @@ -45,6 +46,9 @@ public class ResourceServerConfiguration extends WebSecurityConfigurerAdapter { @Autowired(required = false) private TokenStore tokenStore; + @Autowired(required = false) + private ResourceServerTokenServices tokenServices; + private List configurers = Collections.emptyList(); private AccessDeniedHandler accessDeniedHandler = new OAuth2AccessDeniedHandler(); @@ -118,12 +122,17 @@ protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests().expressionHandler(new OAuth2WebSecurityExpressionHandler()); ResourceServerSecurityConfigurer resources = new ResourceServerSecurityConfigurer(); http.apply(resources); + if (tokenServices != null) { + resources.tokenServices(tokenServices); + } + else { + if (tokenStore != null) { + resources.tokenStore(tokenStore); + } + } for (ResourceServerConfigurer configurer : configurers) { configurer.configure(resources); } - if (tokenStore != null) { - resources.tokenStore(tokenStore); - } } } 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 a61ac88ce..9a1f44188 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 @@ -44,11 +44,15 @@ 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.InMemoryTokenStore; +import org.springframework.security.oauth2.provider.token.JwtAccessTokenConverter; import org.springframework.security.oauth2.provider.token.JwtTokenStore; +import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices; import org.springframework.security.oauth2.provider.token.TokenEnhancer; import org.springframework.security.oauth2.provider.token.TokenStore; @@ -66,12 +70,16 @@ public final class AuthorizationServerEndpointsConfigurer { private AuthorizationCodeServices authorizationCodeServices; + private ResourceServerTokenServices resourceTokenServices; + private ImplicitGrantService implicitGrantService = new InMemoryImplicitGrantService(); private TokenStore tokenStore; private TokenEnhancer tokenEnhancer; + private AccessTokenConverter accessTokenConverter; + private ApprovalStore approvalStore; private TokenGranter tokenGranter; @@ -97,13 +105,17 @@ public AuthorizationServerTokenServices getTokenServices() { } public TokenStore getTokenStore() { - return tokenStore; + return tokenStore(); } public TokenEnhancer getTokenEnhancer() { return tokenEnhancer; } + public AccessTokenConverter getAccessTokenConverter() { + return accessTokenConverter; + } + public ApprovalStore getApprovalStore() { return approvalStore; } @@ -134,6 +146,11 @@ public AuthorizationServerEndpointsConfigurer tokenEnhancer(TokenEnhancer tokenE return this; } + public AuthorizationServerEndpointsConfigurer accessTokenConverter(AccessTokenConverter accessTokenConverter) { + this.accessTokenConverter = accessTokenConverter; + return this; + } + public AuthorizationServerEndpointsConfigurer tokenServices(AuthorizationServerTokenServices tokenServices) { this.tokenServices = tokenServices; return this; @@ -187,7 +204,8 @@ public AuthorizationServerEndpointsConfigurer requestValidator(OAuth2RequestVali return this; } - public AuthorizationServerEndpointsConfigurer authorizationCodeServices(AuthorizationCodeServices authorizationCodeServices) { + public AuthorizationServerEndpointsConfigurer authorizationCodeServices( + AuthorizationCodeServices authorizationCodeServices) { this.authorizationCodeServices = authorizationCodeServices; return this; } @@ -196,6 +214,10 @@ public ConsumerTokenServices getConsumerTokenServices() { return consumerTokenServices(); } + public ResourceServerTokenServices getResourceServerTokenServices() { + return resourceTokenServices(); + } + public ImplicitGrantService getImplicitGrantService() { return implicitGrantService; } @@ -216,14 +238,22 @@ public FrameworkEndpointHandlerMapping getFrameworkEndpointHandlerMapping() { return frameworkEndpointHandlerMapping(); } + private ResourceServerTokenServices resourceTokenServices() { + if (resourceTokenServices == null) { + if (tokenServices instanceof ResourceServerTokenServices) { + return (ResourceServerTokenServices) tokenServices; + } + resourceTokenServices = createTokenServices(); + } + return resourceTokenServices; + } + private ConsumerTokenServices consumerTokenServices() { if (consumerTokenServices == null) { - if (tokenStore() != null) { - DefaultTokenServices defaultTokenServices = new DefaultTokenServices(); - defaultTokenServices.setClientDetailsService(clientDetailsService()); - defaultTokenServices.setTokenStore(tokenStore()); - consumerTokenServices = defaultTokenServices; + if (tokenServices instanceof ConsumerTokenServices) { + return (ConsumerTokenServices) tokenServices; } + consumerTokenServices = createTokenServices(); } return consumerTokenServices; } @@ -232,24 +262,47 @@ private AuthorizationServerTokenServices tokenServices() { if (tokenServices != null) { return tokenServices; } + this.tokenServices = createTokenServices(); + return tokenServices; + } + + private DefaultTokenServices createTokenServices() { DefaultTokenServices tokenServices = new DefaultTokenServices(); tokenServices.setTokenStore(tokenStore()); tokenServices.setSupportRefreshToken(true); tokenServices.setClientDetailsService(clientDetailsService()); - tokenServices.setTokenEnhancer(this.tokenEnhancer); - this.tokenServices = tokenServices; + tokenServices.setTokenEnhancer(tokenEnchancer()); return tokenServices; } + private TokenEnhancer tokenEnchancer() { + if (this.tokenEnhancer == null && accessTokenConverter() instanceof JwtAccessTokenConverter) { + tokenEnhancer = (TokenEnhancer) accessTokenConverter; + } + return this.tokenEnhancer; + } + + private AccessTokenConverter accessTokenConverter() { + if (this.accessTokenConverter == null) { + accessTokenConverter = new DefaultAccessTokenConverter(); + } + return this.accessTokenConverter; + } + private TokenStore tokenStore() { - if (tokenStore == null && approvalStore == null) { - this.tokenStore = new InMemoryTokenStore(); + if (tokenStore == null) { + if (accessTokenConverter() instanceof JwtAccessTokenConverter) { + this.tokenStore = new JwtTokenStore((JwtAccessTokenConverter) accessTokenConverter()); + } + else { + this.tokenStore = new InMemoryTokenStore(); + } } return this.tokenStore; } private ApprovalStore approvalStore() { - if (approvalStore==null && tokenStore() != null && !isApprovalStoreDisabled()) { + if (approvalStore == null && tokenStore() != null && !isApprovalStoreDisabled()) { TokenApprovalStore tokenApprovalStore = new TokenApprovalStore(); tokenApprovalStore.setTokenStore(tokenStore()); this.approvalStore = tokenApprovalStore; @@ -267,15 +320,15 @@ private ClientDetailsService clientDetailsService() { } return this.clientDetailsService; } - + private UserApprovalHandler userApprovalHandler() { if (userApprovalHandler == null) { - if (approvalStore()!=null) { + if (approvalStore() != null) { ApprovalStoreUserApprovalHandler handler = new ApprovalStoreUserApprovalHandler(); handler.setApprovalStore(approvalStore()); handler.setRequestFactory(requestFactory()); handler.setClientDetailsService(clientDetailsService); - this.userApprovalHandler = handler; + this.userApprovalHandler = handler; } else if (tokenStore() != null) { TokenStoreUserApprovalHandler userApprovalHandler = new TokenStoreUserApprovalHandler(); @@ -283,7 +336,8 @@ else if (tokenStore() != null) { userApprovalHandler.setClientDetailsService(clientDetailsService()); userApprovalHandler.setRequestFactory(requestFactory()); this.userApprovalHandler = userApprovalHandler; - } else { + } + else { throw new IllegalStateException("Either a TokenStore or an ApprovalStore must be provided"); } } @@ -304,7 +358,7 @@ private OAuth2RequestFactory requestFactory() { requestFactory = new DefaultOAuth2RequestFactory(clientDetailsService()); return requestFactory; } - + private OAuth2RequestValidator requestValidator() { if (requestValidator != null) { return requestValidator; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java index cff47c420..40e5c5cf4 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java @@ -54,6 +54,10 @@ public final class AuthorizationServerSecurityConfigurer extends private boolean allowFormAuthenticationForClients = false; + private String tokenKeyAccess = "denyAll()"; + + private String checkTokenAccess = "denyAll()"; + public AuthorizationServerSecurityConfigurer allowFormAuthenticationForClients() { this.allowFormAuthenticationForClients = true; return this; @@ -70,6 +74,24 @@ public AuthorizationServerSecurityConfigurer authenticationEntryPoint( return this; } + public AuthorizationServerSecurityConfigurer tokenKeyAccess(String tokenKeyAccess) { + this.tokenKeyAccess = tokenKeyAccess; + return this; + } + + public AuthorizationServerSecurityConfigurer checkTokenAccess(String checkTokenAccess) { + this.checkTokenAccess = checkTokenAccess; + return this; + } + + public String getTokenKeyAccess() { + return tokenKeyAccess; + } + + public String getCheckTokenAccess() { + return checkTokenAccess; + } + @Override public void init(HttpSecurity http) throws Exception { registerDefaultAuthenticationEntryPoint(http); @@ -118,7 +140,7 @@ private ClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilte http.addFilterBefore(clientCredentialsTokenEndpointFilter, BasicAuthenticationFilter.class); return clientCredentialsTokenEndpointFilter; } - + private ClientDetailsService clientDetailsService() { return getBuilder().getSharedObject(ClientDetailsService.class); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/CheckTokenEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/CheckTokenEndpoint.java new file mode 100644 index 000000000..a4fd32809 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/CheckTokenEndpoint.java @@ -0,0 +1,99 @@ +/******************************************************************************* + * Cloud Foundry + * Copyright (c) [2009-2014] Pivotal Software, Inc. All Rights Reserved. + * + * This product is licensed to you under the Apache License, Version 2.0 (the "License"). + * You may not use this product except in compliance with the License. + * + * This product includes a number of subcomponents with + * separate copyright notices and license terms. Your use of these + * subcomponents is subject to the terms and conditions of the + * subcomponent's license, as noted in the LICENSE file. + *******************************************************************************/ +package org.springframework.security.oauth2.provider.endpoint; + +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.http.ResponseEntity; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; +import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator; +import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator; +import org.springframework.security.oauth2.provider.token.AccessTokenConverter; +import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter; +import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +/** + * Controller which decodes access tokens for clients who are not able to do so (or where opaque token values are used). + * + * @author Luke Taylor + * @author Joel D'sa + */ +@FrameworkEndpoint +public class CheckTokenEndpoint { + + private ResourceServerTokenServices resourceServerTokenServices; + + private AccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter(); + + protected final Log logger = LogFactory.getLog(getClass()); + + private WebResponseExceptionTranslator exceptionTranslator = new DefaultWebResponseExceptionTranslator(); + + public CheckTokenEndpoint(ResourceServerTokenServices resourceServerTokenServices) { + this.resourceServerTokenServices = resourceServerTokenServices; + } + + /** + * @param accessTokenConverter the accessTokenConverter to set + */ + public void setAccessTokenConverter(AccessTokenConverter accessTokenConverter) { + this.accessTokenConverter = accessTokenConverter; + } + + @RequestMapping(value = "/oauth/check_token") + @ResponseBody + public Map checkToken(@RequestParam("token") String value) { + + OAuth2AccessToken token = resourceServerTokenServices.readAccessToken(value); + if (token == null) { + throw new InvalidTokenException("Token was not recognised"); + } + + if (token.isExpired()) { + throw new InvalidTokenException("Token has expired"); + } + + OAuth2Authentication authentication = resourceServerTokenServices.loadAuthentication(token.getValue()); + + Map response = accessTokenConverter.convertAccessToken(token, authentication); + + return response; + } + + @ExceptionHandler(InvalidTokenException.class) + public ResponseEntity handleException(Exception e) throws Exception { + logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage()); + // This isn't an oauth resource, so we don't want to send an + // unauthorized code here. The client has already authenticated + // successfully with basic auth and should just + // get back the invalid token error. + @SuppressWarnings("serial") + InvalidTokenException e400 = new InvalidTokenException(e.getMessage()) { + @Override + public int getHttpErrorCode() { + return 400; + } + }; + return exceptionTranslator.translate(e400); + } + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenKeyEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenKeyEndpoint.java new file mode 100644 index 000000000..2ec589c5a --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenKeyEndpoint.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * Cloud Foundry + * Copyright (c) [2009-2014] Pivotal Software, Inc. All Rights Reserved. + * + * This product is licensed to you under the Apache License, Version 2.0 (the "License"). + * You may not use this product except in compliance with the License. + * + * This product includes a number of subcomponents with + * separate copyright notices and license terms. Your use of these + * subcomponents is subject to the terms and conditions of the + * subcomponent's license, as noted in the LICENSE file. + *******************************************************************************/ +package org.springframework.security.oauth2.provider.endpoint; + +import java.security.Principal; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.authentication.AnonymousAuthenticationToken; +import org.springframework.security.oauth2.provider.token.JwtAccessTokenConverter; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +/** + * OAuth2 token services that produces JWT encoded token values. + * + * @author Dave Syer + * @author Luke Taylor + * @author Joel D'sa + */ +@FrameworkEndpoint +public class TokenKeyEndpoint { + + protected final Log logger = LogFactory.getLog(getClass()); + + private JwtAccessTokenConverter converter; + + public TokenKeyEndpoint(JwtAccessTokenConverter converter) { + super(); + this.converter = converter; + } + + /** + * Get the verification key for the token signatures. The principal has to + * be provided only if the key is secret + * (shared not public). + * + * @param principal the currently authenticated user if there is one + * @return the key used to verify tokens + */ + @RequestMapping(value = "/oauth/token_key", method = RequestMethod.GET) + @ResponseBody + public Map getKey(Principal principal) { + if ((principal == null || principal instanceof AnonymousAuthenticationToken) && !converter.isPublic()) { + throw new AccessDeniedException("You need to authenticate to see a shared key"); + } + Map result = converter.getKey(); + return result; + } + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtAccessTokenConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtAccessTokenConverter.java index cc681c06e..0e7f8525d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtAccessTokenConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtAccessTokenConverter.java @@ -12,7 +12,6 @@ */ package org.springframework.security.oauth2.provider.token; -import java.security.Principal; import java.util.Date; import java.util.LinkedHashMap; import java.util.Map; @@ -105,7 +104,7 @@ public OAuth2Authentication extractAuthentication(Map map) { * * @return the key used to verify tokens */ - public Map getKey(Principal principal) { + public Map getKey() { Map result = new LinkedHashMap(); result.put("alg", signer.algorithm()); result.put("value", verifierKey); @@ -141,6 +140,13 @@ public void setSigningKey(String key) { private boolean isPublic(String key) { return key.startsWith("-----BEGIN"); } + + /** + * @return true if the signing key is a public key + */ + public boolean isPublic() { + return signer instanceof RsaSigner; + } /** * The key used for verifying signatures produced by this class. This is not used but is returned from the endpoint diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/RemoteTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/RemoteTokenServices.java new file mode 100644 index 000000000..ddf1fb214 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/RemoteTokenServices.java @@ -0,0 +1,139 @@ +/******************************************************************************* + * Cloud Foundry + * Copyright (c) [2009-2014] Pivotal Software, Inc. All Rights Reserved. + * + * This product is licensed to you under the Apache License, Version 2.0 (the "License"). + * You may not use this product except in compliance with the License. + * + * This product includes a number of subcomponents with + * separate copyright notices and license terms. Your use of these + * subcomponents is subject to the terms and conditions of the + * subcomponent's license, as noted in the LICENSE file. + *******************************************************************************/ +package org.springframework.security.oauth2.provider.token; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.crypto.codec.Base64; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.util.Assert; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.DefaultResponseErrorHandler; +import org.springframework.web.client.RestOperations; +import org.springframework.web.client.RestTemplate; + +/** + * Queries the /check_token endpoint to obtain the contents of an access token. + * + * If the endpoint returns a 400 response, this indicates that the token is invalid. + * + * @author Dave Syer + * @author Luke Taylor + * + */ +public class RemoteTokenServices implements ResourceServerTokenServices { + + protected final Log logger = LogFactory.getLog(getClass()); + + private RestOperations restTemplate; + + private String checkTokenEndpointUrl; + + private String clientId; + + private String clientSecret; + + private AccessTokenConverter tokenConverter = new DefaultAccessTokenConverter(); + + public RemoteTokenServices() { + restTemplate = new RestTemplate(); + ((RestTemplate) restTemplate).setErrorHandler(new DefaultResponseErrorHandler() { + @Override + // Ignore 400 + public void handleError(ClientHttpResponse response) throws IOException { + if (response.getRawStatusCode() != 400) { + super.handleError(response); + } + } + }); + } + + public void setRestTemplate(RestOperations restTemplate) { + this.restTemplate = restTemplate; + } + + public void setCheckTokenEndpointUrl(String checkTokenEndpointUrl) { + this.checkTokenEndpointUrl = checkTokenEndpointUrl; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + public void setClientSecret(String clientSecret) { + this.clientSecret = clientSecret; + } + + public void setAccessTokenConverter(AccessTokenConverter accessTokenConverter) { + this.tokenConverter = accessTokenConverter; + } + + @Override + public OAuth2Authentication loadAuthentication(String accessToken) throws AuthenticationException { + + MultiValueMap formData = new LinkedMultiValueMap(); + formData.add("token", accessToken); + HttpHeaders headers = new HttpHeaders(); + headers.set("Authorization", getAuthorizationHeader(clientId, clientSecret)); + Map map = postForMap(checkTokenEndpointUrl, formData, headers); + + if (map.containsKey("error")) { + logger.debug("check_token returned error: " + map.get("error")); + throw new InvalidTokenException(accessToken); + } + + Assert.state(map.containsKey("client_id"), "Client id must be present in response from auth server"); + return tokenConverter.extractAuthentication(map); + } + + @Override + public OAuth2AccessToken readAccessToken(String accessToken) { + throw new UnsupportedOperationException("Not supported: read access token"); + } + + private String getAuthorizationHeader(String clientId, String clientSecret) { + String creds = String.format("%s:%s", clientId, clientSecret); + try { + return "Basic " + new String(Base64.encode(creds.getBytes("UTF-8"))); + } + catch (UnsupportedEncodingException e) { + throw new IllegalStateException("Could not convert String"); + } + } + + private Map postForMap(String path, MultiValueMap formData, HttpHeaders headers) { + if (headers.getContentType() == null) { + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + } + @SuppressWarnings("rawtypes") + Map map = restTemplate.exchange(path, HttpMethod.POST, + new HttpEntity>(formData, headers), Map.class).getBody(); + @SuppressWarnings("unchecked") + Map result = map; + return result; + } + +} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancerTests.java index 1f8356a3a..7c6f4d512 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancerTests.java @@ -19,7 +19,6 @@ import org.junit.Before; import org.junit.Test; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.jwt.JwtHelper; import org.springframework.security.jwt.crypto.sign.RsaVerifier; @@ -109,7 +108,7 @@ public void publicKeyStringIsReturnedFromTokenKeyEndpoint() throws Exception { + "MGgCYQDk3m+AGfjcDrT4fspyIBqmulFjVXuiciYvpaD5j2XaR7c6Krm5wsBLOiUo\n" + "kmd6wbrRAMPMpoC1eogWNNoXY7Jd4eWdDVmscfHczGX13uBKXwdOCEqKqoWQsXIb\n" + "7kgz+HkCAwEAAQ==\n" + "-----END RSA PUBLIC KEY-----"); - Map key = tokenEnhancer.getKey(new UsernamePasswordAuthenticationToken("foo", "bar")); + Map key = tokenEnhancer.getKey(); assertTrue("Wrong key: " + key, key.get("value").contains("-----BEGIN")); } @@ -119,7 +118,7 @@ public void publicKeyStringIsReturnedFromTokenKeyEndpointWithNullPrincipal() thr + "MGgCYQDk3m+AGfjcDrT4fspyIBqmulFjVXuiciYvpaD5j2XaR7c6Krm5wsBLOiUo\n" + "kmd6wbrRAMPMpoC1eogWNNoXY7Jd4eWdDVmscfHczGX13uBKXwdOCEqKqoWQsXIb\n" + "7kgz+HkCAwEAAQ==\n" + "-----END RSA PUBLIC KEY-----"); - Map key = tokenEnhancer.getKey(null); + Map key = tokenEnhancer.getKey(); assertTrue("Wrong key: " + key, key.get("value").contains("-----BEGIN")); } @@ -127,7 +126,7 @@ public void publicKeyStringIsReturnedFromTokenKeyEndpointWithNullPrincipal() thr public void sharedSecretIsReturnedFromTokenKeyEndpoint() throws Exception { tokenEnhancer.setVerifierKey("someKey"); assertEquals("{alg=HMACSHA256, value=someKey}", - tokenEnhancer.getKey(new UsernamePasswordAuthenticationToken("foo", "bar")).toString()); + tokenEnhancer.getKey().toString()); } @Test(expected = IllegalStateException.class) From 15dc701c6b02fd45d83d77ac9173bf62e14f2ca8 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Sat, 19 Apr 2014 06:18:30 -0700 Subject: [PATCH 252/831] Remove cycle in common util --- .../util => provider}/DefaultSecurityContextAccessor.java | 3 +-- .../{common/util => provider}/SecurityContextAccessor.java | 2 +- .../oauth2/provider/request/DefaultOAuth2RequestFactory.java | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) rename spring-security-oauth2/src/main/java/org/springframework/security/oauth2/{common/util => provider}/DefaultSecurityContextAccessor.java (93%) rename spring-security-oauth2/src/main/java/org/springframework/security/oauth2/{common/util => provider}/SecurityContextAccessor.java (94%) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/DefaultSecurityContextAccessor.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultSecurityContextAccessor.java similarity index 93% rename from spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/DefaultSecurityContextAccessor.java rename to spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultSecurityContextAccessor.java index d53cea568..0bab78276 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/DefaultSecurityContextAccessor.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultSecurityContextAccessor.java @@ -11,7 +11,7 @@ * specific language governing permissions and limitations under the License. */ -package org.springframework.security.oauth2.common.util; +package org.springframework.security.oauth2.provider; import java.util.Collections; import java.util.HashSet; @@ -20,7 +20,6 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.oauth2.provider.OAuth2Authentication; /** * Strategy for accessing useful information about the current security context. diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/SecurityContextAccessor.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/SecurityContextAccessor.java similarity index 94% rename from spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/SecurityContextAccessor.java rename to spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/SecurityContextAccessor.java index 5c0a885c0..26862cc64 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/SecurityContextAccessor.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/SecurityContextAccessor.java @@ -11,7 +11,7 @@ * specific language governing permissions and limitations under the License. */ -package org.springframework.security.oauth2.common.util; +package org.springframework.security.oauth2.provider; import java.util.Set; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/request/DefaultOAuth2RequestFactory.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/request/DefaultOAuth2RequestFactory.java index bf3887d58..17e9afcd3 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/request/DefaultOAuth2RequestFactory.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/request/DefaultOAuth2RequestFactory.java @@ -19,14 +19,14 @@ import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.oauth2.common.exceptions.InvalidClientException; -import org.springframework.security.oauth2.common.util.DefaultSecurityContextAccessor; import org.springframework.security.oauth2.common.util.OAuth2Utils; -import org.springframework.security.oauth2.common.util.SecurityContextAccessor; import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.DefaultSecurityContextAccessor; import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; +import org.springframework.security.oauth2.provider.SecurityContextAccessor; import org.springframework.security.oauth2.provider.TokenRequest; /** From af59af9fe0576aa6ac3e8fd08c4e69224c3af656 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Sat, 19 Apr 2014 06:30:08 -0700 Subject: [PATCH 253/831] Extract TokenStore implementations into a sub-package (anti-cycle) --- .../oauth/examples/sparklr/config/OAuth2ServerConfig.java | 2 +- .../AuthorizationServerEndpointsConfiguration.java | 4 ++-- .../AuthorizationServerEndpointsConfigurer.java | 6 +++--- .../web/configurers/ResourceServerSecurityConfigurer.java | 2 +- .../oauth2/config/xml/ProviderBeanDefinitionParser.java | 2 +- .../oauth2/provider/endpoint/TokenKeyEndpoint.java | 2 +- .../oauth2/provider/token/AccessTokenConverter.java | 2 +- .../provider/token/{ => store}/InMemoryTokenStore.java | 5 ++++- .../oauth2/provider/token/{ => store}/JdbcTokenStore.java | 5 ++++- .../token/{ => store}/JwtAccessTokenConverter.java | 7 +++++-- .../oauth2/provider/token/{ => store}/JwtTokenStore.java | 3 ++- .../annotation/AuthorizationServerConfigurationTests.java | 8 ++++---- .../annotation/ResourceServerConfigurationTests.java | 2 +- .../oauth2/provider/approval/TokenApprovalStoreTests.java | 2 +- .../approval/TokenStoreUserApprovalHandlerTests.java | 2 +- .../provider/code/AuthorizationCodeTokenGranterTests.java | 2 +- .../password/ResourceOwnerPasswordTokenGranterTests.java | 2 +- .../token/DefaultTokenServicesWithInMemoryTests.java | 1 + .../provider/token/DefaultTokenServicesWithJdbcTests.java | 1 + .../provider/token/DefaultTokenServicesWithJwtTests.java | 3 +++ .../oauth2/provider/token/InMemoryTokenStoreTests.java | 1 + .../oauth2/provider/token/JdbcTokenStoreTests.java | 1 + .../oauth2/provider/token/JwtTokenEnhancerTests.java | 1 + .../oauth2/provider/token/JwtTokenStoreTests.java | 2 ++ .../token/TokenServicesWithTokenEnhancerTests.java | 2 ++ .../oauth2/config/xml/authorization-server-extras.xml | 2 +- .../config/xml/resource-server-authmanager-context.xml | 2 +- .../oauth2/config/xml/resource-server-context.xml | 2 +- 28 files changed, 49 insertions(+), 27 deletions(-) rename spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/{ => store}/InMemoryTokenStore.java (97%) rename spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/{ => store}/JdbcTokenStore.java (98%) rename spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/{ => store}/JwtAccessTokenConverter.java (95%) rename spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/{ => store}/JwtTokenStore.java (97%) diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java index caf66ec1d..987b6936e 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java @@ -42,8 +42,8 @@ import org.springframework.security.oauth2.provider.approval.TokenApprovalStore; import org.springframework.security.oauth2.provider.approval.UserApprovalHandler; import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory; -import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; import org.springframework.security.oauth2.provider.token.TokenStore; +import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore; /** * @author Rob Winch 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 832f2fca2..3329ebe18 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 @@ -45,9 +45,9 @@ import org.springframework.security.oauth2.provider.endpoint.WhitelabelErrorEndpoint; import org.springframework.security.oauth2.provider.implicit.ImplicitGrantService; import org.springframework.security.oauth2.provider.token.ConsumerTokenServices; -import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; -import org.springframework.security.oauth2.provider.token.JwtAccessTokenConverter; 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.JwtAccessTokenConverter; /** * @author Dave Syer 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 9a1f44188..1f0b41548 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 @@ -49,12 +49,12 @@ 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.InMemoryTokenStore; -import org.springframework.security.oauth2.provider.token.JwtAccessTokenConverter; -import org.springframework.security.oauth2.provider.token.JwtTokenStore; 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.store.InMemoryTokenStore; +import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; +import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; /** * diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java index d84e5e5c5..82a73d575 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java @@ -30,9 +30,9 @@ import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint; import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler; import org.springframework.security.oauth2.provider.token.DefaultTokenServices; -import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices; import org.springframework.security.oauth2.provider.token.TokenStore; +import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.DefaultSecurityFilterChain; import org.springframework.security.web.FilterInvocation; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ProviderBeanDefinitionParser.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ProviderBeanDefinitionParser.java index 32efb4b96..1550d3845 100755 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ProviderBeanDefinitionParser.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ProviderBeanDefinitionParser.java @@ -18,7 +18,7 @@ import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.security.oauth2.provider.token.DefaultTokenServices; -import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; +import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore; import org.springframework.util.StringUtils; import org.w3c.dom.Element; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenKeyEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenKeyEndpoint.java index 2ec589c5a..ecd231cfd 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenKeyEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenKeyEndpoint.java @@ -19,7 +19,7 @@ import org.apache.commons.logging.LogFactory; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.authentication.AnonymousAuthenticationToken; -import org.springframework.security.oauth2.provider.token.JwtAccessTokenConverter; +import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AccessTokenConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AccessTokenConverter.java index dbb8abd96..409844de3 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AccessTokenConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AccessTokenConverter.java @@ -31,7 +31,7 @@ public interface AccessTokenConverter { final String EXP = "exp"; - final String JTI = JwtAccessTokenConverter.TOKEN_ID; + final String JTI = "jti"; final String SCOPE = OAuth2AccessToken.SCOPE; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/InMemoryTokenStore.java similarity index 97% rename from spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStore.java rename to spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/InMemoryTokenStore.java index f7f794870..b70767fa0 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/InMemoryTokenStore.java @@ -1,4 +1,4 @@ -package org.springframework.security.oauth2.provider.token; +package org.springframework.security.oauth2.provider.token.store; import java.util.Collection; import java.util.Collections; @@ -13,6 +13,9 @@ 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.AuthenticationKeyGenerator; +import org.springframework.security.oauth2.provider.token.DefaultAuthenticationKeyGenerator; +import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.util.Assert; /** diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JdbcTokenStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JdbcTokenStore.java similarity index 98% rename from spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JdbcTokenStore.java rename to spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JdbcTokenStore.java index ea897d117..f3af1b281 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JdbcTokenStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JdbcTokenStore.java @@ -1,4 +1,4 @@ -package org.springframework.security.oauth2.provider.token; +package org.springframework.security.oauth2.provider.token.store; import java.io.UnsupportedEncodingException; import java.math.BigInteger; @@ -23,6 +23,9 @@ import org.springframework.security.oauth2.common.OAuth2RefreshToken; import org.springframework.security.oauth2.common.util.SerializationUtils; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.token.AuthenticationKeyGenerator; +import org.springframework.security.oauth2.provider.token.DefaultAuthenticationKeyGenerator; +import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.util.Assert; /** diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtAccessTokenConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java similarity index 95% rename from spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtAccessTokenConverter.java rename to spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java index 0e7f8525d..e84b2b63d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtAccessTokenConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java @@ -10,7 +10,7 @@ * subcomponents is subject to the terms and conditions of the * subcomponent's license, as noted in the LICENSE file. */ -package org.springframework.security.oauth2.provider.token; +package org.springframework.security.oauth2.provider.token.store; import java.util.Date; import java.util.LinkedHashMap; @@ -37,6 +37,9 @@ import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; import org.springframework.security.oauth2.common.util.RandomValueStringGenerator; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.token.AccessTokenConverter; +import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter; +import org.springframework.security.oauth2.provider.token.TokenEnhancer; import org.springframework.util.Assert; /** @@ -54,7 +57,7 @@ public class JwtAccessTokenConverter implements TokenEnhancer, AccessTokenConver /** * Field name for token id. */ - public static final String TOKEN_ID = "jti"; + public static final String TOKEN_ID = AccessTokenConverter.JTI; private static final Log logger = LogFactory.getLog(JwtAccessTokenConverter.class); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStore.java similarity index 97% rename from spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenStore.java rename to spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStore.java index 8374aabda..816ff56ff 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/JwtTokenStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStore.java @@ -11,7 +11,7 @@ * specific language governing permissions and limitations under the License. */ -package org.springframework.security.oauth2.provider.token; +package org.springframework.security.oauth2.provider.token.store; import java.util.ArrayList; import java.util.Collection; @@ -28,6 +28,7 @@ import org.springframework.security.oauth2.provider.approval.Approval; import org.springframework.security.oauth2.provider.approval.Approval.ApprovalStatus; import org.springframework.security.oauth2.provider.approval.ApprovalStore; +import org.springframework.security.oauth2.provider.token.TokenStore; /** * A {@link TokenStore} implementation that just reads data from the tokens themselves. Not really a store since it diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java index 309f31450..f1b88d045 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java @@ -54,11 +54,11 @@ import org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; import org.springframework.security.oauth2.provider.token.DefaultTokenServices; -import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; -import org.springframework.security.oauth2.provider.token.JdbcTokenStore; -import org.springframework.security.oauth2.provider.token.JwtAccessTokenConverter; -import org.springframework.security.oauth2.provider.token.JwtTokenStore; 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.security.oauth2.provider.token.store.JwtAccessTokenConverter; +import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java index cd36c6744..53be0955b 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java @@ -30,8 +30,8 @@ import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.client.BaseClientDetails; -import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; import org.springframework.security.oauth2.provider.token.TokenStore; +import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.result.MockMvcResultMatchers; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TokenApprovalStoreTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TokenApprovalStoreTests.java index e9a634142..d136b380d 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TokenApprovalStoreTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TokenApprovalStoreTests.java @@ -30,7 +30,7 @@ import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; -import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; +import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore; /** * @author Dave Syer diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandlerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandlerTests.java index ab9e1f536..70552058c 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandlerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandlerTests.java @@ -24,7 +24,7 @@ import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory; import org.springframework.security.oauth2.provider.token.DefaultTokenServices; -import org.springframework.security.oauth2.provider.token.InMemoryTokenStore; +import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore; /** * @author Dave Syer diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranterTests.java index df59c7e3d..429cefa0a 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranterTests.java @@ -36,7 +36,7 @@ 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.InMemoryTokenStore; +import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranterTests.java index 28c40f288..8cccf3299 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranterTests.java @@ -39,7 +39,7 @@ 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.InMemoryTokenStore; +import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore; /** * @author Dave Syer diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithInMemoryTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithInMemoryTests.java index 71fe892cc..18f4e8feb 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithInMemoryTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithInMemoryTests.java @@ -25,6 +25,7 @@ import org.springframework.security.oauth2.provider.RequestTokenFactory; import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.client.BaseClientDetails; +import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore; import org.springframework.test.util.ReflectionTestUtils; /** diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithJdbcTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithJdbcTests.java index 0862ba0e9..39f989878 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithJdbcTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithJdbcTests.java @@ -4,6 +4,7 @@ import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore; /** * @author Dave Syer diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithJwtTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithJwtTests.java index 53421c054..9cdcb5323 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithJwtTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithJwtTests.java @@ -1,5 +1,8 @@ package org.springframework.security.oauth2.provider.token; +import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; +import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; + /** * @author Ryan Heaton diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStoreTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStoreTests.java index a6e82d331..9ac0cca73 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStoreTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStoreTests.java @@ -9,6 +9,7 @@ import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.RequestTokenFactory; +import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore; /** * @author Dave Syer diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JdbcTokenStoreTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JdbcTokenStoreTests.java index 963c41399..66c9ce2ad 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JdbcTokenStoreTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JdbcTokenStoreTests.java @@ -4,6 +4,7 @@ import org.junit.Before; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore; /** * @author Dave Syer diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancerTests.java index 7c6f4d512..0b03590dd 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancerTests.java @@ -28,6 +28,7 @@ import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.token.AbstractDefaultTokenServicesTests.TestAuthentication; +import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; /** * @author Dave Syer diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenStoreTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenStoreTests.java index 79536d60b..fd45a958f 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenStoreTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenStoreTests.java @@ -17,6 +17,8 @@ import org.springframework.security.oauth2.provider.approval.Approval; import org.springframework.security.oauth2.provider.approval.Approval.ApprovalStatus; import org.springframework.security.oauth2.provider.approval.InMemoryApprovalStore; +import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; +import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; /** * @author Dave Syer diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenServicesWithTokenEnhancerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenServicesWithTokenEnhancerTests.java index 00e378373..c1d7cfa05 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenServicesWithTokenEnhancerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenServicesWithTokenEnhancerTests.java @@ -31,6 +31,8 @@ import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.RequestTokenFactory; +import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; +import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; /** * @author Dave Syer diff --git a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-extras.xml b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-extras.xml index 701fde1d0..03b4b9d19 100644 --- a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-extras.xml +++ b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-extras.xml @@ -18,7 +18,7 @@ - + diff --git a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/resource-server-authmanager-context.xml b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/resource-server-authmanager-context.xml index e3e9fc44a..b6b804f7e 100644 --- a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/resource-server-authmanager-context.xml +++ b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/resource-server-authmanager-context.xml @@ -15,7 +15,7 @@ - + \ No newline at end of file diff --git a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/resource-server-context.xml b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/resource-server-context.xml index 6bb483061..965addbd1 100644 --- a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/resource-server-context.xml +++ b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/resource-server-context.xml @@ -26,7 +26,7 @@ - + \ No newline at end of file From 4f321e1adec9ddecfce6dadcc83a077b89f4c0ed Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 24 Apr 2014 15:02:34 +0100 Subject: [PATCH 254/831] Update commons-codec dependency to 1.6 Fixed gh-190 --- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index 473f8e906..d53d7fb33 100644 --- a/spring-security-oauth/pom.xml +++ b/spring-security-oauth/pom.xml @@ -118,7 +118,7 @@ commons-codec commons-codec - 1.3 + 1.6 diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 765baaa39..78e2da9d7 100644 --- a/spring-security-oauth2/pom.xml +++ b/spring-security-oauth2/pom.xml @@ -146,7 +146,7 @@ commons-codec commons-codec - 1.3 + 1.6 From b46e96caf066f9a38af1d686cfefd866971cee89 Mon Sep 17 00:00:00 2001 From: Christopher Elkins Date: Mon, 21 Apr 2014 12:00:37 -0700 Subject: [PATCH 255/831] ClientBuilder should forward configured auto-approve scopes --- .../config/annotation/builders/ClientDetailsServiceBuilder.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java index 91e229e10..e9cf37163 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java @@ -113,6 +113,8 @@ private ClientDetails build() { result.setResourceIds(resourceIds); if (autoApprove) { result.setAutoApproveScopes(scopes); + } else { + result.setAutoApproveScopes(autoApproveScopes); } return result; } From c9baf3429a4f6825acf82bc65db0e13e230d0eca Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 25 Apr 2014 13:58:47 +0100 Subject: [PATCH 256/831] [maven-release-plugin] prepare release 2.0.0.RC2 --- pom.xml | 4 ++-- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index 3b16080e3..790dc5937 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.0.BUILD-SNAPSHOT + 2.0.0.RC2 http://static.springframework.org/spring-security/oauth @@ -25,7 +25,7 @@ http://github.com/SpringSource/spring-security-oauth scm:git:git://github.com/SpringSource/spring-security-oauth.git scm:git:ssh://git@github.com/SpringSource/spring-security-oauth.git - HEAD + 2.0.0.RC2 JIRA diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index 86f09c156..a48f81f03 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.0.BUILD-SNAPSHOT + 2.0.0.RC2 ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index 2de3a9ae1..84805a2a1 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.0.BUILD-SNAPSHOT + 2.0.0.RC2 ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index fea01b7d4..b6e479eaf 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.0.BUILD-SNAPSHOT + 2.0.0.RC2 ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 66328cf18..102d96a8e 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.0.BUILD-SNAPSHOT + 2.0.0.RC2 ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index d88a907a1..570615313 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.0.BUILD-SNAPSHOT + 2.0.0.RC2 spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index d53d7fb33..132f63707 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.0.BUILD-SNAPSHOT + 2.0.0.RC2 spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 78e2da9d7..baf3ae5cb 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.0.BUILD-SNAPSHOT + 2.0.0.RC2 spring-security-oauth2 From b704faa88abc7c9fe9d7fca7d9b28e1feda63902 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 25 Apr 2014 13:58:54 +0100 Subject: [PATCH 257/831] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index 790dc5937..3b16080e3 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.0.RC2 + 2.0.0.BUILD-SNAPSHOT http://static.springframework.org/spring-security/oauth @@ -25,7 +25,7 @@ http://github.com/SpringSource/spring-security-oauth scm:git:git://github.com/SpringSource/spring-security-oauth.git scm:git:ssh://git@github.com/SpringSource/spring-security-oauth.git - 2.0.0.RC2 + HEAD JIRA diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index a48f81f03..86f09c156 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.0.RC2 + 2.0.0.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index 84805a2a1..2de3a9ae1 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.0.RC2 + 2.0.0.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index b6e479eaf..fea01b7d4 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.0.RC2 + 2.0.0.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 102d96a8e..66328cf18 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.0.RC2 + 2.0.0.BUILD-SNAPSHOT ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index 570615313..d88a907a1 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.0.RC2 + 2.0.0.BUILD-SNAPSHOT spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index 132f63707..d53d7fb33 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.0.RC2 + 2.0.0.BUILD-SNAPSHOT spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index baf3ae5cb..78e2da9d7 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.0.RC2 + 2.0.0.BUILD-SNAPSHOT spring-security-oauth2 From 9e3da75a458f739a633e7aed8cfbf3fbd4474f4b Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 2 May 2014 18:23:35 +0100 Subject: [PATCH 258/831] Use resource id for realm in resource server by default --- .../builders/ClientDetailsServiceBuilder.java | 6 +++- .../AuthorizationServerConfigurer.java | 33 +++++++++++++++++-- .../ResourceServerConfiguration.java | 16 +++++++-- .../ResourceServerConfigurer.java | 3 +- ...uthorizationServerEndpointsConfigurer.java | 1 + .../ResourceServerSecurityConfigurer.java | 7 ++++ 6 files changed, 59 insertions(+), 7 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java index e9cf37163..d9b7ed27f 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java @@ -30,6 +30,9 @@ import org.springframework.security.oauth2.provider.client.BaseClientDetails; /** + * Builder for OAuth2 client details service. Can be used to construct either an in-memory or a JDBC implementation of + * the {@link ClientDetailsService} and populate it with data. + * * @author Dave Syer * */ @@ -113,7 +116,8 @@ private ClientDetails build() { result.setResourceIds(resourceIds); if (autoApprove) { result.setAutoApproveScopes(scopes); - } else { + } + else { result.setAutoApproveScopes(autoApproveScopes); } return result; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurer.java index 518172e64..56d9d2876 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurer.java @@ -13,20 +13,49 @@ package org.springframework.security.oauth2.config.annotation.web.configuration; +import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; +import org.springframework.security.oauth2.provider.ClientDetailsService; /** + * Convenient strategy for configuring an OAUth2 Authorization Server. Beans of this type are applied to the Spring + * context automatically if you {@link EnableAuthorizationServer @EnableAuthorizationServer}. + * * @author Dave Syer - * + * */ public interface AuthorizationServerConfigurer { - void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception; + /** + * Configure the security of the Authorization Server, which means in practical terms the /oauth/token endpoint. The + * /oauth/authorize endpoint also needs to be secure, but that is a normal user-facing endpoint and should be + * secured the same way as the rest of your UI, so is not covered here. The default settings cover the most common + * requirements, following recommendations from the OAuth2 spec, so you don't need to do anything here to get a + * basic server up and running. + * + * @param security a fluent configurer for security features + */ + void configure(AuthorizationServerSecurityConfigurer security) throws Exception; + /** + * Configure the {@link ClientDetailsService}, e.g. declaring individual clients and their properties. Note that + * password grant is not enabled (even if some clients are allowed it) unless an {@link AuthenticationManager} is + * supplied to the {@link #configure(AuthorizationServerEndpointsConfigurer)}. At least one client, or a fully + * formed custom {@link ClientDetailsService} must be declared or the server will not start. + * + * @param clients the client details configurer + */ void configure(ClientDetailsServiceConfigurer clients) throws Exception; + /** + * Configure the non-security features of the Authorization Server endpoints, like token store, token + * customizations, user approvals and grant types. You shouldn't need to do anything by default, unless you need + * password grants, in which case you need to provide an {@link AuthenticationManager}. + * + * @param endpoints the endpoints configurer + */ void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java index 369ac50cb..a3168a6e5 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java @@ -22,7 +22,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; -import org.springframework.core.annotation.Order; +import org.springframework.core.Ordered; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity.RequestMatcherConfigurer; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @@ -40,8 +40,9 @@ * */ @Configuration -@Order(3) -public class ResourceServerConfiguration extends WebSecurityConfigurerAdapter { +public class ResourceServerConfiguration extends WebSecurityConfigurerAdapter implements Ordered { + + private int order = 3; @Autowired(required = false) private TokenStore tokenStore; @@ -55,6 +56,15 @@ public class ResourceServerConfiguration extends WebSecurityConfigurerAdapter { @Autowired(required = false) private AuthorizationServerEndpointsConfiguration endpoints; + + @Override + public int getOrder() { + return order; + } + + public void setOrder(int order) { + this.order = order; + } /** * @param configurers the configurers to set diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurer.java index bc4ee118d..b27557633 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurer.java @@ -30,7 +30,8 @@ public interface ResourceServerConfigurer { /** - * Add resource-server specific properties (like a resource id). + * Add resource-server specific properties (like a resource id). The defaults should work for many applications, but + * you might want to change at least the resource id. * * @param resources configurer for the resource server * @throws Exception if there is a problem 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 1f0b41548..b1eb86db5 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 @@ -57,6 +57,7 @@ import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; /** + * Configure the properties and enhanced functionality of the Authorization Server endpoints. * * @author Rob Winch * @author Dave Syer diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java index 82a73d575..e32dc86e2 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java @@ -66,6 +66,10 @@ public final class ResourceServerSecurityConfigurer extends private String resourceId = "oauth2-resource"; private SecurityExpressionHandler expressionHandler = new OAuth2WebSecurityExpressionHandler(); + + public ResourceServerSecurityConfigurer() { + resourceId(resourceId); + } private ClientDetailsService clientDetails() { return getBuilder().getSharedObject(ClientDetailsService.class); @@ -120,6 +124,9 @@ private void registerDefaultAuthenticationEntryPoint(HttpSecurity http) { public ResourceServerSecurityConfigurer resourceId(String resourceId) { this.resourceId = resourceId; + if (authenticationEntryPoint instanceof OAuth2AuthenticationEntryPoint) { + ((OAuth2AuthenticationEntryPoint) authenticationEntryPoint).setRealmName(resourceId); + } return this; } From 75296b8d389e063c61976a8db9c54c9176ded36b Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 12 May 2014 12:20:29 +0100 Subject: [PATCH 259/831] Remove unneeded Boot dependency --- spring-security-oauth2/pom.xml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 78e2da9d7..ece5328f2 100644 --- a/spring-security-oauth2/pom.xml +++ b/spring-security-oauth2/pom.xml @@ -218,11 +218,7 @@ 2.0.0 test - - org.springframework.boot - spring-boot-starter - 1.0.0.RELEASE - + From e5f9ff3be7d9cf1101d96aa3e169e34f33421516 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 13 May 2014 10:09:14 +0100 Subject: [PATCH 260/831] Update to 2.0.0.RELEASE --- pom.xml | 2 +- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index 3b16080e3..203789701 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.0.BUILD-SNAPSHOT + 2.0.0.RELEASE http://static.springframework.org/spring-security/oauth diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index 86f09c156..f19826fef 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.0.BUILD-SNAPSHOT + 2.0.0.RELEASE ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index 2de3a9ae1..d34f043fe 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.0.BUILD-SNAPSHOT + 2.0.0.RELEASE ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index fea01b7d4..05202181e 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.0.BUILD-SNAPSHOT + 2.0.0.RELEASE ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 66328cf18..4f3176dad 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.0.BUILD-SNAPSHOT + 2.0.0.RELEASE ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index d88a907a1..e6cb5b633 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.0.BUILD-SNAPSHOT + 2.0.0.RELEASE spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index d53d7fb33..533391ee2 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.0.BUILD-SNAPSHOT + 2.0.0.RELEASE spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index ece5328f2..cd4504886 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.0.BUILD-SNAPSHOT + 2.0.0.RELEASE spring-security-oauth2 From 93e849ff6447c023995a28116657dc37f3727ca2 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 13 May 2014 10:11:22 +0100 Subject: [PATCH 261/831] Update to new SNAPSHOT version --- pom.xml | 2 +- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index 203789701..f2ad7be3c 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.0.RELEASE + 2.0.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 f19826fef..452c92548 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.0.RELEASE + 2.0.1.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index d34f043fe..a66275bc8 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.0.RELEASE + 2.0.1.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 05202181e..9944148e6 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.0.RELEASE + 2.0.1.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 4f3176dad..786cc5140 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.0.RELEASE + 2.0.1.BUILD-SNAPSHOT ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index e6cb5b633..614ea8696 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.0.RELEASE + 2.0.1.BUILD-SNAPSHOT spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index 533391ee2..6d136d1c5 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.0.RELEASE + 2.0.1.BUILD-SNAPSHOT spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index cd4504886..7f4758807 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.0.RELEASE + 2.0.1.BUILD-SNAPSHOT spring-security-oauth2 From 51eb6d8fdb5fe117f10525017c6d8ee833eeb4b4 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 16 May 2014 15:03:06 +0100 Subject: [PATCH 262/831] Copy refresh token value correctly in JwtAccessTokenConverter Fixes gh-200 --- .../oauth2/provider/token/store/JwtAccessTokenConverter.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java index e84b2b63d..6c225237c 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java @@ -183,6 +183,10 @@ public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentica OAuth2RefreshToken refreshToken = result.getRefreshToken(); if (refreshToken != null) { DefaultOAuth2AccessToken encodedRefreshToken = new DefaultOAuth2AccessToken(accessToken); + encodedRefreshToken.setValue(refreshToken.getValue()); + Map refreshTokenInfo = new LinkedHashMap(accessToken.getAdditionalInformation()); + refreshTokenInfo.put(TOKEN_ID, encodedRefreshToken.getValue()); + encodedRefreshToken.setAdditionalInformation(refreshTokenInfo); DefaultOAuth2RefreshToken token = new DefaultOAuth2RefreshToken(encode(encodedRefreshToken, authentication)); if (refreshToken instanceof ExpiringOAuth2RefreshToken) { Date expiration = ((ExpiringOAuth2RefreshToken) refreshToken).getExpiration(); From 81615a0b9fd130a55a7f9a493e0e907e38a19601 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 16 May 2014 15:41:34 +0100 Subject: [PATCH 263/831] Add additional details to ClientDetailsServiceConfigurer Fixes gh-197 --- .../builders/ClientDetailsServiceBuilder.java | 24 +++++++++++++++++++ ...AuthorizationServerConfigurationTests.java | 7 +++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java index d9b7ed27f..ac0df5230 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java @@ -18,8 +18,10 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; import java.util.Set; import org.springframework.security.config.annotation.SecurityBuilder; @@ -103,6 +105,8 @@ public final class ClientBuilder { private boolean autoApprove; + private Map additionalInformation = new LinkedHashMap(); + private ClientDetails build() { BaseClientDetails result = new BaseClientDetails(); result.setClientId(clientId); @@ -114,6 +118,7 @@ private ClientDetails build() { result.setScope(scopes); result.setAuthorities(AuthorityUtils.createAuthorityList(authorities.toArray(new String[authorities.size()]))); result.setResourceIds(resourceIds); + result.setAdditionalInformation(additionalInformation); if (autoApprove) { result.setAutoApproveScopes(scopes); } @@ -185,6 +190,25 @@ public ClientBuilder autoApprove(String... scopes) { return this; } + public ClientBuilder additionalInformation(Map map) { + this.additionalInformation.putAll(map); + return this; + } + + public ClientBuilder additionalInformation(String... pairs) { + for (String pair : pairs) { + String separator = ":"; + if (!pair.contains(separator) && pair.contains("=")) { + separator = "="; + } + int index = pair.indexOf(separator); + String key = pair.substring(0, index > 0 ? index : pair.length()); + String value = index > 0 ? null : pair.substring(index); + this.additionalInformation.put(key, (Object) value); + } + return this; + } + public ClientDetailsServiceBuilder and() { return ClientDetailsServiceBuilder.this; } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java index f1b88d045..f62c54c80 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java @@ -133,6 +133,9 @@ protected static class AuthorizationServerUnconfigured { protected static class AuthorizationServerVanilla extends AuthorizationServerConfigurerAdapter implements Runnable { @Autowired private AuthorizationEndpoint endpoint; + + @Autowired + private ClientDetailsService clientDetailsService; @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { @@ -142,7 +145,8 @@ public void configure(ClientDetailsServiceConfigurer clients) throws Exception { .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit") .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") .scopes("read", "write", "trust") - .accessTokenValiditySeconds(60); + .accessTokenValiditySeconds(60) + .additionalInformation("foo:bar", "spam:bucket"); // @formatter:on } @@ -156,6 +160,7 @@ public void run() { Map request = handler.getUserApprovalRequest(authorizationRequest, new UsernamePasswordAuthenticationToken("user", "password")); assertTrue(request.containsKey("scopes")); + assertTrue(clientDetailsService.loadClientByClientId("my-trusted-client").getAdditionalInformation().containsKey("foo")); } } From 0c4b50572140264c39b179ce0f17bc0859da5b78 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 16 May 2014 15:51:02 +0100 Subject: [PATCH 264/831] Change throws clause of InMemoryClientDetailsService Fixes gh-196 --- .../oauth2/provider/client/InMemoryClientDetailsService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/InMemoryClientDetailsService.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/InMemoryClientDetailsService.java index 0055b116e..763d9a0bb 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/InMemoryClientDetailsService.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/InMemoryClientDetailsService.java @@ -19,9 +19,9 @@ import java.util.HashMap; import java.util.Map; -import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.ClientRegistrationException; import org.springframework.security.oauth2.provider.NoSuchClientException; /** @@ -33,7 +33,7 @@ public class InMemoryClientDetailsService implements ClientDetailsService { private Map clientDetailsStore = new HashMap(); - public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exception { + public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException { ClientDetails details = clientDetailsStore.get(clientId); if (details == null) { throw new NoSuchClientException("No client with requested id: " + clientId); From 15ae2a0a908352c123e7eb267e16e07af73f7951 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 19 May 2014 12:17:19 +0100 Subject: [PATCH 265/831] Update to 2.0.1.RELEASE --- pom.xml | 2 +- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index f2ad7be3c..408dd1c42 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.1.BUILD-SNAPSHOT + 2.0.1.RELEASE http://static.springframework.org/spring-security/oauth diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index 452c92548..ee89cb737 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.1.BUILD-SNAPSHOT + 2.0.1.RELEASE ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index a66275bc8..60dce7c3a 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.1.BUILD-SNAPSHOT + 2.0.1.RELEASE ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 9944148e6..01740d39f 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.1.BUILD-SNAPSHOT + 2.0.1.RELEASE ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 786cc5140..ef077afb6 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.1.BUILD-SNAPSHOT + 2.0.1.RELEASE ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index 614ea8696..87678131d 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.1.BUILD-SNAPSHOT + 2.0.1.RELEASE spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index 6d136d1c5..8db6f6c3f 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.1.BUILD-SNAPSHOT + 2.0.1.RELEASE spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 7f4758807..58e8612fa 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.1.BUILD-SNAPSHOT + 2.0.1.RELEASE spring-security-oauth2 From 42802632c44dcb721e737b1120928c02b6800343 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 19 May 2014 12:18:50 +0100 Subject: [PATCH 266/831] Update to next dev version --- pom.xml | 2 +- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index 408dd1c42..a43ef542d 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.1.RELEASE + 2.0.2.BUILD-SNAPSHOT http://static.springframework.org/spring-security/oauth diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index ee89cb737..3fe41b53e 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.1.RELEASE + 2.0.2.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index 60dce7c3a..7ba36a18a 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.1.RELEASE + 2.0.2.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 01740d39f..29b47da6e 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.1.RELEASE + 2.0.2.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index ef077afb6..413f12b37 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.1.RELEASE + 2.0.2.BUILD-SNAPSHOT ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index 87678131d..bd047bc78 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.1.RELEASE + 2.0.2.BUILD-SNAPSHOT spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index 8db6f6c3f..c2798c328 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.1.RELEASE + 2.0.2.BUILD-SNAPSHOT spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 58e8612fa..79d44396e 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.1.RELEASE + 2.0.2.BUILD-SNAPSHOT spring-security-oauth2 From f22332dd07cfc6a6ea8d279adba417b131765a76 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Sat, 24 May 2014 12:32:17 +0100 Subject: [PATCH 267/831] Fix repository ids --- pom.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index a43ef542d..da2bdf4db 100644 --- a/pom.xml +++ b/pom.xml @@ -93,19 +93,19 @@ bootstrap - spring-milestones + repo.spring.io/milestone Spring Framework Milestone Repository - http://maven.springframework.org.s3.amazonaws.com/milestone + http://repo.spring.io/libs-milestone-local - spring-releases + repo.spring.io/release Spring Framework Release Repository - http://maven.springframework.org.s3.amazonaws.com/release + http://repo.spring.io/libs-release-local - spring-snapshots + repo.spring.io/snapshot Spring Framework Maven Snapshot Repository - http://maven.springframework.org.s3.amazonaws.com/snapshot + http://repo.spring.io/libs-snapshot-local true From 20903ff56bbea896c7f2709f61dc6cf1c5b6b8ef Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 10 Jun 2014 10:07:44 +0100 Subject: [PATCH 268/831] Deprecate ImplicitGrantService and add new ImplicitTokenRequest The ImplicitGrantService introduced a race condition in the implicit grant (but only for concurrent requests from the same client with the same parameters, so unlikely to be a problem in a real system). The best way to solve it seems to be to deprecate that service (which is only used in the scope of a single method in AuthorizationEndpoint, so there is no need for peristence or anything) and replace it with a new way to carry the OAuth2Request down into the TokenGranter. Fixes gh-212 --- ...orizationServerEndpointsConfiguration.java | 6 - ...uthorizationServerEndpointsConfigurer.java | 9 - ...thorizationServerBeanDefinitionParser.java | 55 ++---- .../endpoint/AuthorizationEndpoint.java | 25 ++- .../implicit/ImplicitGrantService.java | 3 + .../implicit/ImplicitTokenGranter.java | 8 +- .../implicit/ImplicitTokenRequest.java | 39 +++++ .../InMemoryImplicitGrantService.java | 1 + .../oauth2/spring-security-oauth2-2.0.xsd | 2 +- .../endpoint/AuthorizationEndpointTests.java | 165 ++++++++++-------- 10 files changed, 173 insertions(+), 140 deletions(-) create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenRequest.java 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 3329ebe18..a3565b975 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 @@ -43,7 +43,6 @@ import org.springframework.security.oauth2.provider.endpoint.TokenKeyEndpoint; import org.springframework.security.oauth2.provider.endpoint.WhitelabelApprovalEndpoint; import org.springframework.security.oauth2.provider.endpoint.WhitelabelErrorEndpoint; -import org.springframework.security.oauth2.provider.implicit.ImplicitGrantService; import org.springframework.security.oauth2.provider.token.ConsumerTokenServices; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore; @@ -92,7 +91,6 @@ public AuthorizationEndpoint authorizationEndpoint() throws Exception { authorizationEndpoint.setOAuth2RequestFactory(oauth2RequestFactory()); authorizationEndpoint.setOAuth2RequestValidator(oauth2RequestValidator()); authorizationEndpoint.setUserApprovalHandler(userApprovalHandler()); - authorizationEndpoint.setImplicitGrantService(implicitGrantService()); return authorizationEndpoint; } @@ -138,10 +136,6 @@ public TokenStore tokenStore() throws Exception { return endpoints.getTokenStore(); } - private ImplicitGrantService implicitGrantService() throws Exception { - return endpoints.getImplicitGrantService(); - } - private OAuth2RequestFactory oauth2RequestFactory() throws Exception { return endpoints.getOAuth2RequestFactory(); } 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 b1eb86db5..a0ca75d32 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 @@ -37,9 +37,7 @@ import org.springframework.security.oauth2.provider.code.AuthorizationCodeTokenGranter; import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices; import org.springframework.security.oauth2.provider.endpoint.FrameworkEndpointHandlerMapping; -import org.springframework.security.oauth2.provider.implicit.ImplicitGrantService; import org.springframework.security.oauth2.provider.implicit.ImplicitTokenGranter; -import org.springframework.security.oauth2.provider.implicit.InMemoryImplicitGrantService; import org.springframework.security.oauth2.provider.password.ResourceOwnerPasswordTokenGranter; import org.springframework.security.oauth2.provider.refresh.RefreshTokenGranter; import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory; @@ -73,8 +71,6 @@ public final class AuthorizationServerEndpointsConfigurer { private ResourceServerTokenServices resourceTokenServices; - private ImplicitGrantService implicitGrantService = new InMemoryImplicitGrantService(); - private TokenStore tokenStore; private TokenEnhancer tokenEnhancer; @@ -219,10 +215,6 @@ public ResourceServerTokenServices getResourceServerTokenServices() { return resourceTokenServices(); } - public ImplicitGrantService getImplicitGrantService() { - return implicitGrantService; - } - public AuthorizationCodeServices getAuthorizationCodeServices() { return authorizationCodeServices(); } @@ -380,7 +372,6 @@ private TokenGranter tokenGranter() { clientDetails, requestFactory)); tokenGranters.add(new RefreshTokenGranter(tokenServices, clientDetails, requestFactory)); ImplicitTokenGranter implicit = new ImplicitTokenGranter(tokenServices, clientDetails, requestFactory); - implicit.setImplicitGrantService(implicitGrantService); tokenGranters.add(implicit); tokenGranters.add(new ClientCredentialsTokenGranter(tokenServices, clientDetails, requestFactory)); if (authenticationManager != null) { 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 a9563985c..48a7da559 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 @@ -34,7 +34,6 @@ import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint; import org.springframework.security.oauth2.provider.endpoint.WhitelabelApprovalEndpoint; import org.springframework.security.oauth2.provider.implicit.ImplicitTokenGranter; -import org.springframework.security.oauth2.provider.implicit.InMemoryImplicitGrantService; import org.springframework.security.oauth2.provider.password.ResourceOwnerPasswordTokenGranter; import org.springframework.security.oauth2.provider.refresh.RefreshTokenGranter; import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory; @@ -67,31 +66,22 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P String errorPage = element.getAttribute("error-page"); String approvalParameter = element.getAttribute("approval-parameter-name"); String redirectResolverRef = element.getAttribute("redirect-resolver-ref"); - - String implicitGrantServiceRef = element.getAttribute("implicit-grant-service-ref"); + String oAuth2RequestValidatorRef = element.getAttribute("request-validator-ref"); // Create a bean definition speculatively for the auth endpoint BeanDefinitionBuilder authorizationEndpointBean = BeanDefinitionBuilder .rootBeanDefinition(AuthorizationEndpoint.class); - if (!StringUtils.hasText(implicitGrantServiceRef)) { - implicitGrantServiceRef = "inMemoryImplicitGrantService"; - BeanDefinitionBuilder implicitGrantService = BeanDefinitionBuilder - .rootBeanDefinition(InMemoryImplicitGrantService.class); - parserContext.getRegistry().registerBeanDefinition(implicitGrantServiceRef, - implicitGrantService.getBeanDefinition()); - } - if (!StringUtils.hasText(oAuth2RequestValidatorRef)) { oAuth2RequestValidatorRef = "defaultOAuth2RequestValidator"; BeanDefinitionBuilder oAuth2RequestValidator = BeanDefinitionBuilder .rootBeanDefinition(DefaultOAuth2RequestValidator.class); - parserContext.getRegistry().registerBeanDefinition(oAuth2RequestValidatorRef, + parserContext.getRegistry().registerBeanDefinition(oAuth2RequestValidatorRef, oAuth2RequestValidator.getBeanDefinition()); } authorizationEndpointBean.addPropertyReference("oAuth2RequestValidator", oAuth2RequestValidatorRef); - + if (!StringUtils.hasText(oAuth2RequestFactoryRef)) { oAuth2RequestFactoryRef = "oAuth2AuthorizationRequestManager"; BeanDefinitionBuilder oAuth2RequestManager = BeanDefinitionBuilder @@ -100,8 +90,7 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P parserContext.getRegistry().registerBeanDefinition(oAuth2RequestFactoryRef, oAuth2RequestManager.getBeanDefinition()); } - authorizationEndpointBean.addPropertyReference("implicitGrantService", implicitGrantServiceRef); - + ManagedList tokenGranters = null; if (!StringUtils.hasText(tokenGranterRef)) { tokenGranterRef = "oauth2TokenGranter"; @@ -116,7 +105,7 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P boolean registerAuthorizationEndpoint = false; Element authorizationCodeElement = DomUtils.getChildElementByTagName(element, "authorization-code"); - + if (authorizationCodeElement != null && !"true".equalsIgnoreCase(authorizationCodeElement.getAttribute("disabled"))) { // authorization code grant configuration. @@ -147,8 +136,7 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P authorizationEndpointBean.addPropertyReference("clientTokenCache", clientTokenCacheRef); } if (StringUtils.hasText(oAuth2RequestFactoryRef)) { - authorizationEndpointBean.addPropertyReference("oAuth2RequestFactory", - oAuth2RequestFactoryRef); + authorizationEndpointBean.addPropertyReference("oAuth2RequestFactory", oAuth2RequestFactoryRef); } if (tokenGranters != null) { @@ -160,7 +148,7 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P if (tokenGranters != null) { Element refreshTokenElement = DomUtils.getChildElementByTagName(element, "refresh-token"); - + if (refreshTokenElement != null && !"true".equalsIgnoreCase(refreshTokenElement.getAttribute("disabled"))) { BeanDefinitionBuilder refreshTokenGranterBean = BeanDefinitionBuilder .rootBeanDefinition(RefreshTokenGranter.class); @@ -173,13 +161,6 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P if (implicitElement != null && !"true".equalsIgnoreCase(implicitElement.getAttribute("disabled"))) { BeanDefinitionBuilder implicitGranterBean = BeanDefinitionBuilder .rootBeanDefinition(ImplicitTokenGranter.class); - - String implicitGrantServiceRef2 = implicitElement.getAttribute("implicit-grant-service-ref"); - if (!StringUtils.hasText(implicitGrantServiceRef2)) { - implicitGrantServiceRef2 = implicitGrantServiceRef; - } - implicitGranterBean.addPropertyReference("implicitGrantService", implicitGrantServiceRef2); - implicitGranterBean.addConstructorArgReference(tokenServicesRef); implicitGranterBean.addConstructorArgReference(clientDetailsRef); implicitGranterBean.addConstructorArgReference(oAuth2RequestFactoryRef); @@ -212,10 +193,10 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P tokenGranters.add(clientPasswordTokenGranter.getBeanDefinition()); } List customGrantElements = DomUtils.getChildElementsByTagName(element, "custom-grant"); - for(Element customGrantElement: customGrantElements) { - if(!"true".equalsIgnoreCase(customGrantElement.getAttribute("disabled"))) { + for (Element customGrantElement : customGrantElements) { + if (!"true".equalsIgnoreCase(customGrantElement.getAttribute("disabled"))) { String customGranterRef = customGrantElement.getAttribute("token-granter-ref"); - tokenGranters.add( new RuntimeBeanReference(customGranterRef) ); + tokenGranters.add(new RuntimeBeanReference(customGranterRef)); } } } @@ -269,23 +250,26 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P BeanDefinitionBuilder handlerMappingBean = BeanDefinitionBuilder .rootBeanDefinition(FrameworkEndpointHandlerMapping.class); if (StringUtils.hasText(tokenEndpointUrl) || StringUtils.hasText(authorizationEndpointUrl)) { - ManagedMap mappings = new ManagedMap(); + ManagedMap mappings = new ManagedMap(); if (StringUtils.hasText(tokenEndpointUrl)) { mappings.put("/oauth/token", new TypedStringValue(tokenEndpointUrl, String.class)); } if (StringUtils.hasText(authorizationEndpointUrl)) { - mappings.put("/oauth/authorize", new TypedStringValue(authorizationEndpointUrl,String.class)); + mappings.put("/oauth/authorize", new TypedStringValue(authorizationEndpointUrl, String.class)); } if (StringUtils.hasText(approvalPage)) { - mappings.put("/oauth/confirm_access", new TypedStringValue(approvalPage,String.class)); + mappings.put("/oauth/confirm_access", new TypedStringValue(approvalPage, String.class)); } handlerMappingBean.addPropertyValue("mappings", mappings); } if (StringUtils.hasText(approvalParameter) && registerAuthorizationEndpoint) { if (!StringUtils.hasText(userApprovalHandlerRef)) { - BeanDefinitionBuilder userApprovalHandler = BeanDefinitionBuilder.rootBeanDefinition(DefaultUserApprovalHandler.class); - userApprovalHandler.addPropertyValue("approvalParameter", new TypedStringValue(approvalParameter, String.class)); - authorizationEndpointBean.addPropertyValue("userApprovalHandler", userApprovalHandler.getBeanDefinition()); + BeanDefinitionBuilder userApprovalHandler = BeanDefinitionBuilder + .rootBeanDefinition(DefaultUserApprovalHandler.class); + userApprovalHandler.addPropertyValue("approvalParameter", new TypedStringValue(approvalParameter, + String.class)); + authorizationEndpointBean.addPropertyValue("userApprovalHandler", + userApprovalHandler.getBeanDefinition()); } handlerMappingBean.addPropertyValue("approvalParameter", approvalParameter); } @@ -293,7 +277,6 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P parserContext.getRegistry().registerBeanDefinition("oauth2HandlerMapping", handlerMappingBean.getBeanDefinition()); - // We aren't defining a filter... return null; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java index 57b72dcca..5abf42ea8 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java @@ -48,8 +48,7 @@ import org.springframework.security.oauth2.provider.approval.UserApprovalHandler; import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices; -import org.springframework.security.oauth2.provider.implicit.ImplicitGrantService; -import org.springframework.security.oauth2.provider.implicit.InMemoryImplicitGrantService; +import org.springframework.security.oauth2.provider.implicit.ImplicitTokenRequest; import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestValidator; import org.springframework.util.StringUtils; import org.springframework.web.HttpSessionRequiredException; @@ -99,12 +98,12 @@ public class AuthorizationEndpoint extends AbstractEndpoint { private OAuth2RequestValidator oauth2RequestValidator = new DefaultOAuth2RequestValidator(); - private ImplicitGrantService implicitGrantService = new InMemoryImplicitGrantService(); - private String userApprovalPage = "forward:/oauth/confirm_access"; private String errorPage = "forward:/oauth/error"; + private Object implicitLock = new Object(); + public void setSessionAttributeStore(SessionAttributeStore sessionAttributeStore) { this.sessionAttributeStore = sessionAttributeStore; } @@ -251,8 +250,7 @@ private ModelAndView getImplicitGrantResponse(AuthorizationRequest authorization try { TokenRequest tokenRequest = getOAuth2RequestFactory().createTokenRequest(authorizationRequest, "implicit"); OAuth2Request storedOAuth2Request = getOAuth2RequestFactory().createOAuth2Request(authorizationRequest); - implicitGrantService.store(storedOAuth2Request, tokenRequest); - OAuth2AccessToken accessToken = getTokenGranter().grant("implicit", tokenRequest); + OAuth2AccessToken accessToken = getAccessTokenForImplicitGrant(tokenRequest, storedOAuth2Request); if (accessToken == null) { throw new UnsupportedResponseTypeException("Unsupported response type: token"); } @@ -265,6 +263,17 @@ private ModelAndView getImplicitGrantResponse(AuthorizationRequest authorization } } + private OAuth2AccessToken getAccessTokenForImplicitGrant(TokenRequest tokenRequest, + OAuth2Request storedOAuth2Request) { + OAuth2AccessToken accessToken = null; + // These 1 method calls have to be atomic, otherwise the ImplicitGrantService can have a race condition where + // one thread removes the token request before another has a chance to redeem it. + synchronized (this.implicitLock) { + accessToken = getTokenGranter().grant("implicit", new ImplicitTokenRequest(tokenRequest, storedOAuth2Request)); + } + return accessToken; + } + private View getAuthorizationCodeResponse(AuthorizationRequest authorizationRequest, Authentication authUser) { try { return new RedirectView(getSuccessfulRedirect(authorizationRequest, @@ -427,8 +436,8 @@ public void setOAuth2RequestValidator(OAuth2RequestValidator oauth2RequestValida this.oauth2RequestValidator = oauth2RequestValidator; } - public void setImplicitGrantService(ImplicitGrantService implicitGrantService) { - this.implicitGrantService = implicitGrantService; + @SuppressWarnings("deprecation") + public void setImplicitGrantService(org.springframework.security.oauth2.provider.implicit.ImplicitGrantService implicitGrantService) { } @ExceptionHandler(ClientRegistrationException.class) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitGrantService.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitGrantService.java index 3b81c1aba..105a3d8ce 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitGrantService.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitGrantService.java @@ -10,8 +10,11 @@ * AuthorizationRequest, while still allowing the ImplicitTokenGranter to adhere to the TokenGranter interface. * * @author Amanda Anganes + * + * @deprecated with no replacement (it shouldn't be necessary to use this strategy since 2.0.2) * */ +@Deprecated public interface ImplicitGrantService { /** diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java index b08bdaf05..73137cade 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java @@ -28,6 +28,7 @@ import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.token.AbstractTokenGranter; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; +import org.springframework.util.Assert; /** * @author Dave Syer @@ -37,8 +38,6 @@ public class ImplicitTokenGranter extends AbstractTokenGranter { private static final String GRANT_TYPE = "implicit"; - private ImplicitGrantService service = new InMemoryImplicitGrantService(); - public ImplicitTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory) { super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE); } @@ -50,15 +49,16 @@ protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, Tok if (userAuth==null || !userAuth.isAuthenticated()) { throw new InsufficientAuthenticationException("There is no currently logged in user"); } + Assert.state(clientToken instanceof ImplicitTokenRequest, "An ImplicitTokenRequest is required here. Caller needs to wrap the TokenRequest."); - OAuth2Request requestForStorage = service.remove(clientToken); + OAuth2Request requestForStorage = ((ImplicitTokenRequest)clientToken).getOAuth2Request(); return new OAuth2Authentication(requestForStorage, userAuth); } + @SuppressWarnings("deprecation") public void setImplicitGrantService(ImplicitGrantService service) { - this.service = service; } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenRequest.java new file mode 100644 index 000000000..b7e967f74 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenRequest.java @@ -0,0 +1,39 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.springframework.security.oauth2.provider.implicit; + +import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.TokenRequest; + +/** + * @author Dave Syer + * + * @since 2.0.2 + * + */ +@SuppressWarnings("serial") +public class ImplicitTokenRequest extends TokenRequest { + + private OAuth2Request oauth2Request; + + public ImplicitTokenRequest(TokenRequest tokenRequest, OAuth2Request oauth2Request) { + super(tokenRequest.getRequestParameters(), tokenRequest.getClientId(), tokenRequest.getScope(), tokenRequest.getGrantType()); + this.oauth2Request = oauth2Request; + } + + public OAuth2Request getOAuth2Request() { + return oauth2Request; + } + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/InMemoryImplicitGrantService.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/InMemoryImplicitGrantService.java index c6048a4c7..6156fac1a 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/InMemoryImplicitGrantService.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/InMemoryImplicitGrantService.java @@ -11,6 +11,7 @@ * @author Amanda Anganes * */ +@SuppressWarnings("deprecation") public class InMemoryImplicitGrantService implements ImplicitGrantService { protected final ConcurrentHashMap requestStore = new ConcurrentHashMap(); diff --git a/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-2.0.xsd b/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-2.0.xsd index 88b84156a..31281626b 100644 --- a/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-2.0.xsd +++ b/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-2.0.xsd @@ -238,7 +238,7 @@ - The reference to the bean that defines the + @deprecated (since 2.0.2 this is unnecessary). The reference to the bean that defines the implicit grant service. diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java index 2c750b267..12fcd1e03 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java @@ -86,11 +86,10 @@ private AuthorizationRequest getAuthorizationRequest(String clientId, String red if (responseTypes != null) { parameters.put(OAuth2Utils.RESPONSE_TYPE, OAuth2Utils.formatParameterList(responseTypes)); } - return new AuthorizationRequest(parameters, Collections. emptyMap(), - parameters.get(OAuth2Utils.CLIENT_ID), - OAuth2Utils.parseParameterList(parameters.get(OAuth2Utils.SCOPE)), null, - null, false, parameters.get(OAuth2Utils.STATE), - parameters.get(OAuth2Utils.REDIRECT_URI), + return new AuthorizationRequest(parameters, Collections. emptyMap(), + parameters.get(OAuth2Utils.CLIENT_ID), + OAuth2Utils.parseParameterList(parameters.get(OAuth2Utils.SCOPE)), null, null, false, + parameters.get(OAuth2Utils.STATE), parameters.get(OAuth2Utils.REDIRECT_URI), OAuth2Utils.parseParameterList(parameters.get(OAuth2Utils.RESPONSE_TYPE))); } @@ -121,9 +120,10 @@ public void testMandatoryProperties() throws Exception { @Test public void testStartAuthorizationCodeFlow() throws Exception { - - ModelAndView result = endpoint.authorize(model, getAuthorizationRequest("foo", null, null, "read", Collections.singleton("code")) - .getRequestParameters(), sessionStatus, principal); + + ModelAndView result = endpoint.authorize(model, + getAuthorizationRequest("foo", null, null, "read", Collections.singleton("code")) + .getRequestParameters(), sessionStatus, principal); assertEquals("forward:/oauth/confirm_access", result.getViewName()); } @@ -132,8 +132,9 @@ public void testApprovalStoreAddsScopes() throws Exception { ApprovalStoreUserApprovalHandler userApprovalHandler = new ApprovalStoreUserApprovalHandler(); userApprovalHandler.setApprovalStore(new InMemoryApprovalStore()); endpoint.setUserApprovalHandler(userApprovalHandler); - ModelAndView result = endpoint.authorize(model, getAuthorizationRequest("foo", null, null, "read", Collections.singleton("code")) - .getRequestParameters(), sessionStatus, principal); + ModelAndView result = endpoint.authorize(model, + getAuthorizationRequest("foo", null, null, "read", Collections.singleton("code")) + .getRequestParameters(), sessionStatus, principal); assertEquals("forward:/oauth/confirm_access", result.getViewName()); assertTrue(result.getModel().containsKey("scopes")); } @@ -141,68 +142,75 @@ public void testApprovalStoreAddsScopes() throws Exception { @Test(expected = OAuth2Exception.class) public void testStartAuthorizationCodeFlowForClientCredentialsFails() throws Exception { client.setAuthorizedGrantTypes(Collections.singleton("client_credentials")); - ModelAndView result = endpoint.authorize(model, getAuthorizationRequest("foo", null, null, null, Collections.singleton("code")) - .getRequestParameters(), sessionStatus, principal); + ModelAndView result = endpoint.authorize(model, + getAuthorizationRequest("foo", null, null, null, Collections.singleton("code")).getRequestParameters(), + sessionStatus, principal); assertEquals("forward:/oauth/confirm_access", result.getViewName()); } @Test public void testAuthorizationCodeWithFragment() throws Exception { endpoint.setAuthorizationCodeServices(new StubAuthorizationCodeServices()); - model.put("authorizationRequest", getAuthorizationRequest("foo", "http://anywhere.com/#bar", null, null, Collections.singleton("code"))); - View result = endpoint.approveOrDeny( - Collections.singletonMap(OAuth2Utils.USER_OAUTH_APPROVAL, "true"), model, sessionStatus, - principal); + model.put("authorizationRequest", + getAuthorizationRequest("foo", "http://anywhere.com/#bar", null, null, Collections.singleton("code"))); + View result = endpoint.approveOrDeny(Collections.singletonMap(OAuth2Utils.USER_OAUTH_APPROVAL, "true"), model, + sessionStatus, principal); assertEquals("http://anywhere.com/?code=thecode#bar", ((RedirectView) result).getUrl()); } @Test public void testAuthorizationCodeWithQueryParams() throws Exception { endpoint.setAuthorizationCodeServices(new StubAuthorizationCodeServices()); - model.put("authorizationRequest", getAuthorizationRequest("foo", "http://anywhere.com/?foo=bar", null, null, Collections.singleton("code"))); - View result = endpoint.approveOrDeny( - Collections.singletonMap(OAuth2Utils.USER_OAUTH_APPROVAL, "true"), model, sessionStatus, - principal); + model.put( + "authorizationRequest", + getAuthorizationRequest("foo", "http://anywhere.com/?foo=bar", null, null, Collections.singleton("code"))); + View result = endpoint.approveOrDeny(Collections.singletonMap(OAuth2Utils.USER_OAUTH_APPROVAL, "true"), model, + sessionStatus, principal); assertEquals("http://anywhere.com/?foo=bar&code=thecode", ((RedirectView) result).getUrl()); } @Test public void testAuthorizationCodeWithTrickyState() throws Exception { endpoint.setAuthorizationCodeServices(new StubAuthorizationCodeServices()); - model.put("authorizationRequest", getAuthorizationRequest("foo", "http://anywhere.com/", " =?s", null, Collections.singleton("code"))); - View result = endpoint.approveOrDeny( - Collections.singletonMap(OAuth2Utils.USER_OAUTH_APPROVAL, "true"), model, sessionStatus, - principal); + model.put("authorizationRequest", + getAuthorizationRequest("foo", "http://anywhere.com/", " =?s", null, Collections.singleton("code"))); + View result = endpoint.approveOrDeny(Collections.singletonMap(OAuth2Utils.USER_OAUTH_APPROVAL, "true"), model, + sessionStatus, principal); assertEquals("http://anywhere.com/?code=thecode&state=%20%3D?s", ((RedirectView) result).getUrl()); } @Test public void testAuthorizationCodeWithMultipleQueryParams() throws Exception { endpoint.setAuthorizationCodeServices(new StubAuthorizationCodeServices()); - model.put("authorizationRequest", getAuthorizationRequest("foo", "http://anywhere.com/?foo=bar&bar=foo", null, null, Collections.singleton("code"))); - View result = endpoint.approveOrDeny( - Collections.singletonMap(OAuth2Utils.USER_OAUTH_APPROVAL, "true"), model, sessionStatus, - principal); + model.put( + "authorizationRequest", + getAuthorizationRequest("foo", "http://anywhere.com/?foo=bar&bar=foo", null, null, + Collections.singleton("code"))); + View result = endpoint.approveOrDeny(Collections.singletonMap(OAuth2Utils.USER_OAUTH_APPROVAL, "true"), model, + sessionStatus, principal); assertEquals("http://anywhere.com/?foo=bar&bar=foo&code=thecode", ((RedirectView) result).getUrl()); } @Test public void testAuthorizationCodeWithTrickyQueryParams() throws Exception { endpoint.setAuthorizationCodeServices(new StubAuthorizationCodeServices()); - model.put("authorizationRequest", getAuthorizationRequest("foo", "http://anywhere.com/?foo=b%20=&bar=f%20$", null, null, Collections.singleton("code"))); - View result = endpoint.approveOrDeny( - Collections.singletonMap(OAuth2Utils.USER_OAUTH_APPROVAL, "true"), model, sessionStatus, - principal); + model.put( + "authorizationRequest", + getAuthorizationRequest("foo", "http://anywhere.com/?foo=b%20=&bar=f%20$", null, null, + Collections.singleton("code"))); + View result = endpoint.approveOrDeny(Collections.singletonMap(OAuth2Utils.USER_OAUTH_APPROVAL, "true"), model, + sessionStatus, principal); assertEquals("http://anywhere.com/?foo=b%20%3D&bar=f%20http://anywhere.com?foo=b%20%3D&bar=f%20$&code=thecodecode=thecode", ((RedirectView) result).getUrl()); } @Test public void testAuthorizationCodeError() throws Exception { endpoint.setUserApprovalHandler(new DefaultUserApprovalHandler() { - public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { + public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest, + Authentication userAuthentication) { return authorizationRequest; } - + public AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { return authorizationRequest; @@ -218,9 +226,10 @@ public String createAuthorizationCode(OAuth2Authentication authentication) { throw new InvalidScopeException("FOO"); } }); - ModelAndView result = endpoint.authorize(model, - getAuthorizationRequest("foo", "http://anywhere.com/", "mystate", "myscope", Collections.singleton("code")) - .getRequestParameters(), sessionStatus, principal); + ModelAndView result = endpoint.authorize( + model, + getAuthorizationRequest("foo", "http://anywhere.com/", "mystate", "myscope", + Collections.singleton("code")).getRequestParameters(), sessionStatus, principal); String url = ((RedirectView) result.getView()).getUrl(); assertTrue("Wrong view: " + result, url.startsWith("http://anywhere.com/")); assertTrue("No error: " + result, url.contains("?error=")); @@ -233,8 +242,9 @@ public void testAuthorizationCodeWithMultipleResponseTypes() throws Exception { Set responseTypes = new HashSet(); responseTypes.add("code"); responseTypes.add("other"); - ModelAndView result = endpoint.authorize(model, getAuthorizationRequest("foo", null, null, "read", responseTypes) - .getRequestParameters(), sessionStatus, principal); + ModelAndView result = endpoint.authorize(model, + getAuthorizationRequest("foo", null, null, "read", responseTypes).getRequestParameters(), + sessionStatus, principal); assertEquals("forward:/oauth/confirm_access", result.getViewName()); } @@ -244,16 +254,17 @@ public void testImplicitPreApproved() throws Exception { public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) { DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken("FOO"); - token.setAdditionalInformation(Collections.singletonMap("foo", (Object)"bar")); + token.setAdditionalInformation(Collections.singletonMap("foo", (Object) "bar")); return token; } }); endpoint.setUserApprovalHandler(new DefaultUserApprovalHandler() { - public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { + public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest, + Authentication userAuthentication) { return authorizationRequest; } - + public AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { return authorizationRequest; @@ -265,8 +276,8 @@ public boolean isApproved(AuthorizationRequest authorizationRequest, Authenticat }); AuthorizationRequest authorizationRequest = getAuthorizationRequest("foo", "http://anywhere.com/", "mystate", "myscope", Collections.singleton("token")); - ModelAndView result = endpoint.authorize(model, authorizationRequest.getRequestParameters(), - sessionStatus, principal); + ModelAndView result = endpoint.authorize(model, authorizationRequest.getRequestParameters(), sessionStatus, + principal); String url = ((RedirectView) result.getView()).getUrl(); assertTrue("Wrong view: " + result, url.startsWith("http://anywhere.com/")); assertTrue("Wrong state: " + result, url.contains("&state=mystate")); @@ -284,10 +295,11 @@ public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) { } }); endpoint.setUserApprovalHandler(new DefaultUserApprovalHandler() { - public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { + public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest, + Authentication userAuthentication) { return authorizationRequest; } - + public AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { return authorizationRequest; @@ -299,8 +311,8 @@ public boolean isApproved(AuthorizationRequest authorizationRequest, Authenticat }); AuthorizationRequest authorizationRequest = getAuthorizationRequest("foo", "http://anywhere.com/", "mystate", "myscope", Collections.singleton("token")); - ModelAndView result = endpoint.authorize(model, authorizationRequest.getRequestParameters(), - sessionStatus, principal); + ModelAndView result = endpoint.authorize(model, authorizationRequest.getRequestParameters(), sessionStatus, + principal); String url = ((RedirectView) result.getView()).getUrl(); assertTrue("Wrong scope: " + result, url.contains("&scope=read")); } @@ -318,10 +330,10 @@ public boolean isApproved(AuthorizationRequest authorizationRequest, Authenticat return true; } }); - AuthorizationRequest authorizationRequest = getAuthorizationRequest("foo", "http://anywhere.com/?foo=bar", "mystate", - "myscope", Collections.singleton("token")); - ModelAndView result = endpoint.authorize(model, authorizationRequest.getRequestParameters(), - sessionStatus, principal); + AuthorizationRequest authorizationRequest = getAuthorizationRequest("foo", "http://anywhere.com/?foo=bar", + "mystate", "myscope", Collections.singleton("token")); + ModelAndView result = endpoint.authorize(model, authorizationRequest.getRequestParameters(), sessionStatus, + principal); String url = ((RedirectView) result.getView()).getUrl(); assertTrue("Wrong url: " + result, url.contains("foo=bar")); } @@ -340,14 +352,12 @@ public boolean isApproved(AuthorizationRequest authorizationRequest, Authenticat return true; } - public AuthorizationRequest checkForPreApproval( - AuthorizationRequest authorizationRequest, + public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { return authorizationRequest; } - public AuthorizationRequest updateAfterApproval( - AuthorizationRequest authorizationRequest, + public AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { return authorizationRequest; } @@ -355,8 +365,8 @@ public AuthorizationRequest updateAfterApproval( client.setScope(Collections.singleton("read")); AuthorizationRequest authorizationRequest = getAuthorizationRequest("foo", "http://anywhere.com/", "mystate", null, Collections.singleton("token")); - ModelAndView result = endpoint.authorize(model,authorizationRequest.getRequestParameters(), - sessionStatus, principal); + ModelAndView result = endpoint.authorize(model, authorizationRequest.getRequestParameters(), sessionStatus, + principal); String url = ((RedirectView) result.getView()).getUrl(); assertTrue("Wrong scope: " + result, url.contains("&scope=read%20write")); } @@ -372,14 +382,13 @@ public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) { public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { return true; } - public AuthorizationRequest checkForPreApproval( - AuthorizationRequest authorizationRequest, + + public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { return authorizationRequest; } - public AuthorizationRequest updateAfterApproval( - AuthorizationRequest authorizationRequest, + public AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { return authorizationRequest; } @@ -387,8 +396,8 @@ public AuthorizationRequest updateAfterApproval( client.setScope(Collections.singleton("smallscope")); AuthorizationRequest authorizationRequest = getAuthorizationRequest("foo", "http://anywhere.com/", "mystate", "bigscope", Collections.singleton("token")); - ModelAndView result = endpoint.authorize(model, authorizationRequest.getRequestParameters(), - sessionStatus, principal); + ModelAndView result = endpoint.authorize(model, authorizationRequest.getRequestParameters(), sessionStatus, + principal); String url = ((RedirectView) result.getView()).getUrl(); assertTrue("Wrong view: " + result, url.startsWith("http://anywhere.com/")); } @@ -402,18 +411,19 @@ public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) { }); AuthorizationRequest authorizationRequest = getAuthorizationRequest("foo", "http://anywhere.com/", "mystate", "myscope", Collections.singleton("token")); - ModelAndView result = endpoint.authorize(model, authorizationRequest.getRequestParameters(), - sessionStatus, principal); + ModelAndView result = endpoint.authorize(model, authorizationRequest.getRequestParameters(), sessionStatus, + principal); assertEquals("forward:/oauth/confirm_access", result.getViewName()); } @Test public void testImplicitError() throws Exception { endpoint.setUserApprovalHandler(new DefaultUserApprovalHandler() { - public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { + public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationRequest, + Authentication userAuthentication) { return authorizationRequest; } - + public AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { return authorizationRequest; @@ -430,8 +440,8 @@ public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) { }); AuthorizationRequest authorizationRequest = getAuthorizationRequest("foo", "http://anywhere.com/", "mystate", "myscope", Collections.singleton("token")); - ModelAndView result = endpoint.authorize(model, authorizationRequest.getRequestParameters(), - sessionStatus, principal); + ModelAndView result = endpoint.authorize(model, authorizationRequest.getRequestParameters(), sessionStatus, + principal); String url = ((RedirectView) result.getView()).getUrl(); assertTrue("Wrong view: " + result, url.startsWith("http://anywhere.com/")); @@ -442,7 +452,8 @@ public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) { @Test public void testApproveOrDeny() throws Exception { - AuthorizationRequest request = getAuthorizationRequest("foo", "http://anywhere.com/", null, null, Collections.singleton("code")); + AuthorizationRequest request = getAuthorizationRequest("foo", "http://anywhere.com/", null, null, + Collections.singleton("code")); request.setApproved(true); Map approvalParameters = new HashMap(); approvalParameters.put("user_oauth_approval", "true"); @@ -453,7 +464,8 @@ public void testApproveOrDeny() throws Exception { @Test public void testApprovalDenied() throws Exception { - model.put("authorizationRequest", getAuthorizationRequest("foo", "http://anywhere.com/", null, null, Collections.singleton("code"))); + model.put("authorizationRequest", + getAuthorizationRequest("foo", "http://anywhere.com/", null, null, Collections.singleton("code"))); Map approvalParameters = new HashMap(); approvalParameters.put("user_oauth_approval", "false"); View result = endpoint.approveOrDeny(approvalParameters, model, sessionStatus, principal); @@ -465,16 +477,17 @@ public void testApprovalDenied() throws Exception { @Test public void testDirectApproval() throws Exception { ModelAndView result = endpoint.authorize(model, - getAuthorizationRequest("foo", "http://anywhere.com/", null, "read", Collections.singleton("code")).getRequestParameters(), - sessionStatus, principal); + getAuthorizationRequest("foo", "http://anywhere.com/", null, "read", Collections.singleton("code")) + .getRequestParameters(), sessionStatus, principal); // Should go to approval page (SECOAUTH-191) assertFalse(result.getView() instanceof RedirectView); } @Test public void testRedirectUriOptionalForAuthorization() throws Exception { - ModelAndView result = endpoint.authorize(model, getAuthorizationRequest("foo", null, null, "read", Collections.singleton("code")) - .getRequestParameters(), sessionStatus, principal); + ModelAndView result = endpoint.authorize(model, + getAuthorizationRequest("foo", null, null, "read", Collections.singleton("code")) + .getRequestParameters(), sessionStatus, principal); // RedirectUri parameter should be null (SECOAUTH-333), however the resolvedRedirectUri not AuthorizationRequest authorizationRequest = (AuthorizationRequest) result.getModelMap().get( "authorizationRequest"); From 41456683068451dd88b557f98a912b38d8fb8998 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 10 Jun 2014 12:55:13 +0100 Subject: [PATCH 269/831] Add interceptors to AuthorizationServerEndpointsConfigurer Fixes gh-209 --- .../AuthorizationServerEndpointsConfigurer.java | 15 +++++++++++++++ .../token/DefaultAuthenticationKeyGenerator.java | 2 +- .../AuthorizationServerConfigurationTests.java | 10 +++++++--- 3 files changed, 23 insertions(+), 4 deletions(-) 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 a0ca75d32..db6988c99 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 @@ -53,6 +53,8 @@ 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; +import org.springframework.web.context.request.WebRequestInterceptor; +import org.springframework.web.servlet.HandlerInterceptor; /** * Configure the properties and enhanced functionality of the Authorization Server endpoints. @@ -97,6 +99,8 @@ public final class AuthorizationServerEndpointsConfigurer { private boolean approvalStoreDisabled; + private List interceptors = new ArrayList(); + public AuthorizationServerTokenServices getTokenServices() { return tokenServices; } @@ -176,6 +180,16 @@ public AuthorizationServerEndpointsConfigurer pathMapping(String defaultPath, St return this; } + public AuthorizationServerEndpointsConfigurer addInterceptor(HandlerInterceptor interceptor) { + this.interceptors.add(interceptor); + return this; + } + + public AuthorizationServerEndpointsConfigurer addInterceptor(WebRequestInterceptor interceptor) { + this.interceptors.add(interceptor); + return this; + } + public AuthorizationServerEndpointsConfigurer authenticationManager(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; return this; @@ -387,6 +401,7 @@ private FrameworkEndpointHandlerMapping frameworkEndpointHandlerMapping() { if (frameworkEndpointHandlerMapping == null) { frameworkEndpointHandlerMapping = new FrameworkEndpointHandlerMapping(); frameworkEndpointHandlerMapping.setMappings(patternMap); + frameworkEndpointHandlerMapping.setInterceptors(interceptors .toArray()); } return frameworkEndpointHandlerMapping; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAuthenticationKeyGenerator.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAuthenticationKeyGenerator.java index 74a7278b9..af26e51bb 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAuthenticationKeyGenerator.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAuthenticationKeyGenerator.java @@ -24,7 +24,7 @@ import org.springframework.security.oauth2.provider.OAuth2Request; /** - * Basic key generator taking into account the client id, scope, reource ids and username (principal name) if they + * Basic key generator taking into account the client id, scope, resource ids and username (principal name) if they * exist. * * @author Dave Syer diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java index f62c54c80..346fd4935 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java @@ -61,6 +61,7 @@ import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; /** * @author Dave Syer @@ -133,7 +134,7 @@ protected static class AuthorizationServerUnconfigured { protected static class AuthorizationServerVanilla extends AuthorizationServerConfigurerAdapter implements Runnable { @Autowired private AuthorizationEndpoint endpoint; - + @Autowired private ClientDetailsService clientDetailsService; @@ -160,7 +161,8 @@ public void run() { Map request = handler.getUserApprovalRequest(authorizationRequest, new UsernamePasswordAuthenticationToken("user", "password")); assertTrue(request.containsKey("scopes")); - assertTrue(clientDetailsService.loadClientByClientId("my-trusted-client").getAdditionalInformation().containsKey("foo")); + assertTrue(clientDetailsService.loadClientByClientId("my-trusted-client").getAdditionalInformation() + .containsKey("foo")); } } @@ -251,7 +253,9 @@ public TokenApprovalStore approvalStore() { @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { - endpoints.tokenStore(tokenStore).approvalStore(approvalStore()).userApprovalHandler(userApprovalHandler()); + endpoints.tokenStore(tokenStore).approvalStore(approvalStore()).userApprovalHandler(userApprovalHandler()) + .addInterceptor(new HandlerInterceptorAdapter() { + }); } @Override From 3249391c7c51ff93d48032f10baccba8163b4611 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 11 Jun 2014 09:04:07 +0100 Subject: [PATCH 270/831] 2.0.2.RELEASE updates --- .gitignore | 1 + pom.xml | 3 +- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- tests/annotation/README.md | 89 ++++ tests/annotation/approval/README.md | 18 + tests/annotation/approval/pom.xml | 50 ++ .../src/main/java/demo/Application.java | 91 ++++ .../src/main/resources/application.yml | 8 + .../src/test/java/demo/ApplicationTests.java | 20 + .../demo/AuthorizationCodeProviderTests.java | 33 ++ .../demo/ClientCredentialsProviderTests.java | 14 + .../test/java/demo/ImplicitProviderTests.java | 13 + .../java/demo/ProtectedResourceTests.java | 27 ++ .../java/demo/RefreshTokenSupportTests.java | 13 + .../ResourceOwnerPasswordProviderTests.java | 13 + .../src/test/resources/test.properties | 1 + tests/annotation/client/README.md | 2 + tests/annotation/client/pom.xml | 46 ++ .../main/java/client/ClientApplication.java | 71 +++ .../client/src/main/resources/application.yml | 10 + .../test/java/client/ApplicationTests.java | 20 + .../client/ClientServerInteractionTests.java | 49 ++ .../test/java/client/CombinedApplication.java | 93 ++++ .../resources/application-combined.properties | 5 + .../client/src/test/resources/test.properties | 1 + tests/annotation/common/README.md | 4 + tests/annotation/common/pom.xml | 94 ++++ ...bstractAuthorizationCodeProviderTests.java | 430 ++++++++++++++++++ ...bstractClientCredentialsProviderTests.java | 121 +++++ .../common/AbstractImplicitProviderTests.java | 52 +++ .../common/AbstractIntegrationTests.java | 162 +++++++ .../AbstractProtectedResourceTests.java | 51 +++ .../AbstractRefreshTokenSupportTests.java | 108 +++++ ...actResourceOwnerPasswordProviderTests.java | 267 +++++++++++ .../java/sparklr/common/HttpTestUtils.java | 306 +++++++++++++ .../main/java/sparklr/common/PortHolder.java | 24 + tests/annotation/form/README.md | 7 + tests/annotation/form/pom.xml | 50 ++ .../form/src/main/java/demo/Application.java | 80 ++++ .../form/src/main/resources/application.yml | 8 + .../form/src/test/java/demo/AdHocTests.java | 40 ++ .../src/test/java/demo/ApplicationTests.java | 20 + .../demo/AuthorizationCodeProviderTests.java | 25 + .../demo/ClientCredentialsProviderTests.java | 87 ++++ .../test/java/demo/ImplicitProviderTests.java | 13 + .../java/demo/ProtectedResourceTests.java | 27 ++ .../java/demo/RefreshTokenSupportTests.java | 13 + .../ResourceOwnerPasswordProviderTests.java | 13 + .../form/src/test/resources/test.properties | 1 + tests/annotation/jdbc/README.md | 21 + tests/annotation/jdbc/pom.xml | 58 +++ .../jdbc/src/main/java/demo/Application.java | 141 ++++++ .../src/main/java/demo/ClientApplication.java | 89 ++++ .../jdbc/src/main/resources/application.yml | 15 + .../jdbc/src/main/resources/schema.sql | 53 +++ .../jdbc/src/test/java/demo/AdHocTests.java | 39 ++ .../src/test/java/demo/ApplicationTests.java | 29 ++ .../demo/AuthorizationCodeProviderTests.java | 33 ++ .../demo/ClientCredentialsProviderTests.java | 14 + .../test/java/demo/ImplicitProviderTests.java | 13 + .../java/demo/ProtectedResourceTests.java | 27 ++ .../java/demo/RefreshTokenSupportTests.java | 13 + .../ResourceOwnerPasswordProviderTests.java | 13 + .../jdbc/src/test/resources/test.properties | 2 + tests/annotation/jwt/README.md | 18 + tests/annotation/jwt/pom.xml | 54 +++ .../jwt/src/main/java/demo/Application.java | 85 ++++ .../jwt/src/main/resources/application.yml | 8 + .../jwt/src/main/resources/logback.xml | 8 + .../src/test/java/demo/ApplicationTests.java | 29 ++ .../demo/AuthorizationCodeProviderTests.java | 25 + .../demo/ClientCredentialsProviderTests.java | 60 +++ .../test/java/demo/ImplicitProviderTests.java | 13 + .../java/demo/ProtectedResourceTests.java | 27 ++ .../java/demo/RefreshTokenSupportTests.java | 23 + .../ResourceOwnerPasswordProviderTests.java | 48 ++ .../jwt/src/test/resources/test.properties | 1 + tests/annotation/mappings/README.md | 16 + tests/annotation/mappings/pom.xml | 50 ++ .../src/main/java/demo/Application.java | 128 ++++++ .../src/main/resources/application.yml | 15 + .../src/test/java/demo/ApplicationTests.java | 20 + .../demo/AuthorizationCodeProviderTests.java | 51 +++ .../demo/ClientCredentialsProviderTests.java | 59 +++ .../test/java/demo/ImplicitProviderTests.java | 13 + .../java/demo/ProtectedResourceTests.java | 41 ++ .../java/demo/RefreshTokenSupportTests.java | 13 + .../ResourceOwnerPasswordProviderTests.java | 13 + .../src/test/resources/test.properties | 1 + tests/annotation/multi/README.md | 9 + tests/annotation/multi/pom.xml | 50 ++ .../multi/src/main/java/demo/Application.java | 131 ++++++ .../multi/src/main/resources/application.yml | 8 + .../src/test/java/demo/ApplicationTests.java | 20 + .../demo/AuthorizationCodeProviderTests.java | 25 + .../demo/ClientCredentialsProviderTests.java | 14 + .../test/java/demo/ImplicitProviderTests.java | 13 + .../java/demo/ProtectedResourceTests.java | 49 ++ .../java/demo/RefreshTokenSupportTests.java | 13 + .../ResourceOwnerPasswordProviderTests.java | 13 + .../multi/src/test/resources/test.properties | 1 + tests/annotation/pom.xml | 132 ++++++ tests/annotation/resource/README.md | 18 + tests/annotation/resource/pom.xml | 54 +++ .../src/main/java/demo/Application.java | 38 ++ .../src/main/resources/application.yml | 8 + .../resource/src/main/resources/logback.xml | 7 + .../src/test/java/demo/ApplicationTests.java | 20 + .../java/demo/ProtectedResourceTests.java | 27 ++ .../src/test/resources/test.properties | 1 + tests/annotation/vanilla/README.md | 18 + tests/annotation/vanilla/pom.xml | 50 ++ .../src/main/java/demo/Application.java | 74 +++ .../src/main/resources/application.yml | 8 + .../src/test/java/demo/ApplicationTests.java | 20 + .../demo/AuthorizationCodeProviderTests.java | 25 + .../demo/ClientCredentialsProviderTests.java | 14 + .../test/java/demo/ImplicitProviderTests.java | 76 ++++ .../java/demo/ProtectedResourceTests.java | 27 ++ .../java/demo/RefreshTokenSupportTests.java | 13 + .../ResourceOwnerPasswordProviderTests.java | 13 + .../src/test/resources/test.properties | 1 + tests/pom.xml | 44 ++ tests/xml/README.md | 64 +++ tests/xml/approval/README.md | 18 + tests/xml/approval/pom.xml | 50 ++ .../src/main/java/demo/Application.java | 191 ++++++++ .../src/main/resources/application.xml | 34 ++ .../src/main/resources/application.yml | 8 + .../src/test/java/demo/ApplicationTests.java | 20 + .../demo/AuthorizationCodeProviderTests.java | 33 ++ .../demo/ClientCredentialsProviderTests.java | 14 + .../test/java/demo/ImplicitProviderTests.java | 13 + .../java/demo/ProtectedResourceTests.java | 27 ++ .../java/demo/RefreshTokenSupportTests.java | 13 + .../ResourceOwnerPasswordProviderTests.java | 13 + .../src/test/resources/test.properties | 1 + tests/xml/client/README.md | 2 + tests/xml/client/pom.xml | 46 ++ .../main/java/client/ClientApplication.java | 41 ++ .../client/src/main/resources/application.xml | 13 + .../client/src/main/resources/application.yml | 10 + .../test/java/client/ApplicationTests.java | 20 + .../client/ClientServerInteractionTests.java | 49 ++ .../test/java/client/CombinedApplication.java | 93 ++++ .../resources/application-combined.properties | 5 + .../client/src/test/resources/test.properties | 1 + tests/xml/common/README.md | 4 + tests/xml/common/pom.xml | 94 ++++ ...bstractAuthorizationCodeProviderTests.java | 430 ++++++++++++++++++ ...bstractClientCredentialsProviderTests.java | 111 +++++ .../common/AbstractImplicitProviderTests.java | 52 +++ .../common/AbstractIntegrationTests.java | 140 ++++++ .../AbstractProtectedResourceTests.java | 51 +++ .../AbstractRefreshTokenSupportTests.java | 108 +++++ ...actResourceOwnerPasswordProviderTests.java | 254 +++++++++++ .../java/sparklr/common/HttpTestUtils.java | 306 +++++++++++++ .../main/java/sparklr/common/PortHolder.java | 24 + tests/xml/form/README.md | 7 + tests/xml/form/pom.xml | 50 ++ .../form/src/main/java/demo/Application.java | 166 +++++++ .../form/src/main/resources/application.xml | 34 ++ .../form/src/main/resources/application.yml | 8 + .../src/test/java/demo/ApplicationTests.java | 20 + .../demo/AuthorizationCodeProviderTests.java | 25 + .../demo/ClientCredentialsProviderTests.java | 87 ++++ .../test/java/demo/ImplicitProviderTests.java | 13 + .../java/demo/ProtectedResourceTests.java | 27 ++ .../java/demo/RefreshTokenSupportTests.java | 13 + .../ResourceOwnerPasswordProviderTests.java | 13 + .../form/src/test/resources/test.properties | 1 + tests/xml/jdbc/README.md | 21 + tests/xml/jdbc/pom.xml | 58 +++ .../jdbc/src/main/java/demo/Application.java | 201 ++++++++ .../src/main/java/demo/ClientApplication.java | 89 ++++ .../jdbc/src/main/resources/application.xml | 18 + .../jdbc/src/main/resources/application.yml | 15 + tests/xml/jdbc/src/main/resources/data.sql | 8 + tests/xml/jdbc/src/main/resources/logback.xml | 8 + tests/xml/jdbc/src/main/resources/schema.sql | 53 +++ .../jdbc/src/test/java/demo/AdHocTests.java | 39 ++ .../src/test/java/demo/ApplicationTests.java | 29 ++ .../demo/AuthorizationCodeProviderTests.java | 33 ++ .../demo/ClientCredentialsProviderTests.java | 14 + .../test/java/demo/ImplicitProviderTests.java | 13 + .../java/demo/ProtectedResourceTests.java | 27 ++ .../java/demo/RefreshTokenSupportTests.java | 13 + .../ResourceOwnerPasswordProviderTests.java | 13 + .../jdbc/src/test/resources/test.properties | 2 + tests/xml/jwt/README.md | 18 + tests/xml/jwt/pom.xml | 54 +++ .../jwt/src/main/java/demo/Application.java | 171 +++++++ .../jwt/src/main/resources/application.xml | 34 ++ .../jwt/src/main/resources/application.yml | 8 + .../src/test/java/demo/ApplicationTests.java | 29 ++ .../demo/AuthorizationCodeProviderTests.java | 25 + .../demo/ClientCredentialsProviderTests.java | 14 + .../test/java/demo/ImplicitProviderTests.java | 13 + .../java/demo/ProtectedResourceTests.java | 27 ++ .../java/demo/RefreshTokenSupportTests.java | 23 + .../ResourceOwnerPasswordProviderTests.java | 13 + .../jwt/src/test/resources/test.properties | 1 + tests/xml/mappings/README.md | 16 + tests/xml/mappings/pom.xml | 50 ++ .../src/main/java/demo/Application.java | 163 +++++++ .../src/main/resources/application.xml | 37 ++ .../src/main/resources/application.yml | 14 + .../src/test/java/demo/ApplicationTests.java | 20 + .../demo/AuthorizationCodeProviderTests.java | 51 +++ .../demo/ClientCredentialsProviderTests.java | 14 + .../test/java/demo/ImplicitProviderTests.java | 13 + .../java/demo/ProtectedResourceTests.java | 41 ++ .../java/demo/RefreshTokenSupportTests.java | 13 + .../ResourceOwnerPasswordProviderTests.java | 13 + .../src/test/resources/test.properties | 1 + tests/xml/pom.xml | 130 ++++++ tests/xml/vanilla/README.md | 18 + tests/xml/vanilla/pom.xml | 50 ++ .../src/main/java/demo/Application.java | 162 +++++++ .../src/main/resources/application.xml | 34 ++ .../src/main/resources/application.yml | 8 + .../src/test/java/demo/ApplicationTests.java | 20 + .../demo/AuthorizationCodeProviderTests.java | 25 + .../demo/ClientCredentialsProviderTests.java | 14 + .../test/java/demo/ImplicitProviderTests.java | 13 + .../java/demo/ProtectedResourceTests.java | 27 ++ .../java/demo/RefreshTokenSupportTests.java | 13 + .../ResourceOwnerPasswordProviderTests.java | 13 + .../src/test/resources/test.properties | 1 + 235 files changed, 9988 insertions(+), 8 deletions(-) create mode 100644 tests/annotation/README.md create mode 100644 tests/annotation/approval/README.md create mode 100644 tests/annotation/approval/pom.xml create mode 100644 tests/annotation/approval/src/main/java/demo/Application.java create mode 100644 tests/annotation/approval/src/main/resources/application.yml create mode 100644 tests/annotation/approval/src/test/java/demo/ApplicationTests.java create mode 100755 tests/annotation/approval/src/test/java/demo/AuthorizationCodeProviderTests.java create mode 100644 tests/annotation/approval/src/test/java/demo/ClientCredentialsProviderTests.java create mode 100644 tests/annotation/approval/src/test/java/demo/ImplicitProviderTests.java create mode 100644 tests/annotation/approval/src/test/java/demo/ProtectedResourceTests.java create mode 100644 tests/annotation/approval/src/test/java/demo/RefreshTokenSupportTests.java create mode 100644 tests/annotation/approval/src/test/java/demo/ResourceOwnerPasswordProviderTests.java create mode 100644 tests/annotation/approval/src/test/resources/test.properties create mode 100644 tests/annotation/client/README.md create mode 100644 tests/annotation/client/pom.xml create mode 100644 tests/annotation/client/src/main/java/client/ClientApplication.java create mode 100644 tests/annotation/client/src/main/resources/application.yml create mode 100644 tests/annotation/client/src/test/java/client/ApplicationTests.java create mode 100644 tests/annotation/client/src/test/java/client/ClientServerInteractionTests.java create mode 100644 tests/annotation/client/src/test/java/client/CombinedApplication.java create mode 100644 tests/annotation/client/src/test/resources/application-combined.properties create mode 100644 tests/annotation/client/src/test/resources/test.properties create mode 100644 tests/annotation/common/README.md create mode 100644 tests/annotation/common/pom.xml create mode 100755 tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java create mode 100644 tests/annotation/common/src/main/java/sparklr/common/AbstractClientCredentialsProviderTests.java create mode 100644 tests/annotation/common/src/main/java/sparklr/common/AbstractImplicitProviderTests.java create mode 100644 tests/annotation/common/src/main/java/sparklr/common/AbstractIntegrationTests.java create mode 100644 tests/annotation/common/src/main/java/sparklr/common/AbstractProtectedResourceTests.java create mode 100644 tests/annotation/common/src/main/java/sparklr/common/AbstractRefreshTokenSupportTests.java create mode 100644 tests/annotation/common/src/main/java/sparklr/common/AbstractResourceOwnerPasswordProviderTests.java create mode 100644 tests/annotation/common/src/main/java/sparklr/common/HttpTestUtils.java create mode 100644 tests/annotation/common/src/main/java/sparklr/common/PortHolder.java create mode 100644 tests/annotation/form/README.md create mode 100644 tests/annotation/form/pom.xml create mode 100644 tests/annotation/form/src/main/java/demo/Application.java create mode 100644 tests/annotation/form/src/main/resources/application.yml create mode 100644 tests/annotation/form/src/test/java/demo/AdHocTests.java create mode 100644 tests/annotation/form/src/test/java/demo/ApplicationTests.java create mode 100755 tests/annotation/form/src/test/java/demo/AuthorizationCodeProviderTests.java create mode 100644 tests/annotation/form/src/test/java/demo/ClientCredentialsProviderTests.java create mode 100644 tests/annotation/form/src/test/java/demo/ImplicitProviderTests.java create mode 100644 tests/annotation/form/src/test/java/demo/ProtectedResourceTests.java create mode 100644 tests/annotation/form/src/test/java/demo/RefreshTokenSupportTests.java create mode 100644 tests/annotation/form/src/test/java/demo/ResourceOwnerPasswordProviderTests.java create mode 100644 tests/annotation/form/src/test/resources/test.properties create mode 100644 tests/annotation/jdbc/README.md create mode 100644 tests/annotation/jdbc/pom.xml create mode 100644 tests/annotation/jdbc/src/main/java/demo/Application.java create mode 100644 tests/annotation/jdbc/src/main/java/demo/ClientApplication.java create mode 100644 tests/annotation/jdbc/src/main/resources/application.yml create mode 100644 tests/annotation/jdbc/src/main/resources/schema.sql create mode 100644 tests/annotation/jdbc/src/test/java/demo/AdHocTests.java create mode 100644 tests/annotation/jdbc/src/test/java/demo/ApplicationTests.java create mode 100755 tests/annotation/jdbc/src/test/java/demo/AuthorizationCodeProviderTests.java create mode 100644 tests/annotation/jdbc/src/test/java/demo/ClientCredentialsProviderTests.java create mode 100644 tests/annotation/jdbc/src/test/java/demo/ImplicitProviderTests.java create mode 100644 tests/annotation/jdbc/src/test/java/demo/ProtectedResourceTests.java create mode 100644 tests/annotation/jdbc/src/test/java/demo/RefreshTokenSupportTests.java create mode 100644 tests/annotation/jdbc/src/test/java/demo/ResourceOwnerPasswordProviderTests.java create mode 100644 tests/annotation/jdbc/src/test/resources/test.properties create mode 100644 tests/annotation/jwt/README.md create mode 100644 tests/annotation/jwt/pom.xml create mode 100644 tests/annotation/jwt/src/main/java/demo/Application.java create mode 100644 tests/annotation/jwt/src/main/resources/application.yml create mode 100644 tests/annotation/jwt/src/main/resources/logback.xml create mode 100644 tests/annotation/jwt/src/test/java/demo/ApplicationTests.java create mode 100755 tests/annotation/jwt/src/test/java/demo/AuthorizationCodeProviderTests.java create mode 100644 tests/annotation/jwt/src/test/java/demo/ClientCredentialsProviderTests.java create mode 100644 tests/annotation/jwt/src/test/java/demo/ImplicitProviderTests.java create mode 100644 tests/annotation/jwt/src/test/java/demo/ProtectedResourceTests.java create mode 100644 tests/annotation/jwt/src/test/java/demo/RefreshTokenSupportTests.java create mode 100644 tests/annotation/jwt/src/test/java/demo/ResourceOwnerPasswordProviderTests.java create mode 100644 tests/annotation/jwt/src/test/resources/test.properties create mode 100644 tests/annotation/mappings/README.md create mode 100644 tests/annotation/mappings/pom.xml create mode 100644 tests/annotation/mappings/src/main/java/demo/Application.java create mode 100644 tests/annotation/mappings/src/main/resources/application.yml create mode 100644 tests/annotation/mappings/src/test/java/demo/ApplicationTests.java create mode 100755 tests/annotation/mappings/src/test/java/demo/AuthorizationCodeProviderTests.java create mode 100644 tests/annotation/mappings/src/test/java/demo/ClientCredentialsProviderTests.java create mode 100644 tests/annotation/mappings/src/test/java/demo/ImplicitProviderTests.java create mode 100644 tests/annotation/mappings/src/test/java/demo/ProtectedResourceTests.java create mode 100644 tests/annotation/mappings/src/test/java/demo/RefreshTokenSupportTests.java create mode 100644 tests/annotation/mappings/src/test/java/demo/ResourceOwnerPasswordProviderTests.java create mode 100644 tests/annotation/mappings/src/test/resources/test.properties create mode 100644 tests/annotation/multi/README.md create mode 100644 tests/annotation/multi/pom.xml create mode 100644 tests/annotation/multi/src/main/java/demo/Application.java create mode 100644 tests/annotation/multi/src/main/resources/application.yml create mode 100644 tests/annotation/multi/src/test/java/demo/ApplicationTests.java create mode 100755 tests/annotation/multi/src/test/java/demo/AuthorizationCodeProviderTests.java create mode 100644 tests/annotation/multi/src/test/java/demo/ClientCredentialsProviderTests.java create mode 100644 tests/annotation/multi/src/test/java/demo/ImplicitProviderTests.java create mode 100644 tests/annotation/multi/src/test/java/demo/ProtectedResourceTests.java create mode 100644 tests/annotation/multi/src/test/java/demo/RefreshTokenSupportTests.java create mode 100644 tests/annotation/multi/src/test/java/demo/ResourceOwnerPasswordProviderTests.java create mode 100644 tests/annotation/multi/src/test/resources/test.properties create mode 100644 tests/annotation/pom.xml create mode 100644 tests/annotation/resource/README.md create mode 100644 tests/annotation/resource/pom.xml create mode 100644 tests/annotation/resource/src/main/java/demo/Application.java create mode 100644 tests/annotation/resource/src/main/resources/application.yml create mode 100644 tests/annotation/resource/src/main/resources/logback.xml create mode 100644 tests/annotation/resource/src/test/java/demo/ApplicationTests.java create mode 100644 tests/annotation/resource/src/test/java/demo/ProtectedResourceTests.java create mode 100644 tests/annotation/resource/src/test/resources/test.properties create mode 100644 tests/annotation/vanilla/README.md create mode 100644 tests/annotation/vanilla/pom.xml create mode 100644 tests/annotation/vanilla/src/main/java/demo/Application.java create mode 100644 tests/annotation/vanilla/src/main/resources/application.yml create mode 100644 tests/annotation/vanilla/src/test/java/demo/ApplicationTests.java create mode 100755 tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java create mode 100644 tests/annotation/vanilla/src/test/java/demo/ClientCredentialsProviderTests.java create mode 100644 tests/annotation/vanilla/src/test/java/demo/ImplicitProviderTests.java create mode 100644 tests/annotation/vanilla/src/test/java/demo/ProtectedResourceTests.java create mode 100644 tests/annotation/vanilla/src/test/java/demo/RefreshTokenSupportTests.java create mode 100644 tests/annotation/vanilla/src/test/java/demo/ResourceOwnerPasswordProviderTests.java create mode 100644 tests/annotation/vanilla/src/test/resources/test.properties create mode 100644 tests/pom.xml create mode 100644 tests/xml/README.md create mode 100644 tests/xml/approval/README.md create mode 100644 tests/xml/approval/pom.xml create mode 100644 tests/xml/approval/src/main/java/demo/Application.java create mode 100644 tests/xml/approval/src/main/resources/application.xml create mode 100644 tests/xml/approval/src/main/resources/application.yml create mode 100644 tests/xml/approval/src/test/java/demo/ApplicationTests.java create mode 100755 tests/xml/approval/src/test/java/demo/AuthorizationCodeProviderTests.java create mode 100644 tests/xml/approval/src/test/java/demo/ClientCredentialsProviderTests.java create mode 100644 tests/xml/approval/src/test/java/demo/ImplicitProviderTests.java create mode 100644 tests/xml/approval/src/test/java/demo/ProtectedResourceTests.java create mode 100644 tests/xml/approval/src/test/java/demo/RefreshTokenSupportTests.java create mode 100644 tests/xml/approval/src/test/java/demo/ResourceOwnerPasswordProviderTests.java create mode 100644 tests/xml/approval/src/test/resources/test.properties create mode 100644 tests/xml/client/README.md create mode 100644 tests/xml/client/pom.xml create mode 100644 tests/xml/client/src/main/java/client/ClientApplication.java create mode 100644 tests/xml/client/src/main/resources/application.xml create mode 100644 tests/xml/client/src/main/resources/application.yml create mode 100644 tests/xml/client/src/test/java/client/ApplicationTests.java create mode 100644 tests/xml/client/src/test/java/client/ClientServerInteractionTests.java create mode 100644 tests/xml/client/src/test/java/client/CombinedApplication.java create mode 100644 tests/xml/client/src/test/resources/application-combined.properties create mode 100644 tests/xml/client/src/test/resources/test.properties create mode 100644 tests/xml/common/README.md create mode 100644 tests/xml/common/pom.xml create mode 100755 tests/xml/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java create mode 100644 tests/xml/common/src/main/java/sparklr/common/AbstractClientCredentialsProviderTests.java create mode 100644 tests/xml/common/src/main/java/sparklr/common/AbstractImplicitProviderTests.java create mode 100644 tests/xml/common/src/main/java/sparklr/common/AbstractIntegrationTests.java create mode 100644 tests/xml/common/src/main/java/sparklr/common/AbstractProtectedResourceTests.java create mode 100644 tests/xml/common/src/main/java/sparklr/common/AbstractRefreshTokenSupportTests.java create mode 100644 tests/xml/common/src/main/java/sparklr/common/AbstractResourceOwnerPasswordProviderTests.java create mode 100644 tests/xml/common/src/main/java/sparklr/common/HttpTestUtils.java create mode 100644 tests/xml/common/src/main/java/sparklr/common/PortHolder.java create mode 100644 tests/xml/form/README.md create mode 100644 tests/xml/form/pom.xml create mode 100644 tests/xml/form/src/main/java/demo/Application.java create mode 100644 tests/xml/form/src/main/resources/application.xml create mode 100644 tests/xml/form/src/main/resources/application.yml create mode 100644 tests/xml/form/src/test/java/demo/ApplicationTests.java create mode 100755 tests/xml/form/src/test/java/demo/AuthorizationCodeProviderTests.java create mode 100644 tests/xml/form/src/test/java/demo/ClientCredentialsProviderTests.java create mode 100644 tests/xml/form/src/test/java/demo/ImplicitProviderTests.java create mode 100644 tests/xml/form/src/test/java/demo/ProtectedResourceTests.java create mode 100644 tests/xml/form/src/test/java/demo/RefreshTokenSupportTests.java create mode 100644 tests/xml/form/src/test/java/demo/ResourceOwnerPasswordProviderTests.java create mode 100644 tests/xml/form/src/test/resources/test.properties create mode 100644 tests/xml/jdbc/README.md create mode 100644 tests/xml/jdbc/pom.xml create mode 100644 tests/xml/jdbc/src/main/java/demo/Application.java create mode 100644 tests/xml/jdbc/src/main/java/demo/ClientApplication.java create mode 100644 tests/xml/jdbc/src/main/resources/application.xml create mode 100644 tests/xml/jdbc/src/main/resources/application.yml create mode 100644 tests/xml/jdbc/src/main/resources/data.sql create mode 100644 tests/xml/jdbc/src/main/resources/logback.xml create mode 100644 tests/xml/jdbc/src/main/resources/schema.sql create mode 100644 tests/xml/jdbc/src/test/java/demo/AdHocTests.java create mode 100644 tests/xml/jdbc/src/test/java/demo/ApplicationTests.java create mode 100755 tests/xml/jdbc/src/test/java/demo/AuthorizationCodeProviderTests.java create mode 100644 tests/xml/jdbc/src/test/java/demo/ClientCredentialsProviderTests.java create mode 100644 tests/xml/jdbc/src/test/java/demo/ImplicitProviderTests.java create mode 100644 tests/xml/jdbc/src/test/java/demo/ProtectedResourceTests.java create mode 100644 tests/xml/jdbc/src/test/java/demo/RefreshTokenSupportTests.java create mode 100644 tests/xml/jdbc/src/test/java/demo/ResourceOwnerPasswordProviderTests.java create mode 100644 tests/xml/jdbc/src/test/resources/test.properties create mode 100644 tests/xml/jwt/README.md create mode 100644 tests/xml/jwt/pom.xml create mode 100644 tests/xml/jwt/src/main/java/demo/Application.java create mode 100644 tests/xml/jwt/src/main/resources/application.xml create mode 100644 tests/xml/jwt/src/main/resources/application.yml create mode 100644 tests/xml/jwt/src/test/java/demo/ApplicationTests.java create mode 100755 tests/xml/jwt/src/test/java/demo/AuthorizationCodeProviderTests.java create mode 100644 tests/xml/jwt/src/test/java/demo/ClientCredentialsProviderTests.java create mode 100644 tests/xml/jwt/src/test/java/demo/ImplicitProviderTests.java create mode 100644 tests/xml/jwt/src/test/java/demo/ProtectedResourceTests.java create mode 100644 tests/xml/jwt/src/test/java/demo/RefreshTokenSupportTests.java create mode 100644 tests/xml/jwt/src/test/java/demo/ResourceOwnerPasswordProviderTests.java create mode 100644 tests/xml/jwt/src/test/resources/test.properties create mode 100644 tests/xml/mappings/README.md create mode 100644 tests/xml/mappings/pom.xml create mode 100644 tests/xml/mappings/src/main/java/demo/Application.java create mode 100644 tests/xml/mappings/src/main/resources/application.xml create mode 100644 tests/xml/mappings/src/main/resources/application.yml create mode 100644 tests/xml/mappings/src/test/java/demo/ApplicationTests.java create mode 100755 tests/xml/mappings/src/test/java/demo/AuthorizationCodeProviderTests.java create mode 100644 tests/xml/mappings/src/test/java/demo/ClientCredentialsProviderTests.java create mode 100644 tests/xml/mappings/src/test/java/demo/ImplicitProviderTests.java create mode 100644 tests/xml/mappings/src/test/java/demo/ProtectedResourceTests.java create mode 100644 tests/xml/mappings/src/test/java/demo/RefreshTokenSupportTests.java create mode 100644 tests/xml/mappings/src/test/java/demo/ResourceOwnerPasswordProviderTests.java create mode 100644 tests/xml/mappings/src/test/resources/test.properties create mode 100644 tests/xml/pom.xml create mode 100644 tests/xml/vanilla/README.md create mode 100644 tests/xml/vanilla/pom.xml create mode 100644 tests/xml/vanilla/src/main/java/demo/Application.java create mode 100644 tests/xml/vanilla/src/main/resources/application.xml create mode 100644 tests/xml/vanilla/src/main/resources/application.yml create mode 100644 tests/xml/vanilla/src/test/java/demo/ApplicationTests.java create mode 100755 tests/xml/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java create mode 100644 tests/xml/vanilla/src/test/java/demo/ClientCredentialsProviderTests.java create mode 100644 tests/xml/vanilla/src/test/java/demo/ImplicitProviderTests.java create mode 100644 tests/xml/vanilla/src/test/java/demo/ProtectedResourceTests.java create mode 100644 tests/xml/vanilla/src/test/java/demo/RefreshTokenSupportTests.java create mode 100644 tests/xml/vanilla/src/test/java/demo/ResourceOwnerPasswordProviderTests.java create mode 100644 tests/xml/vanilla/src/test/resources/test.properties diff --git a/.gitignore b/.gitignore index d9d370573..f68c4b90b 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ _site/ samples/*/*/src/main/webapp/META-INF/ build/ target/ +bin/ .classpath .project .DS_Store diff --git a/pom.xml b/pom.xml index da2bdf4db..e0d6095d3 100644 --- a/pom.xml +++ b/pom.xml @@ -5,12 +5,13 @@ OAuth for Spring Security Parent Project for OAuth Support for Spring Security pom - 2.0.2.BUILD-SNAPSHOT + 2.0.2.RELEASE http://static.springframework.org/spring-security/oauth spring-security-oauth spring-security-oauth2 + tests samples diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index 3fe41b53e..6ac6f16fe 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.2.BUILD-SNAPSHOT + 2.0.2.RELEASE ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index 7ba36a18a..5208ef565 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.2.BUILD-SNAPSHOT + 2.0.2.RELEASE ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 29b47da6e..55c42c466 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.2.BUILD-SNAPSHOT + 2.0.2.RELEASE ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 413f12b37..270ea6a02 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.2.BUILD-SNAPSHOT + 2.0.2.RELEASE ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index bd047bc78..279338864 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.2.BUILD-SNAPSHOT + 2.0.2.RELEASE spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index c2798c328..472897cae 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.2.BUILD-SNAPSHOT + 2.0.2.RELEASE spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 79d44396e..8ca0e0188 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.2.BUILD-SNAPSHOT + 2.0.2.RELEASE spring-security-oauth2 diff --git a/tests/annotation/README.md b/tests/annotation/README.md new file mode 100644 index 000000000..4076d18e2 --- /dev/null +++ b/tests/annotation/README.md @@ -0,0 +1,89 @@ +This project contains a selection of minimal apps that are functional +OAuth2 Authorization Servers (token issuer) and Resource Servers +(protected API). (You could split the two roles across two +applications if you preferred.) It uses +[Spring Boot](https://github.com/spring-projects/spring-boot) to +provide an embedded servlet container and for defaulting a load of +configuration, so you should be up and running very quickly. There are +integration tests proving that it works and also showing you how to +access it with the Spring `RestTemplate` API. + +The apps are in subdirectories: + +* vanilla - a basic, no-frills Authorization Server and Resource Server + +* jwt - uses Json Web Tokens as the token format + +* mappings - changes the default values for the endpoint paths and the + protected resource paths + +* approval - an auth server with granular approvals (per scope) + +* jdbc - uses JDBC stores for everything + +* form - an auth server that accepts form-based client authentication + +* multi - an auth server and multiple Resource Servers in one app + +* resource - a pure Resoure Server (needs to be paired with an auth + server and share a token store) + +* client - a simple client app + +The client is wired to the other servers as long as they run on the +default port of 8080. + + +## Building and Running + +You need Java (1.7 or better) and Maven (3.0.5 or better): + +``` +$ mvn test +... + +``` + +Each app can be launched from the `main()` method in +`Application.java`, either from an IDE, or from the command line using +`mvn spring-boot:run`. Or you can build an executable JAR and run +that: + +``` +$ cd vanilla +$ mvn package +$ java -jar target/*.jar +... + +``` + +Tests run using the full HTTP protocol against an embedded server on a +random port chosen by the operating system (so it should work +everywhere). In contrast, when the app runs from the `main()` method, +it listens on port 8080 by default. + +Here are some curl commands to use to get started: + +``` +$ curl -H "Accept: application/json" my-client-with-secret:secret@localhost:8080/oauth/token -d grant_type=client_credentials +{... "access_token": "b561ff06-4259-466e-92d8-781db1a51901", ...} +$ TOKEN=b561ff06-4259-466e-92d8-781db1a5190 +$ curl -H "Authorization: Bearer $TOKEN" localhost:8080/ +Hello World +``` + +## Running the Client App + +To test in a browser you can run one of the servers (see above) and +the client on a different port (it runs on 8081 by default). + +``` +$ cd client +$ mvn package +$ java -jar target/*.jar +... + +``` + +Go to http://localhost:8081/client and follow the authorization process (the +username and password are `user` and `password`). diff --git a/tests/annotation/approval/README.md b/tests/annotation/approval/README.md new file mode 100644 index 000000000..acb89fbf6 --- /dev/null +++ b/tests/annotation/approval/README.md @@ -0,0 +1,18 @@ +This project shows what you can do with the minimum configuration to +set up an Authorization Server and Resource Server. + +For the Authorization Server you need to `@EnableAuthorizationServer` +and also configure at least one client registration +(`OAuth2ClientDetails`). You can see this is the bulk of +`Application.java`. + +An `AuthenticationManager` is created by Spring Boot (it has a single +user, named "user", with password "password", per +`application.yml`). It is needed in the Authorization Server to +provide authentication for the Resource Owner Password grant type. + +For the Resource Server all that is needed is the +`@EnableResourceServer` annotation. By default it protects all +resources that are not explicitly ignored and not exposed by the +`AuthorizationEndpoint` (if there is an Authorization Server in the +same application). diff --git a/tests/annotation/approval/pom.xml b/tests/annotation/approval/pom.xml new file mode 100644 index 000000000..6b004eedd --- /dev/null +++ b/tests/annotation/approval/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + + spring-oauth2-tests-approval + + spring-oauth2-tests-approval + Demo project + + + org.demo + spring-oauth2-tests-parent + 2.0.2.RELEASE + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.security.oauth + spring-security-oauth2 + + + org.demo + spring-oauth2-tests-common + ${project.version} + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/tests/annotation/approval/src/main/java/demo/Application.java b/tests/annotation/approval/src/main/java/demo/Application.java new file mode 100644 index 000000000..101b9bfb8 --- /dev/null +++ b/tests/annotation/approval/src/main/java/demo/Application.java @@ -0,0 +1,91 @@ +package demo; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +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; +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.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; +import org.springframework.security.oauth2.provider.approval.ApprovalStore; +import org.springframework.security.oauth2.provider.approval.TokenApprovalStore; +import org.springframework.security.oauth2.provider.token.TokenStore; +import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Configuration +@ComponentScan +@EnableAutoConfiguration +@EnableResourceServer +@RestController +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + @RequestMapping("/") + public String home() { + return "Hello World"; + } + + @Configuration + @EnableAuthorizationServer + protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter { + + @Autowired + private AuthenticationManager authenticationManager; + + @Override + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + endpoints.authenticationManager(authenticationManager).tokenStore(tokenStore()); + } + + @Bean + public ApprovalStore approvalStore() throws Exception { + TokenApprovalStore store = new TokenApprovalStore(); + store.setTokenStore(tokenStore()); + return store; + } + + @Bean + public TokenStore tokenStore() { + return new InMemoryTokenStore(); + } + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + // @formatter:off + clients.inMemory() + .withClient("my-trusted-client") + .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit") + .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") + .scopes("read", "write", "trust") + .resourceIds("oauth2-resource") + .accessTokenValiditySeconds(60) + .and() + .withClient("my-client-with-registered-redirect") + .authorizedGrantTypes("authorization_code") + .authorities("ROLE_CLIENT") + .scopes("read", "trust") + .resourceIds("oauth2-resource") + .redirectUris("http://anywhere/?key=value") + .and() + .withClient("my-client-with-secret") + .authorizedGrantTypes("client_credentials", "password") + .authorities("ROLE_CLIENT") + .scopes("read") + .resourceIds("oauth2-resource") + .secret("secret"); + // @formatter:on + } + + } + +} diff --git a/tests/annotation/approval/src/main/resources/application.yml b/tests/annotation/approval/src/main/resources/application.yml new file mode 100644 index 000000000..e52b05d1f --- /dev/null +++ b/tests/annotation/approval/src/main/resources/application.yml @@ -0,0 +1,8 @@ +spring: + application: + name: approval +management: + context_path: /admin +security: + user: + password: password diff --git a/tests/annotation/approval/src/test/java/demo/ApplicationTests.java b/tests/annotation/approval/src/test/java/demo/ApplicationTests.java new file mode 100644 index 000000000..8da63b411 --- /dev/null +++ b/tests/annotation/approval/src/test/java/demo/ApplicationTests.java @@ -0,0 +1,20 @@ +package demo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = Application.class) +@WebAppConfiguration +@ActiveProfiles("test") +public class ApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/tests/annotation/approval/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/approval/src/test/java/demo/AuthorizationCodeProviderTests.java new file mode 100755 index 000000000..3bc5e7dac --- /dev/null +++ b/tests/annotation/approval/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -0,0 +1,33 @@ +/* + * Copyright 2006-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 demo; + +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) { + assertTrue(page.contains("action='http://github.com/oauth/authorize'")); + assertTrue(page.contains(" + *
  • Client doesn't have a token so redirects to auth server /oauth/authorize
  • + *
  • Auth server prompts for authentication (username/password=user/password)
  • + *
  • Auth server prompts for approval of the token grant and redirects to client app
  • + *
  • Client app obtains token in back channel /oauth/token
  • + *
  • Client app obtains content from protected resource /admin/beans (hard-coded content for the demo)
  • + *
  • Client renders content
  • + * + * + * In this demo the client app is very basic (it just re-renders content it got from the resource server), but in a real + * app it can do whatever it likes with the resource content. + * + * @author Dave Syer + * + */ +@Configuration +@RestController +public class CombinedApplication { + + public static void main(String[] args) { + new SpringApplicationBuilder(ClientApplication.class, CombinedApplication.class).profiles("combined").run(args); + } + + @RequestMapping("/admin/beans") + public List> beans() { + return Arrays.asList(Collections. singletonMap("message", "Hello World")); + } + + @RequestMapping("/admin/info") + public Map info() { + return Collections. emptyMap(); + } + + @Configuration + @EnableAuthorizationServer + protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter { + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + clients.inMemory().withClient("my-trusted-client").authorizedGrantTypes("authorization_code") + .authorities("ROLE_CLIENT").scopes("read", "write").resourceIds("oauth2-resource"); + + } + + } + + @Configuration + @EnableResourceServer + protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { + + @Override + public void configure(HttpSecurity http) throws Exception { + http.antMatcher("/admin/beans").authorizeRequests().anyRequest().authenticated(); + } + + } + +} diff --git a/tests/annotation/client/src/test/resources/application-combined.properties b/tests/annotation/client/src/test/resources/application-combined.properties new file mode 100644 index 000000000..c44bd0a7a --- /dev/null +++ b/tests/annotation/client/src/test/resources/application-combined.properties @@ -0,0 +1,5 @@ +server.port: 8080 +server.context_path: +security.basic.enabled: true +security.user.password: password +security.ignored: /,/admin/info \ No newline at end of file diff --git a/tests/annotation/client/src/test/resources/test.properties b/tests/annotation/client/src/test/resources/test.properties new file mode 100644 index 000000000..24466e50d --- /dev/null +++ b/tests/annotation/client/src/test/resources/test.properties @@ -0,0 +1 @@ +server.port: 0 \ No newline at end of file diff --git a/tests/annotation/common/README.md b/tests/annotation/common/README.md new file mode 100644 index 000000000..624c516e2 --- /dev/null +++ b/tests/annotation/common/README.md @@ -0,0 +1,4 @@ +This project contains test utilities for the other projects, for +instance `HttpUtils` for accessing RESTful resources and several +`Abstract*Tests` base classes for testing the basic operations of an +OAuth2 provider. diff --git a/tests/annotation/common/pom.xml b/tests/annotation/common/pom.xml new file mode 100644 index 000000000..f60499b23 --- /dev/null +++ b/tests/annotation/common/pom.xml @@ -0,0 +1,94 @@ + + + 4.0.0 + + spring-oauth2-tests-common + + spring-oauth2-tests-common + Demo OAuth2 Spring Boot Common Utilities + + + org.demo + spring-oauth2-tests-parent + 2.0.2.RELEASE + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-jdbc + true + + + org.springframework.security.oauth + spring-security-oauth2 + + + org.apache.httpcomponents + httpclient + + + org.springframework.boot + spring-boot-starter-test + + + junit + junit + + + org.mockito + mockito-core + + + org.hamcrest + hamcrest-library + + + + + demo.Application + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + + spring-snapshots + Spring Snapshots + http://repo.spring.io/snapshot + + true + + + + spring-milestones + Spring Milestones + http://repo.spring.io/milestone + + false + + + + + + spring-snapshots + Spring Snapshots + http://repo.spring.io/snapshot + + true + + + + + diff --git a/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java b/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java new file mode 100755 index 000000000..bcebe3a2d --- /dev/null +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java @@ -0,0 +1,430 @@ +/* + * Copyright 2006-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 sparklr.common; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.concurrent.atomic.AtomicReference; + +import org.junit.Test; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.security.crypto.codec.Base64; +import org.springframework.security.oauth2.client.OAuth2RestTemplate; +import org.springframework.security.oauth2.client.resource.UserApprovalRequiredException; +import org.springframework.security.oauth2.client.resource.UserRedirectRequiredException; +import org.springframework.security.oauth2.client.test.BeforeOAuth2Context; +import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration; +import org.springframework.security.oauth2.client.token.AccessTokenRequest; +import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider; +import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.common.exceptions.RedirectMismatchException; +import org.springframework.security.oauth2.common.util.OAuth2Utils; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.StreamUtils; +import org.springframework.web.client.DefaultResponseErrorHandler; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.ResourceAccessException; +import org.springframework.web.client.ResponseErrorHandler; +import org.springframework.web.client.ResponseExtractor; + +import sparklr.common.HttpTestUtils.UriBuilder; + +/** + * @author Dave Syer + * @author Luke Taylor + */ +public abstract class AbstractAuthorizationCodeProviderTests extends AbstractIntegrationTests { + + private AuthorizationCodeAccessTokenProvider accessTokenProvider; + + private ClientHttpResponse tokenEndpointResponse; + + @BeforeOAuth2Context + public void setupAccessTokenProvider() { + accessTokenProvider = new AuthorizationCodeAccessTokenProvider() { + + private ResponseExtractor extractor = super.getResponseExtractor(); + + private ResponseExtractor> authExtractor = super.getAuthorizationResponseExtractor(); + + private ResponseErrorHandler errorHandler = super.getResponseErrorHandler(); + + @Override + protected ResponseErrorHandler getResponseErrorHandler() { + return new DefaultResponseErrorHandler() { + public void handleError(ClientHttpResponse response) throws IOException { + response.getHeaders(); + response.getStatusCode(); + tokenEndpointResponse = response; + errorHandler.handleError(response); + } + }; + } + + @Override + protected ResponseExtractor getResponseExtractor() { + return new ResponseExtractor() { + + public OAuth2AccessToken extractData(ClientHttpResponse response) throws IOException { + try { + response.getHeaders(); + response.getStatusCode(); + tokenEndpointResponse = response; + return extractor.extractData(response); + } + catch (ResourceAccessException e) { + return null; + } + } + + }; + } + + @Override + protected ResponseExtractor> getAuthorizationResponseExtractor() { + return new ResponseExtractor>() { + + public ResponseEntity extractData(ClientHttpResponse response) throws IOException { + response.getHeaders(); + response.getStatusCode(); + tokenEndpointResponse = response; + return authExtractor.extractData(response); + } + }; + } + }; + context.setAccessTokenProvider(accessTokenProvider); + } + + @Test + @OAuth2ContextConfiguration(resource = MyTrustedClient.class, initialize = false) + public void testUnauthenticatedAuthorizationRespondsUnauthorized() throws Exception { + + AccessTokenRequest request = context.getAccessTokenRequest(); + request.setCurrentUri("http://anywhere/"); + request.add(OAuth2Utils.USER_OAUTH_APPROVAL, "true"); + + try { + String code = accessTokenProvider.obtainAuthorizationCode(context.getResource(), request); + assertNotNull(code); + fail("Expected UserRedirectRequiredException"); + } + catch (HttpClientErrorException e) { + assertEquals(HttpStatus.UNAUTHORIZED, e.getStatusCode()); + } + + } + + @Test + @OAuth2ContextConfiguration(resource = MyTrustedClient.class, initialize = false) + public void testSuccessfulAuthorizationCodeFlow() throws Exception { + + // Once the request is ready and approved, we can continue with the access token + approveAccessTokenGrant("http://anywhere/", true); + + // Finally everything is in place for the grant to happen... + assertNotNull(context.getAccessToken()); + + AccessTokenRequest request = context.getAccessTokenRequest(); + assertNotNull(request.getAuthorizationCode()); + assertEquals(HttpStatus.OK, http.getStatusCode("/admin/beans")); + + } + + @Test + @OAuth2ContextConfiguration(resource = MyTrustedClient.class, initialize = false) + public void testWrongRedirectUri() throws Exception { + approveAccessTokenGrant("http://anywhere/", true); + AccessTokenRequest request = context.getAccessTokenRequest(); + // The redirect is stored in the preserved state... + context.getOAuth2ClientContext().setPreservedState(request.getStateKey(), "http://nowhere/"); + // Finally everything is in place for the grant to happen... + try { + assertNotNull(context.getAccessToken()); + fail("Expected RedirectMismatchException"); + } + catch (RedirectMismatchException e) { + // expected + } + assertEquals(HttpStatus.BAD_REQUEST, tokenEndpointResponse.getStatusCode()); + } + + @Test + @OAuth2ContextConfiguration(resource = MyTrustedClient.class, initialize = false) + public void testUserDeniesConfirmation() throws Exception { + approveAccessTokenGrant("http://anywhere/", false); + String location = null; + try { + assertNotNull(context.getAccessToken()); + fail("Expected UserRedirectRequiredException"); + } + catch (UserRedirectRequiredException e) { + location = e.getRedirectUri(); + } + assertTrue("Wrong location: " + location, location.contains("state=")); + assertTrue(location.startsWith("http://anywhere/")); + assertTrue(location.substring(location.indexOf('?')).contains("error=access_denied")); + // It was a redirect that triggered our client redirect exception: + assertEquals(HttpStatus.FOUND, tokenEndpointResponse.getStatusCode()); + } + + @Test + public void testNoClientIdProvided() throws Exception { + ResponseEntity response = attemptToGetConfirmationPage(null, "http://anywhere/"); + // With no client id you get an InvalidClientException on the server which is forwarded to /oauth/error + assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); + String body = response.getBody(); + assertTrue("Wrong body: " + body, body.contains(" response = attemptToGetConfirmationPage("my-trusted-client", null); + // With no redirect uri you get an UnapprovedClientAuthenticationException on the server which is redirected to + // /oauth/error. + assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); + String body = response.getBody(); + assertTrue("Wrong body: " + body, body.contains(" response = http.postForStatus(authorizeUrl, headers, + new LinkedMultiValueMap()); + assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); + } + + @Test + @OAuth2ContextConfiguration(resource = MyClientWithRegisteredRedirect.class, initialize = false) + public void testSuccessfulFlowWithRegisteredRedirect() throws Exception { + + // Once the request is ready and approved, we can continue with the access token + approveAccessTokenGrant(null, true); + + // Finally everything is in place for the grant to happen... + assertNotNull(context.getAccessToken()); + + AccessTokenRequest request = context.getAccessTokenRequest(); + assertNotNull(request.getAuthorizationCode()); + assertEquals(HttpStatus.OK, http.getStatusCode("/admin/beans")); + + } + + @Test + public void testInvalidScopeInAuthorizationRequest() throws Exception { + + HttpHeaders headers = getAuthenticatedHeaders(); + headers.setAccept(Arrays.asList(MediaType.TEXT_HTML)); + + String scope = "bogus"; + String redirectUri = "http://anywhere/?key=value"; + String clientId = "my-client-with-registered-redirect"; + + UriBuilder uri = http.buildUri(authorizePath()).queryParam("response_type", "code") + .queryParam("state", "mystateid").queryParam("scope", scope); + if (clientId != null) { + uri.queryParam("client_id", clientId); + } + if (redirectUri != null) { + uri.queryParam("redirect_uri", redirectUri); + } + ResponseEntity response = http.getForString(uri.pattern(), headers, uri.params()); + assertEquals(HttpStatus.FOUND, response.getStatusCode()); + String location = response.getHeaders().getLocation().toString(); + assertTrue(location.startsWith("http://anywhere/")); + assertTrue(location.contains("error=invalid_scope")); + assertFalse(location.contains("redirect_uri=")); + } + + @Test + public void testInvalidAccessToken() throws Exception { + + // now make sure an unauthorized request fails the right way. + HttpHeaders headers = new HttpHeaders(); + headers.set("Authorization", String.format("%s %s", OAuth2AccessToken.BEARER_TYPE, "FOO")); + ResponseEntity response = http.getForString("/admin/beans", headers); + assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); + + String authenticate = response.getHeaders().getFirst("WWW-Authenticate"); + assertNotNull(authenticate); + assertTrue(authenticate.startsWith("Bearer")); + // Resource Server doesn't know what scopes are required until the token can be validated + assertFalse(authenticate.contains("scope=\"")); + + } + + @Test + @OAuth2ContextConfiguration(resource = MyClientWithRegisteredRedirect.class, initialize = false) + public void testRegisteredRedirectWithWrongRequestedRedirect() throws Exception { + try { + approveAccessTokenGrant("http://nowhere/", true); + fail("Expected RedirectMismatchException"); + } + catch (HttpClientErrorException e) { + assertEquals(HttpStatus.BAD_REQUEST, e.getStatusCode()); + } + } + + @Test + @OAuth2ContextConfiguration(resource = MyClientWithRegisteredRedirect.class, initialize = false) + public void testRegisteredRedirectWithWrongOneInTokenEndpoint() throws Exception { + approveAccessTokenGrant("http://anywhere/?key=value", true); + // Setting the redirect uri directly in the request should override the saved value + context.getAccessTokenRequest().set("redirect_uri", "http://nowhere.com/"); + try { + assertNotNull(context.getAccessToken()); + fail("Expected RedirectMismatchException"); + } + catch (RedirectMismatchException e) { + assertEquals(HttpStatus.BAD_REQUEST.value(), e.getHttpErrorCode()); + assertEquals("invalid_grant", e.getOAuth2ErrorCode()); + } + } + + private ResponseEntity attemptToGetConfirmationPage(String clientId, String redirectUri) { + HttpHeaders headers = getAuthenticatedHeaders(); + return http.getForString(getAuthorizeUrl(clientId, redirectUri, "read"), headers); + } + + private HttpHeaders getAuthenticatedHeaders() { + HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Arrays.asList(MediaType.TEXT_HTML)); + headers.set("Authorization", "Basic " + new String(Base64.encode("user:password".getBytes()))); + if (context.getRestTemplate() != null) { + context.getAccessTokenRequest().setHeaders(headers); + } + return headers; + } + + private String getAuthorizeUrl(String clientId, String redirectUri, String scope) { + UriBuilder uri = http.buildUri(authorizePath()).queryParam("response_type", "code") + .queryParam("state", "mystateid").queryParam("scope", scope); + if (clientId != null) { + uri.queryParam("client_id", clientId); + } + if (redirectUri != null) { + uri.queryParam("redirect_uri", redirectUri); + } + return uri.build().toString(); + } + + protected void approveAccessTokenGrant(String currentUri, boolean approved) { + + AccessTokenRequest request = context.getAccessTokenRequest(); + request.setHeaders(getAuthenticatedHeaders()); + AuthorizationCodeResourceDetails resource = (AuthorizationCodeResourceDetails) context.getResource(); + + if (currentUri != null) { + request.setCurrentUri(currentUri); + } + + String location = null; + + try { + // First try to obtain the access token... + assertNotNull(context.getAccessToken()); + fail("Expected UserRedirectRequiredException"); + } + catch (UserRedirectRequiredException e) { + // Expected and necessary, so that the correct state is set up in the request... + location = e.getRedirectUri(); + } + + assertTrue(location.startsWith(resource.getUserAuthorizationUri())); + assertNull(request.getAuthorizationCode()); + + verifyAuthorizationPage(context.getRestTemplate(), location); + + try { + // Now try again and the token provider will redirect for user approval... + assertNotNull(context.getAccessToken()); + fail("Expected UserRedirectRequiredException"); + } + catch (UserApprovalRequiredException e) { + // Expected and necessary, so that the user can approve the grant... + location = e.getApprovalUri(); + } + + assertTrue(location.startsWith(resource.getUserAuthorizationUri())); + assertNull(request.getAuthorizationCode()); + + // The approval (will be processed on the next attempt to obtain an access token)... + request.set(OAuth2Utils.USER_OAUTH_APPROVAL, "" + approved); + + } + + private void verifyAuthorizationPage(OAuth2RestTemplate restTemplate, String location) { + final AtomicReference confirmationPage = new AtomicReference(); + AuthorizationCodeAccessTokenProvider provider = new AuthorizationCodeAccessTokenProvider() { + @Override + protected ResponseExtractor> getAuthorizationResponseExtractor() { + return new ResponseExtractor>() { + public ResponseEntity extractData(ClientHttpResponse response) throws IOException { + confirmationPage.set(StreamUtils.copyToString(response.getBody(), Charset.forName("UTF-8"))); + return new ResponseEntity(response.getHeaders(), response.getStatusCode()); + } + }; + } + }; + try { + provider.obtainAuthorizationCode(restTemplate.getResource(), restTemplate.getOAuth2ClientContext().getAccessTokenRequest()); + } catch (UserApprovalRequiredException e) { + // ignore + } + String page = confirmationPage.get(); + verifyAuthorizationPage(page); + } + + protected void verifyAuthorizationPage(String page) { + } + + protected static class MyTrustedClient extends AuthorizationCodeResourceDetails { + public MyTrustedClient(Object target) { + super(); + setClientId("my-trusted-client"); + setScope(Arrays.asList("read")); + setId(getClientId()); + AbstractAuthorizationCodeProviderTests test = (AbstractAuthorizationCodeProviderTests) target; + setAccessTokenUri(test.http.getUrl(tokenPath())); + setUserAuthorizationUri(test.http.getUrl(authorizePath())); + } + } + + protected static class MyClientWithRegisteredRedirect extends MyTrustedClient { + public MyClientWithRegisteredRedirect(Object target) { + super(target); + setClientId("my-client-with-registered-redirect"); + setPreEstablishedRedirectUri("http://anywhere/?key=value"); + } + } +} diff --git a/tests/annotation/common/src/main/java/sparklr/common/AbstractClientCredentialsProviderTests.java b/tests/annotation/common/src/main/java/sparklr/common/AbstractClientCredentialsProviderTests.java new file mode 100644 index 000000000..9b273e600 --- /dev/null +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractClientCredentialsProviderTests.java @@ -0,0 +1,121 @@ +package sparklr.common; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.IOException; +import java.util.Arrays; + +import org.junit.Test; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration; +import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsAccessTokenProvider; +import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.web.client.DefaultResponseErrorHandler; +import org.springframework.web.client.ResponseErrorHandler; + +/** + * @author Ryan Heaton + * @author Dave Syer + */ +public abstract class AbstractClientCredentialsProviderTests extends AbstractIntegrationTests { + + private HttpHeaders responseHeaders; + + private HttpStatus responseStatus; + + /** + * tests the basic provider + */ + @Test + @OAuth2ContextConfiguration(ClientCredentials.class) + public void testPostForToken() throws Exception { + OAuth2AccessToken token = context.getAccessToken(); + assertNull(token.getRefreshToken()); + } + + /** + * tests that the registered scopes are used as defaults + */ + @Test + @OAuth2ContextConfiguration(NoScopeClientCredentials.class) + public void testPostForTokenWithNoScopes() throws Exception { + OAuth2AccessToken token = context.getAccessToken(); + assertFalse("Wrong scope: " + token.getScope(), token.getScope().isEmpty()); + } + + @Test + @OAuth2ContextConfiguration(resource = InvalidClientCredentials.class, initialize = false) + public void testInvalidCredentials() throws Exception { + context.setAccessTokenProvider(new ClientCredentialsAccessTokenProvider() { + @Override + protected ResponseErrorHandler getResponseErrorHandler() { + return new DefaultResponseErrorHandler() { + public void handleError(ClientHttpResponse response) throws IOException { + responseHeaders = response.getHeaders(); + responseStatus = response.getStatusCode(); + } + }; + } + }); + try { + context.getAccessToken(); + fail("Expected ResourceAccessException"); + } + catch (Exception e) { + // ignore + } + // System.err.println(responseHeaders); + String header = responseHeaders.getFirst("WWW-Authenticate"); + assertTrue("Wrong header: " + header, header.contains("Basic realm")); + assertEquals(HttpStatus.UNAUTHORIZED, responseStatus); + } + + protected static class ClientCredentials extends ClientCredentialsResourceDetails { + + public ClientCredentials(Object target) { + setClientId("my-client-with-secret"); + setClientSecret("secret"); + setScope(Arrays.asList("read")); + setId(getClientId()); + AbstractClientCredentialsProviderTests test = (AbstractClientCredentialsProviderTests) target; + setAccessTokenUri(test.http.getUrl(tokenPath())); + } + } + + protected static class TrustedClientCredentials extends ClientCredentialsResourceDetails { + + public TrustedClientCredentials(Object target) { + setClientId("my-truusted-client"); + setScope(Arrays.asList("read")); + setId(getClientId()); + AbstractClientCredentialsProviderTests test = (AbstractClientCredentialsProviderTests) target; + setAccessTokenUri(test.http.getUrl(tokenPath())); + } + } + + static class InvalidClientCredentials extends ClientCredentials { + public InvalidClientCredentials(Object target) { + super(target); + setClientId("my-client-with-secret"); + setClientSecret("wrong"); + } + } + + static class NoScopeClientCredentials extends ClientCredentialsResourceDetails { + public NoScopeClientCredentials(Object target) { + setClientId("my-client-with-secret"); + setClientSecret("secret"); + setId(getClientId()); + AbstractClientCredentialsProviderTests test = (AbstractClientCredentialsProviderTests) target; + setAccessTokenUri(test.http.getUrl(tokenPath())); + } + } + +} diff --git a/tests/annotation/common/src/main/java/sparklr/common/AbstractImplicitProviderTests.java b/tests/annotation/common/src/main/java/sparklr/common/AbstractImplicitProviderTests.java new file mode 100644 index 000000000..2f0cf9cc9 --- /dev/null +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractImplicitProviderTests.java @@ -0,0 +1,52 @@ +package sparklr.common; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +import org.junit.Test; +import org.springframework.http.HttpHeaders; +import org.springframework.security.crypto.codec.Base64; +import org.springframework.security.oauth2.client.resource.UserRedirectRequiredException; +import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration; +import org.springframework.security.oauth2.client.token.grant.implicit.ImplicitResourceDetails; +import org.springframework.security.oauth2.common.util.OAuth2Utils; + +/** + * @author Ryan Heaton + * @author Dave Syer + */ +public abstract class AbstractImplicitProviderTests extends AbstractIntegrationTests { + + @Test + @OAuth2ContextConfiguration(resource = NonAutoApproveImplicit.class, initialize = false) + public void testPostForNonAutomaticApprovalToken() throws Exception { + + HttpHeaders headers = new HttpHeaders(); + headers.set("Authorization", "Basic " + new String(Base64.encode("user:password".getBytes()))); + context.getAccessTokenRequest().setHeaders(headers); + try { + assertNotNull(context.getAccessToken()); + fail("Expected UserRedirectRequiredException"); + } + catch (UserRedirectRequiredException e) { + // ignore + } + // add user approval parameter for the second request + context.getAccessTokenRequest().add(OAuth2Utils.USER_OAUTH_APPROVAL, "true"); + context.getAccessTokenRequest().add("scope.read", "true"); + assertNotNull(context.getAccessToken()); + } + + static class NonAutoApproveImplicit extends ImplicitResourceDetails { + public NonAutoApproveImplicit(Object target) { + super(); + setClientId("my-trusted-client"); + setId(getClientId()); + setPreEstablishedRedirectUri("http://anywhere/"); + AbstractImplicitProviderTests test = (AbstractImplicitProviderTests) target; + setAccessTokenUri(test.http.getUrl(authorizePath())); + setUserAuthorizationUri(test.http.getUrl(authorizePath())); + } + } + +} diff --git a/tests/annotation/common/src/main/java/sparklr/common/AbstractIntegrationTests.java b/tests/annotation/common/src/main/java/sparklr/common/AbstractIntegrationTests.java new file mode 100644 index 000000000..70b5e21f9 --- /dev/null +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractIntegrationTests.java @@ -0,0 +1,162 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package sparklr.common; + +import javax.sql.DataSource; + +import org.junit.After; +import org.junit.Rule; +import org.junit.runner.RunWith; +import org.springframework.aop.framework.Advised; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.embedded.EmbeddedWebApplicationContext; +import org.springframework.boot.test.IntegrationTest; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.security.oauth2.client.test.OAuth2ContextSetup; +import org.springframework.security.oauth2.provider.approval.ApprovalStore; +import org.springframework.security.oauth2.provider.approval.InMemoryApprovalStore; +import org.springframework.security.oauth2.provider.approval.JdbcApprovalStore; +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 sparklr.common.AbstractIntegrationTests.TestConfiguration; + +@SpringApplicationConfiguration(classes = TestConfiguration.class, inheritLocations = true) +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +@IntegrationTest +public abstract class AbstractIntegrationTests implements PortHolder { + + private static String globalTokenPath; + + private static String globalTokenKeyPath; + + private static String globalCheckTokenPath; + + private static String globalAuthorizePath; + + @Rule + public HttpTestUtils http = HttpTestUtils.standard().setPortHolder(this); + + @Rule + public OAuth2ContextSetup context = OAuth2ContextSetup.standard(http); + + @Autowired + private EmbeddedWebApplicationContext server; + + @Autowired(required = false) + private TokenStore tokenStore; + + @Autowired(required = false) + private ApprovalStore approvalStore; + + @Autowired(required = false) + private DataSource dataSource; + + @Override + public int getPort() { + return server == null ? 8080 : server.getEmbeddedServletContainer().getPort(); + } + + @After + public void init() throws Exception { + clear(tokenStore); + clear(approvalStore); + } + + private void clear(ApprovalStore approvalStore) throws Exception { + if (approvalStore instanceof Advised) { + Advised advised = (Advised) tokenStore; + ApprovalStore target = (ApprovalStore) advised.getTargetSource().getTarget(); + clear(target); + return; + } + if (approvalStore instanceof InMemoryApprovalStore) { + ((InMemoryApprovalStore) approvalStore).clear(); + } + if (approvalStore instanceof JdbcApprovalStore) { + JdbcTemplate template = new JdbcTemplate(dataSource); + template.execute("delete from oauth_approvals"); + } + } + + private void clear(TokenStore tokenStore) throws Exception { + if (tokenStore instanceof Advised) { + Advised advised = (Advised) tokenStore; + TokenStore target = (TokenStore) advised.getTargetSource().getTarget(); + clear(target); + return; + } + if (tokenStore instanceof InMemoryTokenStore) { + ((InMemoryTokenStore) tokenStore).clear(); + } + if (tokenStore instanceof JdbcTokenStore) { + JdbcTemplate template = new JdbcTemplate(dataSource); + template.execute("delete from oauth_access_token"); + template.execute("delete from oauth_refresh_token"); + template.execute("delete from oauth_client_token"); + template.execute("delete from oauth_code"); + } + } + + @Value("${oauth.paths.token:/oauth/token}") + public void setTokenPath(String tokenPath) { + globalTokenPath = tokenPath; + } + + @Value("${oauth.paths.token_key:/oauth/token_key}") + public void setTokenKeyPath(String tokenKeyPath) { + globalTokenKeyPath = tokenKeyPath; + } + + @Value("${oauth.paths.check_token:/oauth/check_token}") + public void setCheckTokenPath(String tokenPath) { + globalCheckTokenPath = tokenPath; + } + + @Value("${oauth.paths.authorize:/oauth/authorize}") + public void setAuthorizePath(String authorizePath) { + globalAuthorizePath = authorizePath; + } + + public static String tokenPath() { + return globalTokenPath; + } + + public static String tokenKeyPath() { + return globalTokenKeyPath; + } + + public static String checkTokenPath() { + return globalCheckTokenPath; + } + + public static String authorizePath() { + return globalAuthorizePath; + } + + @Configuration + @PropertySource(value = "classpath:test.properties", ignoreResourceNotFound = true) + protected static class TestConfiguration { + + } + +} \ No newline at end of file diff --git a/tests/annotation/common/src/main/java/sparklr/common/AbstractProtectedResourceTests.java b/tests/annotation/common/src/main/java/sparklr/common/AbstractProtectedResourceTests.java new file mode 100644 index 000000000..2e28fff86 --- /dev/null +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractProtectedResourceTests.java @@ -0,0 +1,51 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package sparklr.common; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +/** + * @author Dave Syer + * + */ +public abstract class AbstractProtectedResourceTests extends AbstractIntegrationTests { + + @Test + public void testHomePageIsProtected() throws Exception { + ResponseEntity response = http.getForString("/"); + assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); + assertTrue("Wrong header: " + response.getHeaders(), response.getHeaders().getFirst("WWW-Authenticate") + .startsWith("Bearer realm=")); + } + + @Test + public void testBeansResourceIsProtected() throws Exception { + ResponseEntity response = http.getForString("/admin/beans"); + assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); + assertTrue("Wrong header: " + response.getHeaders(), response.getHeaders().getFirst("WWW-Authenticate") + .startsWith("Bearer realm=")); + } + + @Test + public void testHealthResourceIsOpen() throws Exception { + assertEquals(HttpStatus.OK, http.getStatusCode("/admin/health")); + } + + +} diff --git a/tests/annotation/common/src/main/java/sparklr/common/AbstractRefreshTokenSupportTests.java b/tests/annotation/common/src/main/java/sparklr/common/AbstractRefreshTokenSupportTests.java new file mode 100644 index 000000000..dd3b7b6c6 --- /dev/null +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractRefreshTokenSupportTests.java @@ -0,0 +1,108 @@ +package sparklr.common; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.Map; + +import org.junit.Test; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.crypto.codec.Base64; +import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; + +/** + * @author Dave Syer + */ +public abstract class AbstractRefreshTokenSupportTests extends AbstractIntegrationTests { + + /** + * tests a happy-day flow of the refresh token provider. + */ + @Test + public void testHappyDay() throws Exception { + + OAuth2AccessToken accessToken = getAccessToken("read write", "my-trusted-client"); + + // now use the refresh token to get a new access token. + assertNotNull(accessToken.getRefreshToken()); + OAuth2AccessToken newAccessToken = refreshAccessToken(accessToken.getRefreshToken().getValue()); + assertFalse(newAccessToken.getValue().equals(accessToken.getValue())); + + verifyAccessTokens(accessToken, newAccessToken); + + } + + protected void verifyAccessTokens(OAuth2AccessToken oldAccessToken, OAuth2AccessToken newAccessToken) { + // make sure the new access token can be used. + verifyTokenResponse(newAccessToken.getValue(), HttpStatus.OK); + // make sure the old access token isn't valid anymore. + verifyTokenResponse(oldAccessToken.getValue(), HttpStatus.UNAUTHORIZED); + } + + protected void verifyTokenResponse(String accessToken, HttpStatus status) { + HttpHeaders headers = new HttpHeaders(); + headers.set("Authorization", String.format("%s %s", OAuth2AccessToken.BEARER_TYPE, accessToken)); + assertEquals(status, http.getStatusCode("/admin/beans", headers)); + } + + private OAuth2AccessToken refreshAccessToken(String refreshToken) { + + MultiValueMap formData = new LinkedMultiValueMap(); + formData.add("grant_type", "refresh_token"); + formData.add("client_id", "my-trusted-client"); + formData.add("refresh_token", refreshToken); + formData.add("scope", "read"); + HttpHeaders headers = getTokenHeaders("my-trusted-client"); + + @SuppressWarnings("rawtypes") + ResponseEntity response = http.postForMap(tokenPath(), headers, formData); + assertEquals(HttpStatus.OK, response.getStatusCode()); + assertTrue("Wrong cache control: " + response.getHeaders().getFirst("Cache-Control"), response.getHeaders() + .getFirst("Cache-Control").contains("no-store")); + @SuppressWarnings("unchecked") + OAuth2AccessToken newAccessToken = DefaultOAuth2AccessToken.valueOf(response.getBody()); + return newAccessToken; + + } + + private OAuth2AccessToken getAccessToken(String scope, String clientId) throws Exception { + MultiValueMap formData = getTokenFormData(scope, clientId); + HttpHeaders headers = getTokenHeaders(clientId); + @SuppressWarnings("rawtypes") + ResponseEntity response = http.postForMap(tokenPath(), headers, formData); + assertEquals(HttpStatus.OK, response.getStatusCode()); + assertTrue("Wrong cache control: " + response.getHeaders().getFirst("Cache-Control"), response.getHeaders() + .getFirst("Cache-Control").contains("no-store")); + + @SuppressWarnings("unchecked") + OAuth2AccessToken accessToken = DefaultOAuth2AccessToken.valueOf(response.getBody()); + return accessToken; + } + + private HttpHeaders getTokenHeaders(String clientId) { + HttpHeaders headers = new HttpHeaders(); + if (clientId != null) { + headers.set("Authorization", "Basic " + new String(Base64.encode((clientId + ":").getBytes()))); + } + return headers ; + } + + private MultiValueMap getTokenFormData(String scope, String clientId) { + MultiValueMap formData = new LinkedMultiValueMap(); + formData.add("grant_type", "password"); + if (clientId != null) { + formData.add("client_id", clientId); + } + formData.add("scope", scope); + formData.add("username", "user"); + formData.add("password", "password"); + return formData; + } +} diff --git a/tests/annotation/common/src/main/java/sparklr/common/AbstractResourceOwnerPasswordProviderTests.java b/tests/annotation/common/src/main/java/sparklr/common/AbstractResourceOwnerPasswordProviderTests.java new file mode 100644 index 000000000..319c19f67 --- /dev/null +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractResourceOwnerPasswordProviderTests.java @@ -0,0 +1,267 @@ +package sparklr.common; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.List; + +import org.junit.Test; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.security.crypto.codec.Base64; +import org.springframework.security.oauth2.client.test.BeforeOAuth2Context; +import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration; +import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordAccessTokenProvider; +import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordResourceDetails; +import org.springframework.security.oauth2.common.AuthenticationScheme; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.web.client.DefaultResponseErrorHandler; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.ResponseErrorHandler; +import org.springframework.web.client.ResponseExtractor; + +/** + * @author Ryan Heaton + * @author Dave Syer + */ +public abstract class AbstractResourceOwnerPasswordProviderTests extends AbstractIntegrationTests { + + private ClientHttpResponse tokenEndpointResponse; + + @BeforeOAuth2Context + public void setupAccessTokenProvider() { + ResourceOwnerPasswordAccessTokenProvider accessTokenProvider = new ResourceOwnerPasswordAccessTokenProvider() { + + private ResponseExtractor extractor = super.getResponseExtractor(); + + private ResponseErrorHandler errorHandler = super.getResponseErrorHandler(); + + @Override + protected ResponseErrorHandler getResponseErrorHandler() { + return new DefaultResponseErrorHandler() { + public void handleError(ClientHttpResponse response) throws IOException { + response.getHeaders(); + response.getStatusCode(); + tokenEndpointResponse = response; + errorHandler.handleError(response); + } + }; + } + + @Override + protected ResponseExtractor getResponseExtractor() { + return new ResponseExtractor() { + + public OAuth2AccessToken extractData(ClientHttpResponse response) throws IOException { + response.getHeaders(); + response.getStatusCode(); + tokenEndpointResponse = response; + return extractor.extractData(response); + } + + }; + } + }; + context.setAccessTokenProvider(accessTokenProvider); + } + + @Test + public void testUnauthenticated() throws Exception { + // first make sure the resource is actually protected. + assertEquals(HttpStatus.UNAUTHORIZED, http.getStatusCode("/admin/beans")); + } + + @Test + public void testUnauthenticatedErrorMessage() throws Exception { + HttpHeaders headers = new HttpHeaders(); + ResponseEntity response = http.getForResponse("/admin/beans", headers); + assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); + String authenticate = response.getHeaders().getFirst("WWW-Authenticate"); + assertTrue("Wrong header: " + authenticate, authenticate.contains("error=\"unauthorized\"")); + } + + @Test + public void testInvalidTokenErrorMessage() throws Exception { + HttpHeaders headers = new HttpHeaders(); + headers.set("Authorization", "Bearer FOO"); + ResponseEntity response = http.getForResponse("/admin/beans", headers); + assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); + String authenticate = response.getHeaders().getFirst("WWW-Authenticate"); + assertTrue("Wrong header: " + authenticate, authenticate.contains("error=\"invalid_token\"")); + } + + @Test + @OAuth2ContextConfiguration(ResourceOwner.class) + public void testTokenObtainedWithHeaderAuthentication() throws Exception { + assertEquals(HttpStatus.OK, http.getStatusCode("/admin/beans")); + int expiry = context.getAccessToken().getExpiresIn(); + assertTrue("Expiry not overridden in config: " + expiry, expiry < 1000); + assertEquals(new MediaType("application", "json", Charset.forName("UTF-8")), tokenEndpointResponse.getHeaders() + .getContentType()); + } + + @Test + @OAuth2ContextConfiguration(ResourceOwnerQuery.class) + public void testTokenObtainedWithQueryAuthentication() throws Exception { + assertEquals(HttpStatus.OK, http.getStatusCode("/admin/beans")); + } + + @Test + @OAuth2ContextConfiguration(resource = ResourceOwnerNoSecretProvided.class, initialize = false) + public void testTokenNotGrantedIfSecretNotProvided() throws Exception { + try { + context.getAccessToken(); + } + catch (HttpClientErrorException e) { + assertEquals(HttpStatus.UNAUTHORIZED, e.getStatusCode()); + List values = tokenEndpointResponse.getHeaders().get("WWW-Authenticate"); + assertEquals(1, values.size()); + String header = values.get(0); + assertTrue("Wrong header " + header, header.contains("Basic realm=\"oauth2/client\"")); + } + } + + @Test + @OAuth2ContextConfiguration(ResourceOwnerSecretProvidedInForm.class) + public void testSecretProvidedInForm() throws Exception { + assertEquals(HttpStatus.OK, http.getStatusCode("/admin/beans")); + } + + @Test + @OAuth2ContextConfiguration(ResourceOwnerSecretProvided.class) + public void testSecretProvidedInHeader() throws Exception { + assertEquals(HttpStatus.OK, http.getStatusCode("/admin/beans")); + } + + @Test + @OAuth2ContextConfiguration(resource = NoSuchClient.class, initialize = false) + public void testNoSuchClient() throws Exception { + + // The error comes back as additional information because OAuth2AccessToken is so extensible! + try { + context.getAccessToken(); + } + catch (Exception e) { + // assertEquals("invalid_client", e.getOAuth2ErrorCode()); + } + + assertEquals(HttpStatus.UNAUTHORIZED, tokenEndpointResponse.getStatusCode()); + + List newCookies = tokenEndpointResponse.getHeaders().get("Set-Cookie"); + if (newCookies != null && !newCookies.isEmpty()) { + fail("No cookies should be set. Found: " + newCookies.get(0) + "."); + } + + } + + @Test + public void testTokenEndpointunauthenticated() throws Exception { + // first make sure the resource is actually protected. + assertEquals( + HttpStatus.UNAUTHORIZED, + http.getRestTemplate().exchange(http.getUrl("/oauth/token"), HttpMethod.GET, + new HttpEntity((Void)null), String.class).getStatusCode()); + } + + @Test + @OAuth2ContextConfiguration(resource = InvalidGrantType.class, initialize = false) + public void testInvalidGrantType() throws Exception { + + // The error comes back as additional information because OAuth2AccessToken is so extensible! + try { + context.getAccessToken(); + } + catch (Exception e) { + // assertEquals("invalid_client", e.getOAuth2ErrorCode()); + } + + assertEquals(HttpStatus.UNAUTHORIZED, tokenEndpointResponse.getStatusCode()); + + List newCookies = tokenEndpointResponse.getHeaders().get("Set-Cookie"); + if (newCookies != null && !newCookies.isEmpty()) { + fail("No cookies should be set. Found: " + newCookies.get(0) + "."); + } + + } + + /** + * tests that we get the correct error response if the media type is unacceptable. + */ + @Test + public void testMissingGrantType() throws Exception { + HttpHeaders headers = new HttpHeaders(); + headers.set("Authorization", + String.format("Basic %s", new String(Base64.encode("my-trusted-client:".getBytes())))); + headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); + ResponseEntity response = http.postForString(tokenPath(), headers, + new LinkedMultiValueMap()); + assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); + assertTrue(response.getBody().contains("invalid_request")); + } + + protected static class ResourceOwner extends ResourceOwnerPasswordResourceDetails { + public ResourceOwner(Object target) { + setClientId("my-trusted-client"); + setScope(Arrays.asList("read")); + setId(getClientId()); + setUsername("user"); + setPassword("password"); + AbstractResourceOwnerPasswordProviderTests test = (AbstractResourceOwnerPasswordProviderTests) target; + setAccessTokenUri(test.http.getUrl(tokenPath())); + } + } + + static class ResourceOwnerQuery extends ResourceOwner { + public ResourceOwnerQuery(Object target) { + super(target); + setAuthenticationScheme(AuthenticationScheme.query); + } + } + + static class ResourceOwnerNoSecretProvided extends ResourceOwner { + public ResourceOwnerNoSecretProvided(Object target) { + super(target); + setClientId("my-client-with-secret"); + } + } + + static class ResourceOwnerSecretProvided extends ResourceOwner { + public ResourceOwnerSecretProvided(Object target) { + super(target); + setClientId("my-client-with-secret"); + setClientSecret("secret"); + } + } + + static class ResourceOwnerSecretProvidedInForm extends ResourceOwnerSecretProvided { + public ResourceOwnerSecretProvidedInForm(Object target) { + super(target); + setAuthenticationScheme(AuthenticationScheme.form); + } + } + + static class InvalidGrantType extends ResourceOwner { + public InvalidGrantType(Object target) { + super(target); + setClientId("my-client-with-registered-redirect"); + } + } + + static class NoSuchClient extends ResourceOwner { + public NoSuchClient(Object target) { + super(target); + setClientId("no-such-client"); + } + } + +} diff --git a/tests/annotation/common/src/main/java/sparklr/common/HttpTestUtils.java b/tests/annotation/common/src/main/java/sparklr/common/HttpTestUtils.java new file mode 100644 index 000000000..2b3cb220c --- /dev/null +++ b/tests/annotation/common/src/main/java/sparklr/common/HttpTestUtils.java @@ -0,0 +1,306 @@ +package sparklr.common; + +import java.net.HttpURLConnection; +import java.net.URI; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +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.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.oauth2.client.test.RestTemplateHolder; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestOperations; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriTemplate; + +/** + *

    + * A rule that provides HTTP connectivity to test cases on the assumption that the server is available when test methods + * fire. + *

    + * + * @author Dave Syer + * + */ +public class HttpTestUtils implements MethodRule, RestTemplateHolder { + + private static Log logger = LogFactory.getLog(HttpTestUtils.class); + + private static int DEFAULT_PORT = 8080; + + private static String DEFAULT_HOST = "localhost"; + + private int port; + + private String hostName = DEFAULT_HOST; + + private RestOperations client; + + private PortHolder portHolder; + + /** + * @return a new rule that sets up default host and port etc. + */ + public static HttpTestUtils standard() { + return new HttpTestUtils(); + } + + private HttpTestUtils() { + setPort(DEFAULT_PORT); + } + + /** + * @param port the port to set + */ + public HttpTestUtils setPort(int port) { + this.port = port; + if (client == null) { + client = createRestTemplate(); + } + return this; + } + + /** + * @param port the port holder to set + */ + public HttpTestUtils setPortHolder(PortHolder port) { + this.portHolder = port; + return this; + } + + /** + * @param hostName the hostName to set + */ + public HttpTestUtils setHostName(String hostName) { + this.hostName = hostName; + return this; + } + + public Statement apply(final Statement base, FrameworkMethod method, Object target) { + + if (portHolder!=null) { + setPort(portHolder.getPort()); + } + + RestTemplate client = new RestTemplate(); + boolean followRedirects = HttpURLConnection.getFollowRedirects(); + HttpURLConnection.setFollowRedirects(false); + try { + client.getForEntity(new UriTemplate(getUrl("/admin/info")).toString(), String.class); + logger.info("Basic connectivity test passed"); + } + catch (RestClientException e) { + logger.warn(String.format( + "Not executing tests because basic connectivity test failed for hostName=%s, port=%d", hostName, + port), e); + } + finally { + HttpURLConnection.setFollowRedirects(followRedirects); + } + + return new Statement() { + @Override + public void evaluate() throws Throwable { + base.evaluate(); + } + }; + + } + + public String getBaseUrl() { + return "http://" + hostName + ":" + port; + } + + public String getUrl(String path) { + if (path.startsWith("http")) { + return path; + } + if (!path.startsWith("/")) { + path = "/" + path; + } + return "http://" + hostName + ":" + port + path; + } + + public ResponseEntity postForString(String path, MultiValueMap formData) { + HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); + return client.exchange(getUrl(path), HttpMethod.POST, new HttpEntity>(formData, + headers), String.class); + } + + public ResponseEntity postForString(String path, HttpHeaders headers, MultiValueMap formData) { + HttpHeaders actualHeaders = new HttpHeaders(); + actualHeaders.putAll(headers); + headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); + return client.exchange(getUrl(path), HttpMethod.POST, new HttpEntity>(formData, + actualHeaders), String.class); + } + + @SuppressWarnings("rawtypes") + public ResponseEntity postForMap(String path, MultiValueMap formData) { + return postForMap(path, new HttpHeaders(), formData); + } + + @SuppressWarnings("rawtypes") + public ResponseEntity postForMap(String path, HttpHeaders headers, MultiValueMap formData) { + if (headers.getContentType() == null) { + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + } + return client.exchange(getUrl(path), HttpMethod.POST, new HttpEntity>(formData, + headers), Map.class); + } + + public ResponseEntity postForStatus(String path, MultiValueMap formData) { + return postForStatus(this.client, path, formData); + } + + public ResponseEntity postForStatus(String path, HttpHeaders headers, MultiValueMap formData) { + return postForStatus(this.client, path, headers, formData); + } + + private ResponseEntity postForStatus(RestOperations client, String path, + MultiValueMap formData) { + return postForStatus(client, path, new HttpHeaders(), formData); + } + + private ResponseEntity postForStatus(RestOperations client, String path, HttpHeaders headers, + MultiValueMap formData) { + HttpHeaders actualHeaders = new HttpHeaders(); + actualHeaders.putAll(headers); + actualHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + return client.exchange(getUrl(path), HttpMethod.POST, new HttpEntity>(formData, + actualHeaders), (Class) null); + } + + public ResponseEntity postForRedirect(String path, HttpHeaders headers, MultiValueMap params) { + ResponseEntity exchange = postForStatus(path, headers, params); + + if (exchange.getStatusCode() != HttpStatus.FOUND) { + throw new IllegalStateException("Expected 302 but server returned status code " + exchange.getStatusCode()); + } + + if (exchange.getHeaders().containsKey("Set-Cookie")) { + String cookie = exchange.getHeaders().getFirst("Set-Cookie"); + headers.set("Cookie", cookie); + } + + String location = exchange.getHeaders().getLocation().toString(); + + return client.exchange(location, HttpMethod.GET, new HttpEntity(null, headers), (Class) null); + } + + public ResponseEntity getForString(String path) { + return getForString(path, new HttpHeaders()); + } + + public ResponseEntity getForString(String path, final HttpHeaders headers) { + return client.exchange(getUrl(path), HttpMethod.GET, new HttpEntity((Void) null, headers), String.class); + } + + public ResponseEntity getForString(String path, final HttpHeaders headers, Map uriVariables) { + return client.exchange(getUrl(path), HttpMethod.GET, new HttpEntity((Void) null, headers), String.class, + uriVariables); + } + + public ResponseEntity getForResponse(String path, final HttpHeaders headers, Map uriVariables) { + HttpEntity request = new HttpEntity(null, headers); + return client.exchange(getUrl(path), HttpMethod.GET, request, (Class) null, uriVariables); + } + + public ResponseEntity getForResponse(String path, HttpHeaders headers) { + return getForResponse(path, headers, Collections. emptyMap()); + } + + public HttpStatus getStatusCode(String path, final HttpHeaders headers) { + ResponseEntity response = getForResponse(path, headers); + return response.getStatusCode(); + } + + public HttpStatus getStatusCode(String path) { + return getStatusCode(getUrl(path), null); + } + + public void setRestTemplate(RestOperations restTemplate) { + client = restTemplate; + } + + public RestOperations getRestTemplate() { + return client; + } + + public RestOperations createRestTemplate() { + RestTemplate client = new TestRestTemplate(); + return client; + } + + public UriBuilder buildUri(String url) { + return UriBuilder.fromUri(url.startsWith("http:") ? url : getUrl(url)); + } + + public static class UriBuilder { + + private final String url; + + private Map params = new LinkedHashMap(); + + public UriBuilder(String url) { + this.url = url; + } + + public static UriBuilder fromUri(String url) { + return new UriBuilder(url); + } + + public UriBuilder queryParam(String key, String value) { + params.put(key, value); + return this; + } + + public String pattern() { + StringBuilder builder = new StringBuilder(); + // try { + builder.append(url.replace(" ", "+")); + if (!params.isEmpty()) { + builder.append("?"); + boolean first = true; + for (String key : params.keySet()) { + if (!first) { + builder.append("&"); + } + else { + first = false; + } + String value = params.get(key); + if (value.contains("=")) { + value = value.replace("=", "%3D"); + } + builder.append(key + "={" + key + "}"); + } + } + return builder.toString(); + + } + + public Map params() { + return params; + } + + public URI build() { + return new UriTemplate(pattern()).expand(params); + } + } + +} diff --git a/tests/annotation/common/src/main/java/sparklr/common/PortHolder.java b/tests/annotation/common/src/main/java/sparklr/common/PortHolder.java new file mode 100644 index 000000000..362dceda8 --- /dev/null +++ b/tests/annotation/common/src/main/java/sparklr/common/PortHolder.java @@ -0,0 +1,24 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package sparklr.common; + +/** + * @author Dave Syer + * + */ +public interface PortHolder { + + int getPort(); + +} diff --git a/tests/annotation/form/README.md b/tests/annotation/form/README.md new file mode 100644 index 000000000..7d1ce46a6 --- /dev/null +++ b/tests/annotation/form/README.md @@ -0,0 +1,7 @@ +In this project the Authorization Server allows form-based +authentication on the /oauth/token endpoint. This is not best +practice from a security point of view so it is disabled by default. + +In the Authorization Server we call `allowFormAuthenticationForClients()` +on the configurer. That's it. + diff --git a/tests/annotation/form/pom.xml b/tests/annotation/form/pom.xml new file mode 100644 index 000000000..89a0fc3f4 --- /dev/null +++ b/tests/annotation/form/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + + spring-oauth2-tests-form + + spring-oauth2-tests-form + Demo project + + + org.demo + spring-oauth2-tests-parent + 2.0.2.RELEASE + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.security.oauth + spring-security-oauth2 + + + org.demo + spring-oauth2-tests-common + ${project.version} + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/tests/annotation/form/src/main/java/demo/Application.java b/tests/annotation/form/src/main/java/demo/Application.java new file mode 100644 index 000000000..696029d71 --- /dev/null +++ b/tests/annotation/form/src/main/java/demo/Application.java @@ -0,0 +1,80 @@ +package demo; + +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.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; +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.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Configuration +@ComponentScan +@EnableAutoConfiguration +@EnableResourceServer +@RestController +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + @RequestMapping("/") + public String home() { + return "Hello World"; + } + + @Configuration + @EnableAuthorizationServer + protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter { + + @Autowired + private AuthenticationManager authenticationManager; + + @Override + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + endpoints.authenticationManager(authenticationManager); + } + + @Override + public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { + oauthServer.allowFormAuthenticationForClients(); + } + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + // @formatter:off + clients.inMemory() + .withClient("my-trusted-client") + .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit") + .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") + .scopes("read", "write", "trust") + .resourceIds("oauth2-resource") + .accessTokenValiditySeconds(60) + .and() + .withClient("my-client-with-registered-redirect") + .authorizedGrantTypes("authorization_code") + .authorities("ROLE_CLIENT") + .scopes("read", "trust") + .resourceIds("oauth2-resource") + .redirectUris("http://anywhere/?key=value") + .and() + .withClient("my-client-with-secret") + .authorizedGrantTypes("client_credentials", "password") + .authorities("ROLE_CLIENT") + .scopes("read") + .resourceIds("oauth2-resource") + .secret("secret"); + // @formatter:on + } + + } + +} diff --git a/tests/annotation/form/src/main/resources/application.yml b/tests/annotation/form/src/main/resources/application.yml new file mode 100644 index 000000000..147340301 --- /dev/null +++ b/tests/annotation/form/src/main/resources/application.yml @@ -0,0 +1,8 @@ +spring: + application: + name: form +management: + context_path: /admin +security: + user: + password: password diff --git a/tests/annotation/form/src/test/java/demo/AdHocTests.java b/tests/annotation/form/src/test/java/demo/AdHocTests.java new file mode 100644 index 000000000..e5bfeca13 --- /dev/null +++ b/tests/annotation/form/src/test/java/demo/AdHocTests.java @@ -0,0 +1,40 @@ +/* + * Copyright 20013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package demo; + +import org.junit.Ignore; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +/** + * @author Dave Syer + * + */ +@RunWith(Suite.class) +// @formatter:off +@SuiteClasses({ + ClientCredentialsProviderTests.class, + RefreshTokenSupportTests.class, + ImplicitProviderTests.class, + ResourceOwnerPasswordProviderTests.class, + ApplicationTests.class, + ProtectedResourceTests.class, + AuthorizationCodeProviderTests.class, + }) +// @formatter:on +@Ignore("Test suite for tracking order dependencies") +public class AdHocTests { + +} diff --git a/tests/annotation/form/src/test/java/demo/ApplicationTests.java b/tests/annotation/form/src/test/java/demo/ApplicationTests.java new file mode 100644 index 000000000..8da63b411 --- /dev/null +++ b/tests/annotation/form/src/test/java/demo/ApplicationTests.java @@ -0,0 +1,20 @@ +package demo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = Application.class) +@WebAppConfiguration +@ActiveProfiles("test") +public class ApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/tests/annotation/form/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/form/src/test/java/demo/AuthorizationCodeProviderTests.java new file mode 100755 index 000000000..632098bf1 --- /dev/null +++ b/tests/annotation/form/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -0,0 +1,25 @@ +/* + * Copyright 2006-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 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 new file mode 100644 index 000000000..3d9ccf4f6 --- /dev/null +++ b/tests/annotation/form/src/test/java/demo/ClientCredentialsProviderTests.java @@ -0,0 +1,87 @@ +package demo; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +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; +import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration; +import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsAccessTokenProvider; +import org.springframework.security.oauth2.common.AuthenticationScheme; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.web.client.DefaultResponseErrorHandler; +import org.springframework.web.client.ResponseErrorHandler; + +import sparklr.common.AbstractClientCredentialsProviderTests; + +/** + * @author Dave Syer + */ +@SpringApplicationConfiguration(classes=Application.class) +public class ClientCredentialsProviderTests extends AbstractClientCredentialsProviderTests { + + private HttpHeaders responseHeaders; + + private HttpStatus responseStatus; + + /** + * tests the basic provider with form based client credentials + */ + @Test + @OAuth2ContextConfiguration(FormClientCredentials.class) + public void testPostForTokenWithForm() throws Exception { + OAuth2AccessToken token = context.getAccessToken(); + assertNull(token.getRefreshToken()); + } + + @Test + @OAuth2ContextConfiguration(resource = InvalidClientCredentials.class, initialize = false) + public void testInvalidCredentialsWithFormAuthentication() throws Exception { + context.setAccessTokenProvider(new ClientCredentialsAccessTokenProvider() { + @Override + protected ResponseErrorHandler getResponseErrorHandler() { + return new DefaultResponseErrorHandler() { + public void handleError(ClientHttpResponse response) throws IOException { + responseHeaders = response.getHeaders(); + responseStatus = response.getStatusCode(); + } + }; + } + }); + try { + context.getAccessToken(); + fail("Expected ResourceAccessException"); + } + catch (Exception e) { + // ignore + } + // System.err.println(responseHeaders); + String header = responseHeaders.getFirst("WWW-Authenticate"); + assertTrue("Wrong header: " + header, header.contains("Form realm")); + assertEquals(HttpStatus.UNAUTHORIZED, responseStatus); + } + + static class FormClientCredentials extends ClientCredentials { + public FormClientCredentials(Object target) { + super(target); + setClientAuthenticationScheme(AuthenticationScheme.form); + } + } + + static class InvalidClientCredentials extends ClientCredentials { + public InvalidClientCredentials(Object target) { + super(target); + setClientId("my-client-with-secret"); + setClientSecret("wrong"); + setClientAuthenticationScheme(AuthenticationScheme.form); + } + } + +} diff --git a/tests/annotation/form/src/test/java/demo/ImplicitProviderTests.java b/tests/annotation/form/src/test/java/demo/ImplicitProviderTests.java new file mode 100644 index 000000000..7a8958187 --- /dev/null +++ b/tests/annotation/form/src/test/java/demo/ImplicitProviderTests.java @@ -0,0 +1,13 @@ +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 new file mode 100644 index 000000000..c752cbe12 --- /dev/null +++ b/tests/annotation/form/src/test/java/demo/ProtectedResourceTests.java @@ -0,0 +1,27 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package 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 new file mode 100644 index 000000000..4ed370eea --- /dev/null +++ b/tests/annotation/form/src/test/java/demo/RefreshTokenSupportTests.java @@ -0,0 +1,13 @@ +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 new file mode 100644 index 000000000..aa5786098 --- /dev/null +++ b/tests/annotation/form/src/test/java/demo/ResourceOwnerPasswordProviderTests.java @@ -0,0 +1,13 @@ +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/src/test/resources/test.properties b/tests/annotation/form/src/test/resources/test.properties new file mode 100644 index 000000000..24466e50d --- /dev/null +++ b/tests/annotation/form/src/test/resources/test.properties @@ -0,0 +1 @@ +server.port: 0 \ No newline at end of file diff --git a/tests/annotation/jdbc/README.md b/tests/annotation/jdbc/README.md new file mode 100644 index 000000000..b88f1fd85 --- /dev/null +++ b/tests/annotation/jdbc/README.md @@ -0,0 +1,21 @@ +This project shows what you can do with the minimum configuration to +set up an Authorization Server and Resource Server with JDBC backends. + +The Authorization Server has JDBC backends for clients +(`ClientDetailsStore`), tokens (`TokenStore`), authorization codes +(`AuthorizationCodeStore`) and user accounts +(`UserDetailsManager`). Even with these services, a horizontally +scaled Authorization Server needs to be fronted by a load balancer +with sticky sessions (or else a Spring `SessionAttributeStore` should +be provided in addition to wht you see here), if the stateful grant +types are used (authorization code or implicit). + +An `AuthenticationManager` is created (it has a single user, named +"user", with password "password", per `application.yml`). It is needed +in the Authorization Server to provide authentication for the Resource +Owner Password grant type. + +The Resource Server shares the `TokenStore` with the Authorization +Server, but it doesn't need to know about the other services (so they +could be in-memory if there is a single instance of the Authorization +Server). diff --git a/tests/annotation/jdbc/pom.xml b/tests/annotation/jdbc/pom.xml new file mode 100644 index 000000000..4f9fe30d6 --- /dev/null +++ b/tests/annotation/jdbc/pom.xml @@ -0,0 +1,58 @@ + + + 4.0.0 + + spring-oauth2-tests-jdbc + + spring-oauth2-tests-jdbc + Demo project + + + org.demo + spring-oauth2-tests-parent + 2.0.2.RELEASE + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-jdbc + + + org.springframework.security.oauth + spring-security-oauth2 + + + com.h2database + h2 + + + org.demo + spring-oauth2-tests-common + ${project.version} + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/tests/annotation/jdbc/src/main/java/demo/Application.java b/tests/annotation/jdbc/src/main/java/demo/Application.java new file mode 100644 index 000000000..715962ef2 --- /dev/null +++ b/tests/annotation/jdbc/src/main/java/demo/Application.java @@ -0,0 +1,141 @@ +package demo; + +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.security.SecurityProperties; +import org.springframework.boot.autoconfigure.security.SecurityProperties.User; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; +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.config.annotation.web.configuration.ResourceServerConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; +import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; +import org.springframework.security.oauth2.provider.code.JdbcAuthorizationCodeServices; +import org.springframework.security.oauth2.provider.token.TokenStore; +import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Configuration +@EnableAutoConfiguration +@RestController +public class Application { + + @Order(Ordered.LOWEST_PRECEDENCE - 8) + protected static class ApplicationSecurity extends WebSecurityConfigurerAdapter { + + @Autowired + private DataSource dataSource; + + @Autowired + private SecurityProperties security; + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + User user = security.getUser(); + // @formatter:off + auth.jdbcAuthentication().dataSource(dataSource) + .withUser(user.getName()) + .password(user.getPassword()) + .roles(user.getRole().toArray(new String[0])); + // @formatter:on + } + } + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + @RequestMapping("/") + public String home() { + return "Hello World"; + } + + @Configuration + @EnableResourceServer + protected static class ResourceServer extends ResourceServerConfigurerAdapter { + + @Autowired + private TokenStore tokenStore; + + @Override + public void configure(ResourceServerSecurityConfigurer resources) throws Exception { + resources.tokenStore(tokenStore); + } + + @Override + public void configure(HttpSecurity http) throws Exception { + http.authorizeRequests().anyRequest().authenticated(); + } + + } + + @Configuration + @EnableAuthorizationServer + protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter { + + @Autowired + private AuthenticationManager authenticationManager; + + @Autowired + private DataSource dataSource; + + @Bean + public JdbcTokenStore tokenStore() { + return new JdbcTokenStore(dataSource); + } + + @Bean + protected AuthorizationCodeServices authorizationCodeServices() { + return new JdbcAuthorizationCodeServices(dataSource); + } + + @Override + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + endpoints.authorizationCodeServices(authorizationCodeServices()) + .authenticationManager(authenticationManager).tokenStore(tokenStore()).approvalStoreDisabled(); + } + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + // @formatter:off + clients.jdbc(dataSource) + .withClient("my-trusted-client") + .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit") + .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") + .scopes("read", "write", "trust") + .resourceIds("oauth2-resource") + .accessTokenValiditySeconds(60) + .and() + .withClient("my-client-with-registered-redirect") + .authorizedGrantTypes("authorization_code") + .authorities("ROLE_CLIENT") + .scopes("read", "trust") + .resourceIds("oauth2-resource") + .redirectUris("http://anywhere/?key=value") + .and() + .withClient("my-client-with-secret") + .authorizedGrantTypes("client_credentials", "password") + .authorities("ROLE_CLIENT") + .scopes("read") + .resourceIds("oauth2-resource") + .secret("secret"); + // @formatter:on + } + + } + +} diff --git a/tests/annotation/jdbc/src/main/java/demo/ClientApplication.java b/tests/annotation/jdbc/src/main/java/demo/ClientApplication.java new file mode 100644 index 000000000..82e4612c1 --- /dev/null +++ b/tests/annotation/jdbc/src/main/java/demo/ClientApplication.java @@ -0,0 +1,89 @@ +package demo; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import javax.annotation.Resource; +import javax.sql.DataSource; + +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.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Scope; +import org.springframework.context.annotation.ScopedProxyMode; +import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext; +import org.springframework.security.oauth2.client.OAuth2RestOperations; +import org.springframework.security.oauth2.client.OAuth2RestTemplate; +import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails; +import org.springframework.security.oauth2.client.token.AccessTokenProviderChain; +import org.springframework.security.oauth2.client.token.AccessTokenRequest; +import org.springframework.security.oauth2.client.token.ClientTokenServices; +import org.springframework.security.oauth2.client.token.JdbcClientTokenServices; +import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider; +import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails; +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Configuration +@EnableAutoConfiguration +@EnableOAuth2Client +@RestController +public class ClientApplication { + + public static void main(String[] args) { + new SpringApplicationBuilder().profiles("client").sources(ClientApplication.class).run(args); + } + + @Value("${oauth.resource:http://localhost:8080}") + private String baseUrl; + + @Value("${oauth.authorize:http://localhost:8080/oauth/authorize}") + private String authorizeUrl; + + @Value("${oauth.token:http://localhost:8080/oauth/token}") + private String tokenUrl; + + @Resource + @Qualifier("accessTokenRequest") + private AccessTokenRequest accessTokenRequest; + + @Autowired + private DataSource dataSource; + + @RequestMapping("/") + public List> home() { + @SuppressWarnings("unchecked") + List> result = restTemplate().getForObject(baseUrl + "/admin/beans", List.class); + return result; + } + + @Bean + @Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES) + public OAuth2RestOperations restTemplate() { + OAuth2RestTemplate template = new OAuth2RestTemplate(resource(), new DefaultOAuth2ClientContext(accessTokenRequest)); + AccessTokenProviderChain provider = new AccessTokenProviderChain(Arrays.asList(new AuthorizationCodeAccessTokenProvider())); + provider.setClientTokenServices(clientTokenServices()); + return template; + } + + @Bean + public ClientTokenServices clientTokenServices() { + return new JdbcClientTokenServices(dataSource); + } + + @Bean + protected OAuth2ProtectedResourceDetails resource() { + AuthorizationCodeResourceDetails resource = new AuthorizationCodeResourceDetails(); + resource.setAccessTokenUri(tokenUrl); + resource.setUserAuthorizationUri(authorizeUrl); + resource.setClientId("my-trusted-client"); + return resource; + } + +} diff --git a/tests/annotation/jdbc/src/main/resources/application.yml b/tests/annotation/jdbc/src/main/resources/application.yml new file mode 100644 index 000000000..c2b03892c --- /dev/null +++ b/tests/annotation/jdbc/src/main/resources/application.yml @@ -0,0 +1,15 @@ +spring: + application: + name: jdbc +management: + context_path: /admin +security: + user: + password: password + +--- + +spring: + profiles: client +server: + port: 8081 \ No newline at end of file diff --git a/tests/annotation/jdbc/src/main/resources/schema.sql b/tests/annotation/jdbc/src/main/resources/schema.sql new file mode 100644 index 000000000..5ffe631a8 --- /dev/null +++ b/tests/annotation/jdbc/src/main/resources/schema.sql @@ -0,0 +1,53 @@ +create table users ( + username varchar(256), + password varchar(256), + enabled boolean +); + +create table authorities ( + username varchar(256), + authority varchar(256) +); + +create table oauth_client_details ( + client_id VARCHAR(256) PRIMARY KEY, + resource_ids VARCHAR(256), + client_secret VARCHAR(256), + scope VARCHAR(256), + authorized_grant_types VARCHAR(256), + web_server_redirect_uri VARCHAR(256), + authorities VARCHAR(256), + access_token_validity INTEGER, + refresh_token_validity INTEGER, + additional_information VARCHAR(4096), + autoapprove VARCHAR(256) +); + +create table oauth_client_token ( + token_id VARCHAR(256), + token LONGVARBINARY, + authentication_id VARCHAR(256), + user_name VARCHAR(256), + client_id VARCHAR(256) +); + +create table oauth_access_token ( + token_id VARCHAR(256), + token LONGVARBINARY, + authentication_id VARCHAR(256), + user_name VARCHAR(256), + client_id VARCHAR(256), + authentication LONGVARBINARY, + refresh_token VARCHAR(256) +); + +create table oauth_refresh_token ( + token_id VARCHAR(256), + token LONGVARBINARY, + authentication LONGVARBINARY +); + +create table oauth_code ( + code VARCHAR(256), authentication LONGVARBINARY +); + diff --git a/tests/annotation/jdbc/src/test/java/demo/AdHocTests.java b/tests/annotation/jdbc/src/test/java/demo/AdHocTests.java new file mode 100644 index 000000000..a7d0087ca --- /dev/null +++ b/tests/annotation/jdbc/src/test/java/demo/AdHocTests.java @@ -0,0 +1,39 @@ +/* + * Copyright 20013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package demo; + +import org.junit.Ignore; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +/** + * @author Dave Syer + * + */ +@RunWith(Suite.class) +// @formatter:off +@SuiteClasses({ + AuthorizationCodeProviderTests.class, + RefreshTokenSupportTests.class, + ClientCredentialsProviderTests.class, + ApplicationTests.class, + ProtectedResourceTests.class, + ImplicitProviderTests.class, + ResourceOwnerPasswordProviderTests.class }) +// @formatter:on +@Ignore("Test suite for tracking order dependencies") +public class AdHocTests { + +} diff --git a/tests/annotation/jdbc/src/test/java/demo/ApplicationTests.java b/tests/annotation/jdbc/src/test/java/demo/ApplicationTests.java new file mode 100644 index 000000000..055467fe5 --- /dev/null +++ b/tests/annotation/jdbc/src/test/java/demo/ApplicationTests.java @@ -0,0 +1,29 @@ +package demo; + +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.SpringApplicationConfiguration; +import org.springframework.security.oauth2.provider.token.TokenStore; +import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = Application.class) +@WebAppConfiguration +@ActiveProfiles("test") +public class ApplicationTests { + + @Autowired + private TokenStore tokenStore; + + @Test + public void contextLoads() { + assertTrue("Wrong token store type: " + tokenStore, tokenStore instanceof JdbcTokenStore); + } + +} diff --git a/tests/annotation/jdbc/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/jdbc/src/test/java/demo/AuthorizationCodeProviderTests.java new file mode 100755 index 000000000..8c4082abd --- /dev/null +++ b/tests/annotation/jdbc/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -0,0 +1,33 @@ +/* + * Copyright 2006-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 demo; + +import static org.junit.Assert.assertFalse; +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) { + assertTrue(page.contains("action='http://github.com/oauth/authorize'")); + assertTrue(page.contains(" + + + + + + + diff --git a/tests/annotation/jwt/src/test/java/demo/ApplicationTests.java b/tests/annotation/jwt/src/test/java/demo/ApplicationTests.java new file mode 100644 index 000000000..b6abb23ed --- /dev/null +++ b/tests/annotation/jwt/src/test/java/demo/ApplicationTests.java @@ -0,0 +1,29 @@ +package demo; + +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.SpringApplicationConfiguration; +import org.springframework.security.oauth2.provider.token.TokenStore; +import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = Application.class) +@WebAppConfiguration +@ActiveProfiles("test") +public class ApplicationTests { + + @Autowired + private TokenStore tokenStore; + + @Test + public void contextLoads() { + assertTrue("Wrong token store type: " + tokenStore, tokenStore instanceof JwtTokenStore); + } + +} diff --git a/tests/annotation/jwt/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/jwt/src/test/java/demo/AuthorizationCodeProviderTests.java new file mode 100755 index 000000000..632098bf1 --- /dev/null +++ b/tests/annotation/jwt/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -0,0 +1,25 @@ +/* + * Copyright 2006-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 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 new file mode 100644 index 000000000..f26763279 --- /dev/null +++ b/tests/annotation/jwt/src/test/java/demo/ClientCredentialsProviderTests.java @@ -0,0 +1,60 @@ +package demo; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Map; + +import org.junit.Test; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.boot.test.TestRestTemplate; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.provider.token.AccessTokenConverter; + +import sparklr.common.AbstractClientCredentialsProviderTests; + +/** + * @author Dave Syer + */ +@SpringApplicationConfiguration(classes = Application.class) +public class ClientCredentialsProviderTests extends AbstractClientCredentialsProviderTests { + + /** + * tests the check_token endpoint + */ + @Test + @OAuth2ContextConfiguration(ClientCredentials.class) + public void testCheckToken() throws Exception { + OAuth2AccessToken token = context.getAccessToken(); + HttpHeaders headers = new HttpHeaders(); + headers.set("Content-Type", MediaType.APPLICATION_FORM_URLENCODED_VALUE); + @SuppressWarnings("rawtypes") + ResponseEntity response = new TestRestTemplate("my-client-with-secret", "secret").exchange(http + .getUrl(checkTokenPath()), HttpMethod.POST, + new HttpEntity("token=" + token.getValue(), headers), Map.class); + assertEquals(HttpStatus.OK, response.getStatusCode()); + @SuppressWarnings("unchecked") + Map map = (Map) response.getBody(); + assertTrue(map.containsKey(AccessTokenConverter.EXP)); + assertEquals("my-client-with-secret", map.get(AccessTokenConverter.CLIENT_ID)); + } + + @Test + public void testTokenKey() throws Exception { + @SuppressWarnings("rawtypes") + ResponseEntity response = new TestRestTemplate("my-client-with-secret", "secret").getForEntity( + http.getUrl(tokenKeyPath()), Map.class); + assertEquals(HttpStatus.OK, response.getStatusCode()); + @SuppressWarnings("unchecked") + Map map = (Map) response.getBody(); + assertTrue(map.containsKey("alg")); + } + +} diff --git a/tests/annotation/jwt/src/test/java/demo/ImplicitProviderTests.java b/tests/annotation/jwt/src/test/java/demo/ImplicitProviderTests.java new file mode 100644 index 000000000..7a8958187 --- /dev/null +++ b/tests/annotation/jwt/src/test/java/demo/ImplicitProviderTests.java @@ -0,0 +1,13 @@ +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 new file mode 100644 index 000000000..c752cbe12 --- /dev/null +++ b/tests/annotation/jwt/src/test/java/demo/ProtectedResourceTests.java @@ -0,0 +1,27 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package 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 new file mode 100644 index 000000000..a5a4eb9ee --- /dev/null +++ b/tests/annotation/jwt/src/test/java/demo/RefreshTokenSupportTests.java @@ -0,0 +1,23 @@ +package demo; + +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.http.HttpStatus; +import org.springframework.security.oauth2.common.OAuth2AccessToken; + +import sparklr.common.AbstractRefreshTokenSupportTests; + +/** + * @author Ryan Heaton + * @author Dave Syer + */ +@SpringApplicationConfiguration(classes=Application.class) +public class RefreshTokenSupportTests extends AbstractRefreshTokenSupportTests { + + protected void verifyAccessTokens(OAuth2AccessToken oldAccessToken, OAuth2AccessToken newAccessToken) { + // make sure the new access token can be used. + verifyTokenResponse(newAccessToken.getValue(), HttpStatus.OK); + // the old access token is still valid because there is no state on the server. + verifyTokenResponse(oldAccessToken.getValue(), HttpStatus.OK); + } + +} diff --git a/tests/annotation/jwt/src/test/java/demo/ResourceOwnerPasswordProviderTests.java b/tests/annotation/jwt/src/test/java/demo/ResourceOwnerPasswordProviderTests.java new file mode 100644 index 000000000..d233098a2 --- /dev/null +++ b/tests/annotation/jwt/src/test/java/demo/ResourceOwnerPasswordProviderTests.java @@ -0,0 +1,48 @@ +package demo; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Map; + +import org.junit.Test; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.boot.test.TestRestTemplate; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.provider.token.AccessTokenConverter; +import org.springframework.security.oauth2.provider.token.UserAuthenticationConverter; + +import sparklr.common.AbstractResourceOwnerPasswordProviderTests; + +/** + * @author Dave Syer + */ +@SpringApplicationConfiguration(classes=Application.class) +public class ResourceOwnerPasswordProviderTests extends AbstractResourceOwnerPasswordProviderTests { + + @Test + @OAuth2ContextConfiguration(ResourceOwner.class) + public void testCheckToken() throws Exception { + OAuth2AccessToken token = context.getAccessToken(); + HttpHeaders headers = new HttpHeaders(); + headers.set("Content-Type", MediaType.APPLICATION_FORM_URLENCODED_VALUE); + @SuppressWarnings("rawtypes") + ResponseEntity response = new TestRestTemplate("my-client-with-secret", "secret").exchange(http + .getUrl(checkTokenPath()), HttpMethod.POST, new HttpEntity("token=" + token.getValue(), + headers), Map.class); + assertEquals(HttpStatus.OK, response.getStatusCode()); + @SuppressWarnings("unchecked") + Map map = (Map) response.getBody(); + assertTrue(map.containsKey(AccessTokenConverter.EXP)); + assertTrue(map.containsKey(UserAuthenticationConverter.USERNAME)); + assertEquals("my-trusted-client", map.get(AccessTokenConverter.CLIENT_ID)); + } + +} diff --git a/tests/annotation/jwt/src/test/resources/test.properties b/tests/annotation/jwt/src/test/resources/test.properties new file mode 100644 index 000000000..24466e50d --- /dev/null +++ b/tests/annotation/jwt/src/test/resources/test.properties @@ -0,0 +1 @@ +server.port: 0 \ No newline at end of file diff --git a/tests/annotation/mappings/README.md b/tests/annotation/mappings/README.md new file mode 100644 index 000000000..c0392f6b0 --- /dev/null +++ b/tests/annotation/mappings/README.md @@ -0,0 +1,16 @@ +This project shows what you can do with the minimum configuration to +set up an Authorization Server and Resource Server with different +endpoint paths than the defaults. + +For the Authorization Server, in addition to the basic "vanilla" +features, we add mappings from "/oauth/token" to "/token" for +instance. The target values for the mappings are injected using +`@Value`, largely to make it easier to test them. You can see this is +the bulk of `Application.java`. + +For the Resource Server, in this app we change the default protected +resource patterns to "/" and "/admin/beans". The rest of the app is +protected by HTTP Basic security by default because of the Spring Boot +autoconfiguration features (this is verified in a test case +`ProtectedResourceTests`). We also add an access rule (scope='read' is +required to access both OAuth2 resources). diff --git a/tests/annotation/mappings/pom.xml b/tests/annotation/mappings/pom.xml new file mode 100644 index 000000000..7a66dde14 --- /dev/null +++ b/tests/annotation/mappings/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + + spring-oauth2-tests-mappings + + spring-oauth2-tests-mappings + Demo project + + + org.demo + spring-oauth2-tests-parent + 2.0.2.RELEASE + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.security.oauth + spring-security-oauth2 + + + org.demo + spring-oauth2-tests-common + ${project.version} + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/tests/annotation/mappings/src/main/java/demo/Application.java b/tests/annotation/mappings/src/main/java/demo/Application.java new file mode 100644 index 000000000..d0821d2d3 --- /dev/null +++ b/tests/annotation/mappings/src/main/java/demo/Application.java @@ -0,0 +1,128 @@ +package demo; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; +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.config.annotation.web.configuration.ResourceServerConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Configuration +@ComponentScan +@EnableAutoConfiguration +@RestController +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + @RequestMapping("/") + public String home() { + return "Hello World"; + } + + @Configuration + @EnableResourceServer + protected static class ResourceServer extends ResourceServerConfigurerAdapter { + + @Override + public void configure(HttpSecurity http) throws Exception { + // @formatter:off + http + // Just for laughs, apply OAuth protection to only 2 resources + .requestMatchers().antMatchers("/","/admin/beans") + .and() + .authorizeRequests() + .anyRequest().access("#oauth2.hasScope('read')"); + // @formatter:on + } + + @Override + public void configure(ResourceServerSecurityConfigurer resources) throws Exception { + resources.resourceId("sparklr"); + } + + } + + @Configuration + @EnableAuthorizationServer + protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter { + + @Value("${oauth.paths.token:/oauth/authorize}") + private String tokenPath = "/oauth/token"; + + @Value("${oauth.paths.token_key:/oauth/token_key}") + private String tokenKeyPath = "/oauth/token_key"; + + @Value("${oauth.paths.check_token:/oauth/check_token}") + private String checkTokenPath = "/oauth/check_token"; + + @Value("${oauth.paths.authorize:/oauth/authorize}") + private String authorizePath = "/oauth/authorize"; + + @Value("${oauth.paths.confirm:/oauth/confirm_access}") + private String confirmPath = "/oauth/confirm_access"; + + @Autowired + private AuthenticationManager authenticationManager; + + @Override + public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { + oauthServer.checkTokenAccess("hasRole('ROLE_TRUSTED_CLIENT')"); + } + + @Override + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + // @formatter:off + endpoints.authenticationManager(authenticationManager) + .pathMapping("/oauth/confirm_access", confirmPath) + .pathMapping("/oauth/token", tokenPath) + .pathMapping("/oauth/check_token", checkTokenPath) + .pathMapping("/oauth/token_key", tokenKeyPath) + .pathMapping("/oauth/authorize", authorizePath); + // @formatter:on + } + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + // @formatter:off + clients.inMemory() + .withClient("my-trusted-client") + .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit") + .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") + .scopes("read", "write", "trust") + .resourceIds("sparklr") + .accessTokenValiditySeconds(60) + .and() + .withClient("my-client-with-registered-redirect") + .authorizedGrantTypes("authorization_code") + .authorities("ROLE_CLIENT") + .scopes("read", "trust") + .resourceIds("sparklr") + .redirectUris("http://anywhere/?key=value") + .and() + .withClient("my-client-with-secret") + .authorizedGrantTypes("client_credentials", "password") + .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") + .scopes("read") + .resourceIds("sparklr") + .secret("secret"); + // @formatter:on + } + + } + +} diff --git a/tests/annotation/mappings/src/main/resources/application.yml b/tests/annotation/mappings/src/main/resources/application.yml new file mode 100644 index 000000000..b7b8b2e53 --- /dev/null +++ b/tests/annotation/mappings/src/main/resources/application.yml @@ -0,0 +1,15 @@ +spring: + application: + name: mappings +management: + context_path: /admin +security: + user: + password: password + +oauth: + paths: + token: /token + authorize: /authorize + confirm: /approve + check_token: /decode \ No newline at end of file diff --git a/tests/annotation/mappings/src/test/java/demo/ApplicationTests.java b/tests/annotation/mappings/src/test/java/demo/ApplicationTests.java new file mode 100644 index 000000000..8da63b411 --- /dev/null +++ b/tests/annotation/mappings/src/test/java/demo/ApplicationTests.java @@ -0,0 +1,20 @@ +package demo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = Application.class) +@WebAppConfiguration +@ActiveProfiles("test") +public class ApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/tests/annotation/mappings/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/mappings/src/test/java/demo/AuthorizationCodeProviderTests.java new file mode 100755 index 000000000..36e02d25f --- /dev/null +++ b/tests/annotation/mappings/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -0,0 +1,51 @@ +/* + * Copyright 2006-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 demo; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +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; + +import sparklr.common.AbstractAuthorizationCodeProviderTests; + +/** + * @author Dave Syer + */ +@SpringApplicationConfiguration(classes = Application.class) +public class AuthorizationCodeProviderTests extends AbstractAuthorizationCodeProviderTests { + + @Test + @OAuth2ContextConfiguration(resource = MyClientWithRegisteredRedirect.class, initialize = false) + public void testInsufficientScopeInResourceRequest() throws Exception { + AuthorizationCodeResourceDetails resource = (AuthorizationCodeResourceDetails) context.getResource(); + resource.setScope(Arrays.asList("trust")); + approveAccessTokenGrant("http://anywhere/?key=value", true); + assertNotNull(context.getAccessToken()); + try { + http.getForString("/admin/beans"); + fail("Should have thrown exception"); + } + catch (InsufficientScopeException ex) { + assertTrue("Wrong summary: " + ex, ex.getSummary().contains("scope=\"read")); + } + } + +} diff --git a/tests/annotation/mappings/src/test/java/demo/ClientCredentialsProviderTests.java b/tests/annotation/mappings/src/test/java/demo/ClientCredentialsProviderTests.java new file mode 100644 index 000000000..a514345e7 --- /dev/null +++ b/tests/annotation/mappings/src/test/java/demo/ClientCredentialsProviderTests.java @@ -0,0 +1,59 @@ +package demo; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Map; + +import org.junit.Test; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.boot.test.TestRestTemplate; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.provider.token.AccessTokenConverter; + +import sparklr.common.AbstractClientCredentialsProviderTests; + +/** + * @author Dave Syer + */ +@SpringApplicationConfiguration(classes=Application.class) +public class ClientCredentialsProviderTests extends AbstractClientCredentialsProviderTests { + + + /** + * tests the check_token endpoint + */ + @Test + @OAuth2ContextConfiguration(ClientCredentials.class) + public void testCheckToken() throws Exception { + OAuth2AccessToken token = context.getAccessToken(); + HttpHeaders headers = new HttpHeaders(); + headers.set("Content-Type", MediaType.APPLICATION_FORM_URLENCODED_VALUE); + @SuppressWarnings("rawtypes") + ResponseEntity response = new TestRestTemplate("my-client-with-secret", "secret").exchange(http + .getUrl(checkTokenPath()), HttpMethod.POST, + new HttpEntity("token=" + token.getValue(), headers), Map.class); + assertEquals(HttpStatus.OK, response.getStatusCode()); + @SuppressWarnings("unchecked") + Map map = (Map) response.getBody(); + assertTrue(map.containsKey(AccessTokenConverter.EXP)); + assertEquals("my-client-with-secret", map.get(AccessTokenConverter.CLIENT_ID)); + } + + @Test + public void testTokenKey() throws Exception { + @SuppressWarnings("rawtypes") + ResponseEntity response = new TestRestTemplate("my-client-with-secret", "secret").getForEntity( + http.getUrl(tokenKeyPath()), Map.class); + // This app has no token key. + assertEquals(HttpStatus.FORBIDDEN, response.getStatusCode()); + } + +} diff --git a/tests/annotation/mappings/src/test/java/demo/ImplicitProviderTests.java b/tests/annotation/mappings/src/test/java/demo/ImplicitProviderTests.java new file mode 100644 index 000000000..7a8958187 --- /dev/null +++ b/tests/annotation/mappings/src/test/java/demo/ImplicitProviderTests.java @@ -0,0 +1,13 @@ +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 new file mode 100644 index 000000000..743d9158b --- /dev/null +++ b/tests/annotation/mappings/src/test/java/demo/ProtectedResourceTests.java @@ -0,0 +1,41 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package demo; + +import static org.junit.Assert.assertEquals; +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 sparklr.common.AbstractProtectedResourceTests; + +/** + * @author Dave Syer + * + */ +@SpringApplicationConfiguration(classes = Application.class) +public class ProtectedResourceTests extends AbstractProtectedResourceTests { + + @Test + public void testDumpResourceIsProtected() throws Exception { + ResponseEntity response = http.getForString("/admin/dump"); + assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); + assertTrue("Wrong header: " + response.getHeaders(), response.getHeaders().getFirst("WWW-Authenticate") + .startsWith("Basic realm=")); + } + +} diff --git a/tests/annotation/mappings/src/test/java/demo/RefreshTokenSupportTests.java b/tests/annotation/mappings/src/test/java/demo/RefreshTokenSupportTests.java new file mode 100644 index 000000000..4ed370eea --- /dev/null +++ b/tests/annotation/mappings/src/test/java/demo/RefreshTokenSupportTests.java @@ -0,0 +1,13 @@ +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 new file mode 100644 index 000000000..aa5786098 --- /dev/null +++ b/tests/annotation/mappings/src/test/java/demo/ResourceOwnerPasswordProviderTests.java @@ -0,0 +1,13 @@ +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/resources/test.properties b/tests/annotation/mappings/src/test/resources/test.properties new file mode 100644 index 000000000..73bcdecd2 --- /dev/null +++ b/tests/annotation/mappings/src/test/resources/test.properties @@ -0,0 +1 @@ +server.port: 0 diff --git a/tests/annotation/multi/README.md b/tests/annotation/multi/README.md new file mode 100644 index 000000000..b4e89611f --- /dev/null +++ b/tests/annotation/multi/README.md @@ -0,0 +1,9 @@ +This project shows what you can do with the minimum configuration to +set up an Authorization Server and multiple Resource Servers in the +same app. + +For the Resource Server all that is needed is the +`@EnableResourceServer` annotation. By default it protects all +resources that are not explicitly ignored and not exposed by the +`AuthorizationEndpoint` (if there is an Authorization Server in the +same application). diff --git a/tests/annotation/multi/pom.xml b/tests/annotation/multi/pom.xml new file mode 100644 index 000000000..81c3e9feb --- /dev/null +++ b/tests/annotation/multi/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + + sparklr-boot-multi + + sparklr-boot-multi + Demo project + + + org.demo + spring-oauth2-tests-parent + 2.0.2.RELEASE + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.security.oauth + spring-security-oauth2 + + + org.demo + spring-oauth2-tests-common + ${project.version} + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/tests/annotation/multi/src/main/java/demo/Application.java b/tests/annotation/multi/src/main/java/demo/Application.java new file mode 100644 index 000000000..62034d623 --- /dev/null +++ b/tests/annotation/multi/src/main/java/demo/Application.java @@ -0,0 +1,131 @@ +package demo; + +import java.util.Arrays; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +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.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; +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.ResourceServerConfiguration; +import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Configuration +@ComponentScan +@EnableAutoConfiguration +@RestController +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + @RequestMapping("/") + public String home() { + return "Hello World"; + } + + protected static class AdminResourceServerConfiguration extends ResourceServerConfiguration { + // Empty class because Spring Security hashes configurers against their concrete type and we need two the same + } + + @Bean + protected AdminResourceServerConfiguration adminResources() { + + AdminResourceServerConfiguration resource = new AdminResourceServerConfiguration(); + + resource.setConfigurers(Arrays. asList(new ResourceServerConfigurerAdapter() { + + @Override + public void configure(ResourceServerSecurityConfigurer resources) throws Exception { + resources.resourceId("oauth2/admin"); + } + + @Override + public void configure(HttpSecurity http) throws Exception { + http.requestMatchers().antMatchers("/admin/**").and().authorizeRequests().anyRequest() + .access("#oauth2.hasScope('read')"); + } + + })); + + return resource; + + } + + @Bean + protected ResourceServerConfiguration otherResources() { + + ResourceServerConfiguration resource = new ResourceServerConfiguration(); + + resource.setConfigurers(Arrays. asList(new ResourceServerConfigurerAdapter() { + + @Override + public void configure(ResourceServerSecurityConfigurer resources) throws Exception { + resources.resourceId("oauth2/other"); + } + + @Override + public void configure(HttpSecurity http) throws Exception { + http.authorizeRequests().anyRequest().access("#oauth2.hasScope('trust')"); + } + })); + resource.setOrder(4); + + return resource; + + } + + @Configuration + @EnableAuthorizationServer + protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter { + + @Autowired + private AuthenticationManager authenticationManager; + + @Override + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + endpoints.authenticationManager(authenticationManager); + } + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + // @formatter:off + clients.inMemory() + .withClient("my-trusted-client") + .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit") + .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") + .scopes("read", "write", "trust") + .resourceIds("oauth2/admin") + .accessTokenValiditySeconds(60) + .and() + .withClient("my-client-with-registered-redirect") + .authorizedGrantTypes("authorization_code") + .authorities("ROLE_CLIENT") + .scopes("read", "trust") + .resourceIds("oauth2/admin") + .redirectUris("http://anywhere/?key=value") + .and() + .withClient("my-client-with-secret") + .authorizedGrantTypes("client_credentials", "password") + .authorities("ROLE_CLIENT") + .scopes("read") + .resourceIds("oauth2/other") + .secret("secret"); + // @formatter:on + } + + } + +} diff --git a/tests/annotation/multi/src/main/resources/application.yml b/tests/annotation/multi/src/main/resources/application.yml new file mode 100644 index 000000000..a9c0149f0 --- /dev/null +++ b/tests/annotation/multi/src/main/resources/application.yml @@ -0,0 +1,8 @@ +spring: + application: + name: vanilla +management: + context_path: /admin +security: + user: + password: password diff --git a/tests/annotation/multi/src/test/java/demo/ApplicationTests.java b/tests/annotation/multi/src/test/java/demo/ApplicationTests.java new file mode 100644 index 000000000..8da63b411 --- /dev/null +++ b/tests/annotation/multi/src/test/java/demo/ApplicationTests.java @@ -0,0 +1,20 @@ +package demo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = Application.class) +@WebAppConfiguration +@ActiveProfiles("test") +public class ApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/tests/annotation/multi/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/multi/src/test/java/demo/AuthorizationCodeProviderTests.java new file mode 100755 index 000000000..632098bf1 --- /dev/null +++ b/tests/annotation/multi/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -0,0 +1,25 @@ +/* + * Copyright 2006-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 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 new file mode 100644 index 000000000..af8190074 --- /dev/null +++ b/tests/annotation/multi/src/test/java/demo/ClientCredentialsProviderTests.java @@ -0,0 +1,14 @@ +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 new file mode 100644 index 000000000..7a8958187 --- /dev/null +++ b/tests/annotation/multi/src/test/java/demo/ImplicitProviderTests.java @@ -0,0 +1,13 @@ +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 new file mode 100644 index 000000000..aa30f20f6 --- /dev/null +++ b/tests/annotation/multi/src/test/java/demo/ProtectedResourceTests.java @@ -0,0 +1,49 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package demo; + +import static org.junit.Assert.assertEquals; +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 sparklr.common.AbstractProtectedResourceTests; + +/** + * @author Dave Syer + * + */ +@SpringApplicationConfiguration(classes = Application.class) +public class ProtectedResourceTests extends AbstractProtectedResourceTests { + + @Test + public void testHomePageHasOtherRealm() throws Exception { + ResponseEntity response = http.getForString("/"); + assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); + assertTrue("Wrong header: " + response.getHeaders(), response.getHeaders().getFirst("WWW-Authenticate") + .startsWith("Bearer realm=\"oauth2/other\"")); + } + + @Test + public void testAdminEndpointHasAdminRealm() throws Exception { + ResponseEntity response = http.getForString("/admin/beans"); + assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); + assertTrue("Wrong header: " + response.getHeaders(), response.getHeaders().getFirst("WWW-Authenticate") + .startsWith("Bearer realm=\"oauth2/admin\"")); + } + +} diff --git a/tests/annotation/multi/src/test/java/demo/RefreshTokenSupportTests.java b/tests/annotation/multi/src/test/java/demo/RefreshTokenSupportTests.java new file mode 100644 index 000000000..4ed370eea --- /dev/null +++ b/tests/annotation/multi/src/test/java/demo/RefreshTokenSupportTests.java @@ -0,0 +1,13 @@ +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 new file mode 100644 index 000000000..aa5786098 --- /dev/null +++ b/tests/annotation/multi/src/test/java/demo/ResourceOwnerPasswordProviderTests.java @@ -0,0 +1,13 @@ +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/multi/src/test/resources/test.properties b/tests/annotation/multi/src/test/resources/test.properties new file mode 100644 index 000000000..24466e50d --- /dev/null +++ b/tests/annotation/multi/src/test/resources/test.properties @@ -0,0 +1 @@ +server.port: 0 \ No newline at end of file diff --git a/tests/annotation/pom.xml b/tests/annotation/pom.xml new file mode 100644 index 000000000..9043c5948 --- /dev/null +++ b/tests/annotation/pom.xml @@ -0,0 +1,132 @@ + + + 4.0.0 + + org.demo + spring-oauth2-tests-parent + 2.0.2.RELEASE + pom + + + common + vanilla + mappings + form + jwt + approval + jdbc + multi + client + resource + + + spring-oauth2-tests + Demo project for OAuth2 and Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 1.1.0.RELEASE + + + + + + org.springframework.security.oauth + spring-security-oauth2 + 2.0.2.RELEASE + + + jackson-mapper-asl + org.codehaus.jackson + + + + + org.springframework.security + spring-security-jwt + 1.0.1.RELEASE + + + + + + + + + maven-surefire-plugin + + + **/*Tests.java + + + **/Abstract*.java + + + file:/dev/./urandom + true + + -Xmx1024m -XX:MaxPermSize=256m + + + + + maven-deploy-plugin + + true + + + + + + + + demo.Application + 1.7 + + + + + spring-snapshots + Spring Snapshots + http://repo.spring.io/libs-snapshot-local + + true + + + + spring-milestones + Spring Milestones + http://repo.spring.io/libs-milestone-local + + false + + + + spring-staging + Spring Milestones + http://repo.spring.io/libs-staging-local + + false + + + + + + spring-snapshots + Spring Snapshots + http://repo.spring.io/libs-snapshot-local + + true + + + + spring-staging + Spring Milestones + http://repo.spring.io/libs-staging-local + + false + + + + diff --git a/tests/annotation/resource/README.md b/tests/annotation/resource/README.md new file mode 100644 index 000000000..acb89fbf6 --- /dev/null +++ b/tests/annotation/resource/README.md @@ -0,0 +1,18 @@ +This project shows what you can do with the minimum configuration to +set up an Authorization Server and Resource Server. + +For the Authorization Server you need to `@EnableAuthorizationServer` +and also configure at least one client registration +(`OAuth2ClientDetails`). You can see this is the bulk of +`Application.java`. + +An `AuthenticationManager` is created by Spring Boot (it has a single +user, named "user", with password "password", per +`application.yml`). It is needed in the Authorization Server to +provide authentication for the Resource Owner Password grant type. + +For the Resource Server all that is needed is the +`@EnableResourceServer` annotation. By default it protects all +resources that are not explicitly ignored and not exposed by the +`AuthorizationEndpoint` (if there is an Authorization Server in the +same application). diff --git a/tests/annotation/resource/pom.xml b/tests/annotation/resource/pom.xml new file mode 100644 index 000000000..ea7f66f2c --- /dev/null +++ b/tests/annotation/resource/pom.xml @@ -0,0 +1,54 @@ + + + 4.0.0 + + spring-oauth2-tests-resource + + spring-oauth2-tests-resource + Demo project + + + org.demo + spring-oauth2-tests-parent + 2.0.2.RELEASE + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.security.oauth + spring-security-oauth2 + + + org.springframework.security + spring-security-jwt + + + org.demo + spring-oauth2-tests-common + ${project.version} + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/tests/annotation/resource/src/main/java/demo/Application.java b/tests/annotation/resource/src/main/java/demo/Application.java new file mode 100644 index 000000000..2758734b1 --- /dev/null +++ b/tests/annotation/resource/src/main/java/demo/Application.java @@ -0,0 +1,38 @@ +package demo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +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 +@EnableResourceServer +@RestController +public class Application { + + @Bean + public JwtTokenStore tokenStore() throws Exception { + JwtAccessTokenConverter enhancer = new JwtAccessTokenConverter(); + // N.B. in a real system you would have to configure the verifierKey (or use JdbcTokenStore) + enhancer.afterPropertiesSet(); + return new JwtTokenStore(enhancer); + } + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + @RequestMapping("/") + public String home() { + return "Hello World"; + } + +} diff --git a/tests/annotation/resource/src/main/resources/application.yml b/tests/annotation/resource/src/main/resources/application.yml new file mode 100644 index 000000000..a9c0149f0 --- /dev/null +++ b/tests/annotation/resource/src/main/resources/application.yml @@ -0,0 +1,8 @@ +spring: + application: + name: vanilla +management: + context_path: /admin +security: + user: + password: password diff --git a/tests/annotation/resource/src/main/resources/logback.xml b/tests/annotation/resource/src/main/resources/logback.xml new file mode 100644 index 000000000..f33dc9241 --- /dev/null +++ b/tests/annotation/resource/src/main/resources/logback.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tests/annotation/resource/src/test/java/demo/ApplicationTests.java b/tests/annotation/resource/src/test/java/demo/ApplicationTests.java new file mode 100644 index 000000000..8da63b411 --- /dev/null +++ b/tests/annotation/resource/src/test/java/demo/ApplicationTests.java @@ -0,0 +1,20 @@ +package demo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = Application.class) +@WebAppConfiguration +@ActiveProfiles("test") +public class ApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/tests/annotation/resource/src/test/java/demo/ProtectedResourceTests.java b/tests/annotation/resource/src/test/java/demo/ProtectedResourceTests.java new file mode 100644 index 000000000..c752cbe12 --- /dev/null +++ b/tests/annotation/resource/src/test/java/demo/ProtectedResourceTests.java @@ -0,0 +1,27 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package 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/resource/src/test/resources/test.properties b/tests/annotation/resource/src/test/resources/test.properties new file mode 100644 index 000000000..24466e50d --- /dev/null +++ b/tests/annotation/resource/src/test/resources/test.properties @@ -0,0 +1 @@ +server.port: 0 \ No newline at end of file diff --git a/tests/annotation/vanilla/README.md b/tests/annotation/vanilla/README.md new file mode 100644 index 000000000..acb89fbf6 --- /dev/null +++ b/tests/annotation/vanilla/README.md @@ -0,0 +1,18 @@ +This project shows what you can do with the minimum configuration to +set up an Authorization Server and Resource Server. + +For the Authorization Server you need to `@EnableAuthorizationServer` +and also configure at least one client registration +(`OAuth2ClientDetails`). You can see this is the bulk of +`Application.java`. + +An `AuthenticationManager` is created by Spring Boot (it has a single +user, named "user", with password "password", per +`application.yml`). It is needed in the Authorization Server to +provide authentication for the Resource Owner Password grant type. + +For the Resource Server all that is needed is the +`@EnableResourceServer` annotation. By default it protects all +resources that are not explicitly ignored and not exposed by the +`AuthorizationEndpoint` (if there is an Authorization Server in the +same application). diff --git a/tests/annotation/vanilla/pom.xml b/tests/annotation/vanilla/pom.xml new file mode 100644 index 000000000..d5eaf3e2e --- /dev/null +++ b/tests/annotation/vanilla/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + + spring-oauth2-tests-vanilla + + spring-oauth2-tests-vanilla + Demo project + + + org.demo + spring-oauth2-tests-parent + 2.0.2.RELEASE + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.security.oauth + spring-security-oauth2 + + + org.demo + spring-oauth2-tests-common + ${project.version} + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/tests/annotation/vanilla/src/main/java/demo/Application.java b/tests/annotation/vanilla/src/main/java/demo/Application.java new file mode 100644 index 000000000..94559d110 --- /dev/null +++ b/tests/annotation/vanilla/src/main/java/demo/Application.java @@ -0,0 +1,74 @@ +package demo; + +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.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; +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.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Configuration +@ComponentScan +@EnableAutoConfiguration +@EnableResourceServer +@RestController +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + @RequestMapping("/") + public String home() { + return "Hello World"; + } + + @Configuration + @EnableAuthorizationServer + protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter { + + @Autowired + private AuthenticationManager authenticationManager; + + @Override + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + endpoints.authenticationManager(authenticationManager); + } + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + // @formatter:off + clients.inMemory() + .withClient("my-trusted-client") + .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit") + .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") + .scopes("read", "write", "trust") + .resourceIds("oauth2-resource") + .accessTokenValiditySeconds(60) + .and() + .withClient("my-client-with-registered-redirect") + .authorizedGrantTypes("authorization_code") + .authorities("ROLE_CLIENT") + .scopes("read", "trust") + .resourceIds("oauth2-resource") + .redirectUris("http://anywhere/?key=value") + .and() + .withClient("my-client-with-secret") + .authorizedGrantTypes("client_credentials", "password") + .authorities("ROLE_CLIENT") + .scopes("read") + .resourceIds("oauth2-resource") + .secret("secret"); + // @formatter:on + } + + } + +} diff --git a/tests/annotation/vanilla/src/main/resources/application.yml b/tests/annotation/vanilla/src/main/resources/application.yml new file mode 100644 index 000000000..a9c0149f0 --- /dev/null +++ b/tests/annotation/vanilla/src/main/resources/application.yml @@ -0,0 +1,8 @@ +spring: + application: + name: vanilla +management: + context_path: /admin +security: + user: + password: password diff --git a/tests/annotation/vanilla/src/test/java/demo/ApplicationTests.java b/tests/annotation/vanilla/src/test/java/demo/ApplicationTests.java new file mode 100644 index 000000000..8da63b411 --- /dev/null +++ b/tests/annotation/vanilla/src/test/java/demo/ApplicationTests.java @@ -0,0 +1,20 @@ +package demo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = Application.class) +@WebAppConfiguration +@ActiveProfiles("test") +public class ApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java new file mode 100755 index 000000000..632098bf1 --- /dev/null +++ b/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -0,0 +1,25 @@ +/* + * Copyright 2006-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 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/vanilla/src/test/java/demo/ClientCredentialsProviderTests.java b/tests/annotation/vanilla/src/test/java/demo/ClientCredentialsProviderTests.java new file mode 100644 index 000000000..af8190074 --- /dev/null +++ b/tests/annotation/vanilla/src/test/java/demo/ClientCredentialsProviderTests.java @@ -0,0 +1,14 @@ +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/ImplicitProviderTests.java b/tests/annotation/vanilla/src/test/java/demo/ImplicitProviderTests.java new file mode 100644 index 000000000..cd17d9a0f --- /dev/null +++ b/tests/annotation/vanilla/src/test/java/demo/ImplicitProviderTests.java @@ -0,0 +1,76 @@ +package demo; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +import org.junit.Test; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.boot.test.TestRestTemplate; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration; +import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordResourceDetails; + +import sparklr.common.AbstractImplicitProviderTests; + +/** + * @author Dave Syer + */ +@SpringApplicationConfiguration(classes = Application.class) +public class ImplicitProviderTests extends AbstractImplicitProviderTests { + + @Test + @OAuth2ContextConfiguration(ResourceOwner.class) + public void parallelGrants() throws Exception { + getToken(); + Collection> futures = new HashSet>(); + ExecutorService pool = Executors.newFixedThreadPool(10); + for (int i = 0; i < 100; i++) { + futures.add(pool.submit(new Runnable() { + @Override + public void run() { + getToken(); + } + })); + } + for (Future future : futures) { + future.get(); + } + } + + private void getToken() { + Map form = new LinkedHashMap(); + form.put("client_id", "my-trusted-client"); + form.put("redirect_uri", "http://foo.com/"); + form.put("response_type", "token"); + form.put("scope", "read"); + ResponseEntity response = new TestRestTemplate("user", "password") + .getForEntity( + http.getUrl("/oauth/authorize?client_id={client_id}&redirect_uri={redirect_uri}&response_type={response_type}&scope={scope}"), + Void.class, form); + assertEquals(HttpStatus.FOUND, response.getStatusCode()); + assertTrue(response.getHeaders().getLocation().toString().contains("access_token")); + } + + protected static class ResourceOwner extends ResourceOwnerPasswordResourceDetails { + public ResourceOwner(Object target) { + setClientId("my-trusted-client"); + setScope(Arrays.asList("read")); + setId(getClientId()); + setUsername("user"); + setPassword("password"); + AbstractImplicitProviderTests test = (AbstractImplicitProviderTests) target; + setAccessTokenUri(test.http.getUrl(tokenPath())); + } + } + +} diff --git a/tests/annotation/vanilla/src/test/java/demo/ProtectedResourceTests.java b/tests/annotation/vanilla/src/test/java/demo/ProtectedResourceTests.java new file mode 100644 index 000000000..c752cbe12 --- /dev/null +++ b/tests/annotation/vanilla/src/test/java/demo/ProtectedResourceTests.java @@ -0,0 +1,27 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package 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 new file mode 100644 index 000000000..4ed370eea --- /dev/null +++ b/tests/annotation/vanilla/src/test/java/demo/RefreshTokenSupportTests.java @@ -0,0 +1,13 @@ +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 new file mode 100644 index 000000000..aa5786098 --- /dev/null +++ b/tests/annotation/vanilla/src/test/java/demo/ResourceOwnerPasswordProviderTests.java @@ -0,0 +1,13 @@ +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/vanilla/src/test/resources/test.properties b/tests/annotation/vanilla/src/test/resources/test.properties new file mode 100644 index 000000000..24466e50d --- /dev/null +++ b/tests/annotation/vanilla/src/test/resources/test.properties @@ -0,0 +1 @@ +server.port: 0 \ No newline at end of file diff --git a/tests/pom.xml b/tests/pom.xml new file mode 100644 index 000000000..f0a503e1d --- /dev/null +++ b/tests/pom.xml @@ -0,0 +1,44 @@ + + 4.0.0 + + + org.springframework.security.oauth + spring-security-oauth-parent + 2.0.2.RELEASE + + + spring-security-oauth-tests + OAuth for Spring Security - Integration Tests + Test Projects for OAuth Support for Spring Security + pom + + + annotation + xml + + + https://github.com/spring-projects/spring-security-oauth/tests + + + + + + maven-deploy-plugin + 2.6 + + true + + + + + + + + + static.springframework.org + scp://static.springframework.org/var/www/domains/springframework.org/static/htdocs/spring-security/oauth/tests + + + + + diff --git a/tests/xml/README.md b/tests/xml/README.md new file mode 100644 index 000000000..5afaf63dd --- /dev/null +++ b/tests/xml/README.md @@ -0,0 +1,64 @@ +This project is for integration testing the XML configuration features +of +[Spring OAuth2](https://github.com/spring-projects/spring-security-oauth). +They use a mixture of Java (`@Configuration`) and XML to configure +OAuth clients and servers, but only using XML for the Spring OAuth +bits. Since Spring Security cannot be used with a mixture of +`@Configuration` and XML this is probably not the nicest way to do +things (pure XML or pure Java would probably be better). Pure Java +versions of the same apps can be found +[here](https://github.com/dsyer/spring-oauth-integration-tests). + +## Building and Running + +You need Java (1.7 or better) and Maven (3.0.5 or better): + +``` +$ mvn test +... + +``` + +Each app can be launched from the `main()` method in +`Application.java`, either from an IDE, or from the command line using +`mvn spring-boot:run`. Or you can build an executable JAR and run +that: + +``` +$ cd vanilla +$ mvn package +$ java -jar target/*.jar +... + +``` + +Tests run using the full HTTP protocol against an embedded server on a +random port chosen by the operating system (so it should work +everywhere). In contrast, when the app runs from the `main()` method, +it listens on port 8080 by default. + +Here are some curl commands to use to get started: + +``` +$ curl -H "Accept: application/json" my-client-with-secret:secret@localhost:8080/oauth/token -d grant_type=client_credentials +{... "access_token": "b561ff06-4259-466e-92d8-781db1a51901", ...} +$ TOKEN=b561ff06-4259-466e-92d8-781db1a5190 +$ curl -H "Authorization: Bearer $TOKEN" localhost:8080/ +Hello World +``` + +## Running the Client App + +To test in a browser you can run one of the servers (see above) and +the client on a different port (it runs on 8081 by default). + +``` +$ cd client +$ mvn package +$ java -jar target/*.jar +... + +``` + +Go to http://localhost:8081/client and follow the authorization process (the +username and password are `user` and `password`). diff --git a/tests/xml/approval/README.md b/tests/xml/approval/README.md new file mode 100644 index 000000000..acb89fbf6 --- /dev/null +++ b/tests/xml/approval/README.md @@ -0,0 +1,18 @@ +This project shows what you can do with the minimum configuration to +set up an Authorization Server and Resource Server. + +For the Authorization Server you need to `@EnableAuthorizationServer` +and also configure at least one client registration +(`OAuth2ClientDetails`). You can see this is the bulk of +`Application.java`. + +An `AuthenticationManager` is created by Spring Boot (it has a single +user, named "user", with password "password", per +`application.yml`). It is needed in the Authorization Server to +provide authentication for the Resource Owner Password grant type. + +For the Resource Server all that is needed is the +`@EnableResourceServer` annotation. By default it protects all +resources that are not explicitly ignored and not exposed by the +`AuthorizationEndpoint` (if there is an Authorization Server in the +same application). diff --git a/tests/xml/approval/pom.xml b/tests/xml/approval/pom.xml new file mode 100644 index 000000000..2145afa1b --- /dev/null +++ b/tests/xml/approval/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + + spring-oauth2-tests-xml-approval + + spring-oauth2-tests-xml-approval + Demo project + + + org.demo + spring-oauth2-tests-xml-parent + 2.0.2.RELEASE + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.security.oauth + spring-security-oauth2 + + + org.demo + spring-oauth2-tests-xml-common + ${project.version} + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/tests/xml/approval/src/main/java/demo/Application.java b/tests/xml/approval/src/main/java/demo/Application.java new file mode 100644 index 000000000..21372fc31 --- /dev/null +++ b/tests/xml/approval/src/main/java/demo/Application.java @@ -0,0 +1,191 @@ +package demo; + +import javax.servlet.Filter; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.context.embedded.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ImportResource; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; +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.client.ClientDetailsUserDetailsService; +import org.springframework.security.oauth2.provider.endpoint.WhitelabelApprovalEndpoint; +import org.springframework.security.oauth2.provider.endpoint.WhitelabelErrorEndpoint; +import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; +import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint; +import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler; +import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory; +import org.springframework.security.oauth2.provider.token.DefaultTokenServices; +import org.springframework.security.oauth2.provider.token.TokenStore; +import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.access.AccessDeniedHandler; +import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.util.matcher.NegatedRequestMatcher; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Configuration +@ComponentScan +@EnableAutoConfiguration +@RestController +@ImportResource("classpath:/application.xml") +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + @RequestMapping("/") + public String home() { + return "Hello World"; + } + + @Configuration + protected static class OAuth2Config { + + @Autowired + private OAuth2RequestFactory requestFactory; + + @Autowired + private ClientDetailsService clientDetailsService; + + @Bean + public WhitelabelErrorEndpoint oauth2ErrorEndpoint() { + return new WhitelabelErrorEndpoint(); + } + + @Bean + public WhitelabelApprovalEndpoint oauth2ApprovalEndpoint() { + return new WhitelabelApprovalEndpoint(); + } + + @Bean + public ApprovalStore approvalStore() { + TokenApprovalStore store = new TokenApprovalStore(); + store.setTokenStore(tokenStore()); + return store; + } + + @Bean + public ApprovalStoreUserApprovalHandler userApprovalHandler() { + ApprovalStoreUserApprovalHandler handler = new ApprovalStoreUserApprovalHandler(); + handler.setApprovalStore(approvalStore()); + handler.setClientDetailsService(clientDetailsService); + handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService)); + return handler; + } + + @Bean + public DefaultTokenServices tokenServices() { + DefaultTokenServices services = new DefaultTokenServices(); + services.setClientDetailsService(clientDetailsService); + services.setSupportRefreshToken(true); + services.setTokenStore(tokenStore()); + return services; + } + + @Bean + public TokenStore tokenStore() { + return new InMemoryTokenStore(); + } + + } + + @Configuration + protected static class ResourceServer extends WebSecurityConfigurerAdapter { + + @Autowired + @Qualifier("resourceFilter") + private Filter resourceFilter; + + @Bean + public FilterRegistrationBean resourceFilterRegistration() { + FilterRegistrationBean bean = new FilterRegistrationBean(); + bean.setFilter(resourceFilter); + bean.setEnabled(false); + return bean; + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http.addFilterBefore(resourceFilter, AbstractPreAuthenticatedProcessingFilter.class) + .requestMatcher(new NegatedRequestMatcher(new AntPathRequestMatcher("/oauth/**"))) + .authorizeRequests().anyRequest().authenticated().expressionHandler(new OAuth2WebSecurityExpressionHandler()) + .and() + .anonymous().disable() + .csrf().disable() + .exceptionHandling() + .authenticationEntryPoint(new OAuth2AuthenticationEntryPoint()) + .accessDeniedHandler(new OAuth2AccessDeniedHandler()); + // @formatter:on + } + + + } + + @Configuration + @Order(Ordered.HIGHEST_PRECEDENCE) + protected static class TokenEndpointSecurity extends WebSecurityConfigurerAdapter { + + @Autowired + private ClientDetailsService clientDetailsService; + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.userDetailsService(clientDetailsUserService()); + } + + @Bean + protected UserDetailsService clientDetailsUserService() { + return new ClientDetailsUserDetailsService(clientDetailsService); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http.anonymous().disable() + .antMatcher("/oauth/token") + .authorizeRequests().anyRequest().authenticated() + .and() + .httpBasic().authenticationEntryPoint(authenticationEntryPoint()) + .and() + .csrf().requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/token")).disable() + .exceptionHandling().accessDeniedHandler(accessDeniedHandler()) + .and() + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); + // @formatter:on + } + + @Bean + protected AccessDeniedHandler accessDeniedHandler() { + return new OAuth2AccessDeniedHandler(); + } + + @Bean + protected AuthenticationEntryPoint authenticationEntryPoint() { + OAuth2AuthenticationEntryPoint entryPoint = new OAuth2AuthenticationEntryPoint(); + entryPoint.setTypeName("Basic"); + entryPoint.setRealmName("oauth2/client"); + return entryPoint; + } + + } +} diff --git a/tests/xml/approval/src/main/resources/application.xml b/tests/xml/approval/src/main/resources/application.xml new file mode 100644 index 000000000..b7699634c --- /dev/null +++ b/tests/xml/approval/src/main/resources/application.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/tests/xml/approval/src/main/resources/application.yml b/tests/xml/approval/src/main/resources/application.yml new file mode 100644 index 000000000..e52b05d1f --- /dev/null +++ b/tests/xml/approval/src/main/resources/application.yml @@ -0,0 +1,8 @@ +spring: + application: + name: approval +management: + context_path: /admin +security: + user: + password: password diff --git a/tests/xml/approval/src/test/java/demo/ApplicationTests.java b/tests/xml/approval/src/test/java/demo/ApplicationTests.java new file mode 100644 index 000000000..8da63b411 --- /dev/null +++ b/tests/xml/approval/src/test/java/demo/ApplicationTests.java @@ -0,0 +1,20 @@ +package demo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = Application.class) +@WebAppConfiguration +@ActiveProfiles("test") +public class ApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/tests/xml/approval/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/xml/approval/src/test/java/demo/AuthorizationCodeProviderTests.java new file mode 100755 index 000000000..3bc5e7dac --- /dev/null +++ b/tests/xml/approval/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -0,0 +1,33 @@ +/* + * Copyright 2006-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 demo; + +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) { + assertTrue(page.contains("action='http://github.com/oauth/authorize'")); + assertTrue(page.contains(" + *
  • Client doesn't have a token so redirects to auth server /oauth/authorize
  • + *
  • Auth server prompts for authentication (username/password=user/password)
  • + *
  • Auth server prompts for approval of the token grant and redirects to client app
  • + *
  • Client app obtains token in back channel /oauth/token
  • + *
  • Client app obtains content from protected resource /admin/beans (hard-coded content for the demo)
  • + *
  • Client renders content
  • + * + * + * In this demo the client app is very basic (it just re-renders content it got from the resource server), but in a real + * app it can do whatever it likes with the resource content. + * + * @author Dave Syer + * + */ +@Configuration +@RestController +public class CombinedApplication { + + public static void main(String[] args) { + new SpringApplicationBuilder(ClientApplication.class, CombinedApplication.class).profiles("combined").run(args); + } + + @RequestMapping("/admin/beans") + public List> beans() { + return Arrays.asList(Collections. singletonMap("message", "Hello World")); + } + + @RequestMapping("/admin/info") + public Map info() { + return Collections. emptyMap(); + } + + @Configuration + @EnableAuthorizationServer + protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter { + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + clients.inMemory().withClient("my-trusted-client").authorizedGrantTypes("authorization_code") + .authorities("ROLE_CLIENT").scopes("read", "write").resourceIds("oauth2-resource"); + + } + + } + + @Configuration + @EnableResourceServer + protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { + + @Override + public void configure(HttpSecurity http) throws Exception { + http.antMatcher("/admin/beans").authorizeRequests().anyRequest().authenticated(); + } + + } + +} diff --git a/tests/xml/client/src/test/resources/application-combined.properties b/tests/xml/client/src/test/resources/application-combined.properties new file mode 100644 index 000000000..c44bd0a7a --- /dev/null +++ b/tests/xml/client/src/test/resources/application-combined.properties @@ -0,0 +1,5 @@ +server.port: 8080 +server.context_path: +security.basic.enabled: true +security.user.password: password +security.ignored: /,/admin/info \ No newline at end of file diff --git a/tests/xml/client/src/test/resources/test.properties b/tests/xml/client/src/test/resources/test.properties new file mode 100644 index 000000000..24466e50d --- /dev/null +++ b/tests/xml/client/src/test/resources/test.properties @@ -0,0 +1 @@ +server.port: 0 \ No newline at end of file diff --git a/tests/xml/common/README.md b/tests/xml/common/README.md new file mode 100644 index 000000000..624c516e2 --- /dev/null +++ b/tests/xml/common/README.md @@ -0,0 +1,4 @@ +This project contains test utilities for the other projects, for +instance `HttpUtils` for accessing RESTful resources and several +`Abstract*Tests` base classes for testing the basic operations of an +OAuth2 provider. diff --git a/tests/xml/common/pom.xml b/tests/xml/common/pom.xml new file mode 100644 index 000000000..50f03c395 --- /dev/null +++ b/tests/xml/common/pom.xml @@ -0,0 +1,94 @@ + + + 4.0.0 + + spring-oauth2-tests-xml-common + + spring-oauth2-tests-xml-common + Demo OAuth2 Spring Boot Common Utilities + + + org.demo + spring-oauth2-tests-xml-parent + 2.0.2.RELEASE + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-jdbc + true + + + org.springframework.security.oauth + spring-security-oauth2 + + + org.apache.httpcomponents + httpclient + + + org.springframework.boot + spring-boot-starter-test + + + junit + junit + + + org.mockito + mockito-core + + + org.hamcrest + hamcrest-library + + + + + demo.Application + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + + spring-snapshots + Spring Snapshots + http://repo.spring.io/snapshot + + true + + + + spring-milestones + Spring Milestones + http://repo.spring.io/milestone + + false + + + + + + spring-snapshots + Spring Snapshots + http://repo.spring.io/snapshot + + true + + + + + diff --git a/tests/xml/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java b/tests/xml/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java new file mode 100755 index 000000000..bcebe3a2d --- /dev/null +++ b/tests/xml/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java @@ -0,0 +1,430 @@ +/* + * Copyright 2006-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 sparklr.common; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.concurrent.atomic.AtomicReference; + +import org.junit.Test; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.security.crypto.codec.Base64; +import org.springframework.security.oauth2.client.OAuth2RestTemplate; +import org.springframework.security.oauth2.client.resource.UserApprovalRequiredException; +import org.springframework.security.oauth2.client.resource.UserRedirectRequiredException; +import org.springframework.security.oauth2.client.test.BeforeOAuth2Context; +import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration; +import org.springframework.security.oauth2.client.token.AccessTokenRequest; +import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider; +import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.common.exceptions.RedirectMismatchException; +import org.springframework.security.oauth2.common.util.OAuth2Utils; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.StreamUtils; +import org.springframework.web.client.DefaultResponseErrorHandler; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.ResourceAccessException; +import org.springframework.web.client.ResponseErrorHandler; +import org.springframework.web.client.ResponseExtractor; + +import sparklr.common.HttpTestUtils.UriBuilder; + +/** + * @author Dave Syer + * @author Luke Taylor + */ +public abstract class AbstractAuthorizationCodeProviderTests extends AbstractIntegrationTests { + + private AuthorizationCodeAccessTokenProvider accessTokenProvider; + + private ClientHttpResponse tokenEndpointResponse; + + @BeforeOAuth2Context + public void setupAccessTokenProvider() { + accessTokenProvider = new AuthorizationCodeAccessTokenProvider() { + + private ResponseExtractor extractor = super.getResponseExtractor(); + + private ResponseExtractor> authExtractor = super.getAuthorizationResponseExtractor(); + + private ResponseErrorHandler errorHandler = super.getResponseErrorHandler(); + + @Override + protected ResponseErrorHandler getResponseErrorHandler() { + return new DefaultResponseErrorHandler() { + public void handleError(ClientHttpResponse response) throws IOException { + response.getHeaders(); + response.getStatusCode(); + tokenEndpointResponse = response; + errorHandler.handleError(response); + } + }; + } + + @Override + protected ResponseExtractor getResponseExtractor() { + return new ResponseExtractor() { + + public OAuth2AccessToken extractData(ClientHttpResponse response) throws IOException { + try { + response.getHeaders(); + response.getStatusCode(); + tokenEndpointResponse = response; + return extractor.extractData(response); + } + catch (ResourceAccessException e) { + return null; + } + } + + }; + } + + @Override + protected ResponseExtractor> getAuthorizationResponseExtractor() { + return new ResponseExtractor>() { + + public ResponseEntity extractData(ClientHttpResponse response) throws IOException { + response.getHeaders(); + response.getStatusCode(); + tokenEndpointResponse = response; + return authExtractor.extractData(response); + } + }; + } + }; + context.setAccessTokenProvider(accessTokenProvider); + } + + @Test + @OAuth2ContextConfiguration(resource = MyTrustedClient.class, initialize = false) + public void testUnauthenticatedAuthorizationRespondsUnauthorized() throws Exception { + + AccessTokenRequest request = context.getAccessTokenRequest(); + request.setCurrentUri("http://anywhere/"); + request.add(OAuth2Utils.USER_OAUTH_APPROVAL, "true"); + + try { + String code = accessTokenProvider.obtainAuthorizationCode(context.getResource(), request); + assertNotNull(code); + fail("Expected UserRedirectRequiredException"); + } + catch (HttpClientErrorException e) { + assertEquals(HttpStatus.UNAUTHORIZED, e.getStatusCode()); + } + + } + + @Test + @OAuth2ContextConfiguration(resource = MyTrustedClient.class, initialize = false) + public void testSuccessfulAuthorizationCodeFlow() throws Exception { + + // Once the request is ready and approved, we can continue with the access token + approveAccessTokenGrant("http://anywhere/", true); + + // Finally everything is in place for the grant to happen... + assertNotNull(context.getAccessToken()); + + AccessTokenRequest request = context.getAccessTokenRequest(); + assertNotNull(request.getAuthorizationCode()); + assertEquals(HttpStatus.OK, http.getStatusCode("/admin/beans")); + + } + + @Test + @OAuth2ContextConfiguration(resource = MyTrustedClient.class, initialize = false) + public void testWrongRedirectUri() throws Exception { + approveAccessTokenGrant("http://anywhere/", true); + AccessTokenRequest request = context.getAccessTokenRequest(); + // The redirect is stored in the preserved state... + context.getOAuth2ClientContext().setPreservedState(request.getStateKey(), "http://nowhere/"); + // Finally everything is in place for the grant to happen... + try { + assertNotNull(context.getAccessToken()); + fail("Expected RedirectMismatchException"); + } + catch (RedirectMismatchException e) { + // expected + } + assertEquals(HttpStatus.BAD_REQUEST, tokenEndpointResponse.getStatusCode()); + } + + @Test + @OAuth2ContextConfiguration(resource = MyTrustedClient.class, initialize = false) + public void testUserDeniesConfirmation() throws Exception { + approveAccessTokenGrant("http://anywhere/", false); + String location = null; + try { + assertNotNull(context.getAccessToken()); + fail("Expected UserRedirectRequiredException"); + } + catch (UserRedirectRequiredException e) { + location = e.getRedirectUri(); + } + assertTrue("Wrong location: " + location, location.contains("state=")); + assertTrue(location.startsWith("http://anywhere/")); + assertTrue(location.substring(location.indexOf('?')).contains("error=access_denied")); + // It was a redirect that triggered our client redirect exception: + assertEquals(HttpStatus.FOUND, tokenEndpointResponse.getStatusCode()); + } + + @Test + public void testNoClientIdProvided() throws Exception { + ResponseEntity response = attemptToGetConfirmationPage(null, "http://anywhere/"); + // With no client id you get an InvalidClientException on the server which is forwarded to /oauth/error + assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); + String body = response.getBody(); + assertTrue("Wrong body: " + body, body.contains(" response = attemptToGetConfirmationPage("my-trusted-client", null); + // With no redirect uri you get an UnapprovedClientAuthenticationException on the server which is redirected to + // /oauth/error. + assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); + String body = response.getBody(); + assertTrue("Wrong body: " + body, body.contains(" response = http.postForStatus(authorizeUrl, headers, + new LinkedMultiValueMap()); + assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); + } + + @Test + @OAuth2ContextConfiguration(resource = MyClientWithRegisteredRedirect.class, initialize = false) + public void testSuccessfulFlowWithRegisteredRedirect() throws Exception { + + // Once the request is ready and approved, we can continue with the access token + approveAccessTokenGrant(null, true); + + // Finally everything is in place for the grant to happen... + assertNotNull(context.getAccessToken()); + + AccessTokenRequest request = context.getAccessTokenRequest(); + assertNotNull(request.getAuthorizationCode()); + assertEquals(HttpStatus.OK, http.getStatusCode("/admin/beans")); + + } + + @Test + public void testInvalidScopeInAuthorizationRequest() throws Exception { + + HttpHeaders headers = getAuthenticatedHeaders(); + headers.setAccept(Arrays.asList(MediaType.TEXT_HTML)); + + String scope = "bogus"; + String redirectUri = "http://anywhere/?key=value"; + String clientId = "my-client-with-registered-redirect"; + + UriBuilder uri = http.buildUri(authorizePath()).queryParam("response_type", "code") + .queryParam("state", "mystateid").queryParam("scope", scope); + if (clientId != null) { + uri.queryParam("client_id", clientId); + } + if (redirectUri != null) { + uri.queryParam("redirect_uri", redirectUri); + } + ResponseEntity response = http.getForString(uri.pattern(), headers, uri.params()); + assertEquals(HttpStatus.FOUND, response.getStatusCode()); + String location = response.getHeaders().getLocation().toString(); + assertTrue(location.startsWith("http://anywhere/")); + assertTrue(location.contains("error=invalid_scope")); + assertFalse(location.contains("redirect_uri=")); + } + + @Test + public void testInvalidAccessToken() throws Exception { + + // now make sure an unauthorized request fails the right way. + HttpHeaders headers = new HttpHeaders(); + headers.set("Authorization", String.format("%s %s", OAuth2AccessToken.BEARER_TYPE, "FOO")); + ResponseEntity response = http.getForString("/admin/beans", headers); + assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); + + String authenticate = response.getHeaders().getFirst("WWW-Authenticate"); + assertNotNull(authenticate); + assertTrue(authenticate.startsWith("Bearer")); + // Resource Server doesn't know what scopes are required until the token can be validated + assertFalse(authenticate.contains("scope=\"")); + + } + + @Test + @OAuth2ContextConfiguration(resource = MyClientWithRegisteredRedirect.class, initialize = false) + public void testRegisteredRedirectWithWrongRequestedRedirect() throws Exception { + try { + approveAccessTokenGrant("http://nowhere/", true); + fail("Expected RedirectMismatchException"); + } + catch (HttpClientErrorException e) { + assertEquals(HttpStatus.BAD_REQUEST, e.getStatusCode()); + } + } + + @Test + @OAuth2ContextConfiguration(resource = MyClientWithRegisteredRedirect.class, initialize = false) + public void testRegisteredRedirectWithWrongOneInTokenEndpoint() throws Exception { + approveAccessTokenGrant("http://anywhere/?key=value", true); + // Setting the redirect uri directly in the request should override the saved value + context.getAccessTokenRequest().set("redirect_uri", "http://nowhere.com/"); + try { + assertNotNull(context.getAccessToken()); + fail("Expected RedirectMismatchException"); + } + catch (RedirectMismatchException e) { + assertEquals(HttpStatus.BAD_REQUEST.value(), e.getHttpErrorCode()); + assertEquals("invalid_grant", e.getOAuth2ErrorCode()); + } + } + + private ResponseEntity attemptToGetConfirmationPage(String clientId, String redirectUri) { + HttpHeaders headers = getAuthenticatedHeaders(); + return http.getForString(getAuthorizeUrl(clientId, redirectUri, "read"), headers); + } + + private HttpHeaders getAuthenticatedHeaders() { + HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Arrays.asList(MediaType.TEXT_HTML)); + headers.set("Authorization", "Basic " + new String(Base64.encode("user:password".getBytes()))); + if (context.getRestTemplate() != null) { + context.getAccessTokenRequest().setHeaders(headers); + } + return headers; + } + + private String getAuthorizeUrl(String clientId, String redirectUri, String scope) { + UriBuilder uri = http.buildUri(authorizePath()).queryParam("response_type", "code") + .queryParam("state", "mystateid").queryParam("scope", scope); + if (clientId != null) { + uri.queryParam("client_id", clientId); + } + if (redirectUri != null) { + uri.queryParam("redirect_uri", redirectUri); + } + return uri.build().toString(); + } + + protected void approveAccessTokenGrant(String currentUri, boolean approved) { + + AccessTokenRequest request = context.getAccessTokenRequest(); + request.setHeaders(getAuthenticatedHeaders()); + AuthorizationCodeResourceDetails resource = (AuthorizationCodeResourceDetails) context.getResource(); + + if (currentUri != null) { + request.setCurrentUri(currentUri); + } + + String location = null; + + try { + // First try to obtain the access token... + assertNotNull(context.getAccessToken()); + fail("Expected UserRedirectRequiredException"); + } + catch (UserRedirectRequiredException e) { + // Expected and necessary, so that the correct state is set up in the request... + location = e.getRedirectUri(); + } + + assertTrue(location.startsWith(resource.getUserAuthorizationUri())); + assertNull(request.getAuthorizationCode()); + + verifyAuthorizationPage(context.getRestTemplate(), location); + + try { + // Now try again and the token provider will redirect for user approval... + assertNotNull(context.getAccessToken()); + fail("Expected UserRedirectRequiredException"); + } + catch (UserApprovalRequiredException e) { + // Expected and necessary, so that the user can approve the grant... + location = e.getApprovalUri(); + } + + assertTrue(location.startsWith(resource.getUserAuthorizationUri())); + assertNull(request.getAuthorizationCode()); + + // The approval (will be processed on the next attempt to obtain an access token)... + request.set(OAuth2Utils.USER_OAUTH_APPROVAL, "" + approved); + + } + + private void verifyAuthorizationPage(OAuth2RestTemplate restTemplate, String location) { + final AtomicReference confirmationPage = new AtomicReference(); + AuthorizationCodeAccessTokenProvider provider = new AuthorizationCodeAccessTokenProvider() { + @Override + protected ResponseExtractor> getAuthorizationResponseExtractor() { + return new ResponseExtractor>() { + public ResponseEntity extractData(ClientHttpResponse response) throws IOException { + confirmationPage.set(StreamUtils.copyToString(response.getBody(), Charset.forName("UTF-8"))); + return new ResponseEntity(response.getHeaders(), response.getStatusCode()); + } + }; + } + }; + try { + provider.obtainAuthorizationCode(restTemplate.getResource(), restTemplate.getOAuth2ClientContext().getAccessTokenRequest()); + } catch (UserApprovalRequiredException e) { + // ignore + } + String page = confirmationPage.get(); + verifyAuthorizationPage(page); + } + + protected void verifyAuthorizationPage(String page) { + } + + protected static class MyTrustedClient extends AuthorizationCodeResourceDetails { + public MyTrustedClient(Object target) { + super(); + setClientId("my-trusted-client"); + setScope(Arrays.asList("read")); + setId(getClientId()); + AbstractAuthorizationCodeProviderTests test = (AbstractAuthorizationCodeProviderTests) target; + setAccessTokenUri(test.http.getUrl(tokenPath())); + setUserAuthorizationUri(test.http.getUrl(authorizePath())); + } + } + + protected static class MyClientWithRegisteredRedirect extends MyTrustedClient { + public MyClientWithRegisteredRedirect(Object target) { + super(target); + setClientId("my-client-with-registered-redirect"); + setPreEstablishedRedirectUri("http://anywhere/?key=value"); + } + } +} diff --git a/tests/xml/common/src/main/java/sparklr/common/AbstractClientCredentialsProviderTests.java b/tests/xml/common/src/main/java/sparklr/common/AbstractClientCredentialsProviderTests.java new file mode 100644 index 000000000..bc4135dc8 --- /dev/null +++ b/tests/xml/common/src/main/java/sparklr/common/AbstractClientCredentialsProviderTests.java @@ -0,0 +1,111 @@ +package sparklr.common; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.IOException; +import java.util.Arrays; + +import org.junit.Test; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration; +import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsAccessTokenProvider; +import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.web.client.DefaultResponseErrorHandler; +import org.springframework.web.client.ResponseErrorHandler; + +/** + * @author Ryan Heaton + * @author Dave Syer + */ +public abstract class AbstractClientCredentialsProviderTests extends AbstractIntegrationTests { + + private HttpHeaders responseHeaders; + + private HttpStatus responseStatus; + + /** + * tests the basic provider + */ + @Test + @OAuth2ContextConfiguration(ClientCredentials.class) + public void testPostForToken() throws Exception { + OAuth2AccessToken token = context.getAccessToken(); + assertNull(token.getRefreshToken()); + } + + /** + * tests that the registered scopes are used as defaults + */ + @Test + @OAuth2ContextConfiguration(NoScopeClientCredentials.class) + public void testPostForTokenWithNoScopes() throws Exception { + OAuth2AccessToken token = context.getAccessToken(); + assertFalse("Wrong scope: " + token.getScope(), token.getScope().isEmpty()); + } + + @Test + @OAuth2ContextConfiguration(resource = InvalidClientCredentials.class, initialize = false) + public void testInvalidCredentials() throws Exception { + context.setAccessTokenProvider(new ClientCredentialsAccessTokenProvider() { + @Override + protected ResponseErrorHandler getResponseErrorHandler() { + return new DefaultResponseErrorHandler() { + public void handleError(ClientHttpResponse response) throws IOException { + responseHeaders = response.getHeaders(); + responseStatus = response.getStatusCode(); + } + }; + } + }); + try { + context.getAccessToken(); + fail("Expected ResourceAccessException"); + } + catch (Exception e) { + // ignore + } + // System.err.println(responseHeaders); + String header = responseHeaders.getFirst("WWW-Authenticate"); + assertTrue("Wrong header: " + header, header.contains("Basic realm")); + assertEquals(HttpStatus.UNAUTHORIZED, responseStatus); + } + + protected static class ClientCredentials extends ClientCredentialsResourceDetails { + + public ClientCredentials(Object target) { + setClientId("my-client-with-secret"); + setClientSecret("secret"); + setScope(Arrays.asList("read")); + setId(getClientId()); + AbstractClientCredentialsProviderTests test = (AbstractClientCredentialsProviderTests) target; + setAccessTokenUri(test.http.getUrl(tokenPath())); + } + } + + static class InvalidClientCredentials extends ClientCredentials { + public InvalidClientCredentials(Object target) { + super(target); + setClientId("my-client-with-secret"); + setClientSecret("wrong"); + } + } + + static class NoScopeClientCredentials extends ClientCredentialsResourceDetails { + public NoScopeClientCredentials(Object target) { + setClientId("my-client-with-secret"); + setClientSecret("secret"); + setId(getClientId()); + AbstractClientCredentialsProviderTests test = (AbstractClientCredentialsProviderTests) target; + setAccessTokenUri(test.http.getUrl(tokenPath())); + } + } + + +} diff --git a/tests/xml/common/src/main/java/sparklr/common/AbstractImplicitProviderTests.java b/tests/xml/common/src/main/java/sparklr/common/AbstractImplicitProviderTests.java new file mode 100644 index 000000000..2f0cf9cc9 --- /dev/null +++ b/tests/xml/common/src/main/java/sparklr/common/AbstractImplicitProviderTests.java @@ -0,0 +1,52 @@ +package sparklr.common; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +import org.junit.Test; +import org.springframework.http.HttpHeaders; +import org.springframework.security.crypto.codec.Base64; +import org.springframework.security.oauth2.client.resource.UserRedirectRequiredException; +import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration; +import org.springframework.security.oauth2.client.token.grant.implicit.ImplicitResourceDetails; +import org.springframework.security.oauth2.common.util.OAuth2Utils; + +/** + * @author Ryan Heaton + * @author Dave Syer + */ +public abstract class AbstractImplicitProviderTests extends AbstractIntegrationTests { + + @Test + @OAuth2ContextConfiguration(resource = NonAutoApproveImplicit.class, initialize = false) + public void testPostForNonAutomaticApprovalToken() throws Exception { + + HttpHeaders headers = new HttpHeaders(); + headers.set("Authorization", "Basic " + new String(Base64.encode("user:password".getBytes()))); + context.getAccessTokenRequest().setHeaders(headers); + try { + assertNotNull(context.getAccessToken()); + fail("Expected UserRedirectRequiredException"); + } + catch (UserRedirectRequiredException e) { + // ignore + } + // add user approval parameter for the second request + context.getAccessTokenRequest().add(OAuth2Utils.USER_OAUTH_APPROVAL, "true"); + context.getAccessTokenRequest().add("scope.read", "true"); + assertNotNull(context.getAccessToken()); + } + + static class NonAutoApproveImplicit extends ImplicitResourceDetails { + public NonAutoApproveImplicit(Object target) { + super(); + setClientId("my-trusted-client"); + setId(getClientId()); + setPreEstablishedRedirectUri("http://anywhere/"); + AbstractImplicitProviderTests test = (AbstractImplicitProviderTests) target; + setAccessTokenUri(test.http.getUrl(authorizePath())); + setUserAuthorizationUri(test.http.getUrl(authorizePath())); + } + } + +} diff --git a/tests/xml/common/src/main/java/sparklr/common/AbstractIntegrationTests.java b/tests/xml/common/src/main/java/sparklr/common/AbstractIntegrationTests.java new file mode 100644 index 000000000..d698f9091 --- /dev/null +++ b/tests/xml/common/src/main/java/sparklr/common/AbstractIntegrationTests.java @@ -0,0 +1,140 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package sparklr.common; + +import javax.sql.DataSource; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.runner.RunWith; +import org.springframework.aop.framework.Advised; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.embedded.EmbeddedWebApplicationContext; +import org.springframework.boot.test.IntegrationTest; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.security.oauth2.client.test.OAuth2ContextSetup; +import org.springframework.security.oauth2.provider.approval.ApprovalStore; +import org.springframework.security.oauth2.provider.approval.InMemoryApprovalStore; +import org.springframework.security.oauth2.provider.approval.JdbcApprovalStore; +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 sparklr.common.AbstractIntegrationTests.TestConfiguration; + +@SpringApplicationConfiguration(classes = TestConfiguration.class, inheritLocations = true) +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +@IntegrationTest +public abstract class AbstractIntegrationTests implements PortHolder { + + private static String globalTokenPath; + + private static String globalAuthorizePath; + + @Rule + public HttpTestUtils http = HttpTestUtils.standard().setPortHolder(this); + + @Rule + public OAuth2ContextSetup context = OAuth2ContextSetup.standard(http); + + @Autowired + private EmbeddedWebApplicationContext server; + + @Autowired(required=false) + private TokenStore tokenStore; + + @Autowired(required=false) + private ApprovalStore approvalStore; + + @Autowired(required=false) + private DataSource dataSource; + + @Override + public int getPort() { + return server == null ? 8080 : server.getEmbeddedServletContainer().getPort(); + } + + @Before + public void init() throws Exception { + clear(tokenStore); + clear(approvalStore); + } + + private void clear(ApprovalStore approvalStore) throws Exception { + if (approvalStore instanceof Advised) { + Advised advised = (Advised) tokenStore; + ApprovalStore target = (ApprovalStore) advised.getTargetSource().getTarget(); + clear(target); + return; + } + if (approvalStore instanceof InMemoryApprovalStore) { + ((InMemoryApprovalStore) approvalStore).clear(); + } + if (approvalStore instanceof JdbcApprovalStore) { + JdbcTemplate template = new JdbcTemplate(dataSource); + template.execute("delete from oauth_approvals"); + } + } + + private void clear(TokenStore tokenStore) throws Exception { + if (tokenStore instanceof Advised) { + Advised advised = (Advised) tokenStore; + TokenStore target = (TokenStore) advised.getTargetSource().getTarget(); + clear(target); + return; + } + if (tokenStore instanceof InMemoryTokenStore) { + ((InMemoryTokenStore) tokenStore).clear(); + } + if (tokenStore instanceof JdbcTokenStore) { + JdbcTemplate template = new JdbcTemplate(dataSource); + template.execute("delete from oauth_access_token"); + template.execute("delete from oauth_refresh_token"); + template.execute("delete from oauth_client_token"); + template.execute("delete from oauth_code"); + } + } + + @Value("${oauth.paths.token:/oauth/token}") + public void setTokenPath(String tokenPath) { + globalTokenPath = tokenPath; + } + + @Value("${oauth.paths.authorize:/oauth/authorize}") + public void setAuthorizePath(String authorizePath) { + globalAuthorizePath = authorizePath; + } + + public static String tokenPath() { + return globalTokenPath; + } + + public static String authorizePath() { + return globalAuthorizePath; + } + + @Configuration + @PropertySource(value = "classpath:test.properties", ignoreResourceNotFound = true) + protected static class TestConfiguration { + + } + +} \ No newline at end of file diff --git a/tests/xml/common/src/main/java/sparklr/common/AbstractProtectedResourceTests.java b/tests/xml/common/src/main/java/sparklr/common/AbstractProtectedResourceTests.java new file mode 100644 index 000000000..2e28fff86 --- /dev/null +++ b/tests/xml/common/src/main/java/sparklr/common/AbstractProtectedResourceTests.java @@ -0,0 +1,51 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package sparklr.common; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +/** + * @author Dave Syer + * + */ +public abstract class AbstractProtectedResourceTests extends AbstractIntegrationTests { + + @Test + public void testHomePageIsProtected() throws Exception { + ResponseEntity response = http.getForString("/"); + assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); + assertTrue("Wrong header: " + response.getHeaders(), response.getHeaders().getFirst("WWW-Authenticate") + .startsWith("Bearer realm=")); + } + + @Test + public void testBeansResourceIsProtected() throws Exception { + ResponseEntity response = http.getForString("/admin/beans"); + assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); + assertTrue("Wrong header: " + response.getHeaders(), response.getHeaders().getFirst("WWW-Authenticate") + .startsWith("Bearer realm=")); + } + + @Test + public void testHealthResourceIsOpen() throws Exception { + assertEquals(HttpStatus.OK, http.getStatusCode("/admin/health")); + } + + +} diff --git a/tests/xml/common/src/main/java/sparklr/common/AbstractRefreshTokenSupportTests.java b/tests/xml/common/src/main/java/sparklr/common/AbstractRefreshTokenSupportTests.java new file mode 100644 index 000000000..dd3b7b6c6 --- /dev/null +++ b/tests/xml/common/src/main/java/sparklr/common/AbstractRefreshTokenSupportTests.java @@ -0,0 +1,108 @@ +package sparklr.common; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.Map; + +import org.junit.Test; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.crypto.codec.Base64; +import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; + +/** + * @author Dave Syer + */ +public abstract class AbstractRefreshTokenSupportTests extends AbstractIntegrationTests { + + /** + * tests a happy-day flow of the refresh token provider. + */ + @Test + public void testHappyDay() throws Exception { + + OAuth2AccessToken accessToken = getAccessToken("read write", "my-trusted-client"); + + // now use the refresh token to get a new access token. + assertNotNull(accessToken.getRefreshToken()); + OAuth2AccessToken newAccessToken = refreshAccessToken(accessToken.getRefreshToken().getValue()); + assertFalse(newAccessToken.getValue().equals(accessToken.getValue())); + + verifyAccessTokens(accessToken, newAccessToken); + + } + + protected void verifyAccessTokens(OAuth2AccessToken oldAccessToken, OAuth2AccessToken newAccessToken) { + // make sure the new access token can be used. + verifyTokenResponse(newAccessToken.getValue(), HttpStatus.OK); + // make sure the old access token isn't valid anymore. + verifyTokenResponse(oldAccessToken.getValue(), HttpStatus.UNAUTHORIZED); + } + + protected void verifyTokenResponse(String accessToken, HttpStatus status) { + HttpHeaders headers = new HttpHeaders(); + headers.set("Authorization", String.format("%s %s", OAuth2AccessToken.BEARER_TYPE, accessToken)); + assertEquals(status, http.getStatusCode("/admin/beans", headers)); + } + + private OAuth2AccessToken refreshAccessToken(String refreshToken) { + + MultiValueMap formData = new LinkedMultiValueMap(); + formData.add("grant_type", "refresh_token"); + formData.add("client_id", "my-trusted-client"); + formData.add("refresh_token", refreshToken); + formData.add("scope", "read"); + HttpHeaders headers = getTokenHeaders("my-trusted-client"); + + @SuppressWarnings("rawtypes") + ResponseEntity response = http.postForMap(tokenPath(), headers, formData); + assertEquals(HttpStatus.OK, response.getStatusCode()); + assertTrue("Wrong cache control: " + response.getHeaders().getFirst("Cache-Control"), response.getHeaders() + .getFirst("Cache-Control").contains("no-store")); + @SuppressWarnings("unchecked") + OAuth2AccessToken newAccessToken = DefaultOAuth2AccessToken.valueOf(response.getBody()); + return newAccessToken; + + } + + private OAuth2AccessToken getAccessToken(String scope, String clientId) throws Exception { + MultiValueMap formData = getTokenFormData(scope, clientId); + HttpHeaders headers = getTokenHeaders(clientId); + @SuppressWarnings("rawtypes") + ResponseEntity response = http.postForMap(tokenPath(), headers, formData); + assertEquals(HttpStatus.OK, response.getStatusCode()); + assertTrue("Wrong cache control: " + response.getHeaders().getFirst("Cache-Control"), response.getHeaders() + .getFirst("Cache-Control").contains("no-store")); + + @SuppressWarnings("unchecked") + OAuth2AccessToken accessToken = DefaultOAuth2AccessToken.valueOf(response.getBody()); + return accessToken; + } + + private HttpHeaders getTokenHeaders(String clientId) { + HttpHeaders headers = new HttpHeaders(); + if (clientId != null) { + headers.set("Authorization", "Basic " + new String(Base64.encode((clientId + ":").getBytes()))); + } + return headers ; + } + + private MultiValueMap getTokenFormData(String scope, String clientId) { + MultiValueMap formData = new LinkedMultiValueMap(); + formData.add("grant_type", "password"); + if (clientId != null) { + formData.add("client_id", clientId); + } + formData.add("scope", scope); + formData.add("username", "user"); + formData.add("password", "password"); + return formData; + } +} diff --git a/tests/xml/common/src/main/java/sparklr/common/AbstractResourceOwnerPasswordProviderTests.java b/tests/xml/common/src/main/java/sparklr/common/AbstractResourceOwnerPasswordProviderTests.java new file mode 100644 index 000000000..37536940e --- /dev/null +++ b/tests/xml/common/src/main/java/sparklr/common/AbstractResourceOwnerPasswordProviderTests.java @@ -0,0 +1,254 @@ +package sparklr.common; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.List; + +import org.junit.Test; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.security.crypto.codec.Base64; +import org.springframework.security.oauth2.client.test.BeforeOAuth2Context; +import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration; +import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordAccessTokenProvider; +import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordResourceDetails; +import org.springframework.security.oauth2.common.AuthenticationScheme; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.web.client.DefaultResponseErrorHandler; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.ResponseErrorHandler; +import org.springframework.web.client.ResponseExtractor; + +/** + * @author Ryan Heaton + * @author Dave Syer + */ +public abstract class AbstractResourceOwnerPasswordProviderTests extends AbstractIntegrationTests { + + private ClientHttpResponse tokenEndpointResponse; + + @BeforeOAuth2Context + public void setupAccessTokenProvider() { + ResourceOwnerPasswordAccessTokenProvider accessTokenProvider = new ResourceOwnerPasswordAccessTokenProvider() { + + private ResponseExtractor extractor = super.getResponseExtractor(); + + private ResponseErrorHandler errorHandler = super.getResponseErrorHandler(); + + @Override + protected ResponseErrorHandler getResponseErrorHandler() { + return new DefaultResponseErrorHandler() { + public void handleError(ClientHttpResponse response) throws IOException { + response.getHeaders(); + response.getStatusCode(); + tokenEndpointResponse = response; + errorHandler.handleError(response); + } + }; + } + + @Override + protected ResponseExtractor getResponseExtractor() { + return new ResponseExtractor() { + + public OAuth2AccessToken extractData(ClientHttpResponse response) throws IOException { + response.getHeaders(); + response.getStatusCode(); + tokenEndpointResponse = response; + return extractor.extractData(response); + } + + }; + } + }; + context.setAccessTokenProvider(accessTokenProvider); + } + + @Test + public void testUnauthenticated() throws Exception { + // first make sure the resource is actually protected. + assertEquals(HttpStatus.UNAUTHORIZED, http.getStatusCode("/admin/beans")); + } + + @Test + public void testUnauthenticatedErrorMessage() throws Exception { + HttpHeaders headers = new HttpHeaders(); + ResponseEntity response = http.getForResponse("/admin/beans", headers); + assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); + String authenticate = response.getHeaders().getFirst("WWW-Authenticate"); + assertTrue("Wrong header: " + authenticate, authenticate.contains("error=\"unauthorized\"")); + } + + @Test + public void testInvalidTokenErrorMessage() throws Exception { + HttpHeaders headers = new HttpHeaders(); + headers.set("Authorization", "Bearer FOO"); + ResponseEntity response = http.getForResponse("/admin/beans", headers); + assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); + String authenticate = response.getHeaders().getFirst("WWW-Authenticate"); + assertTrue("Wrong header: " + authenticate, authenticate.contains("error=\"invalid_token\"")); + } + + @Test + @OAuth2ContextConfiguration(ResourceOwner.class) + public void testTokenObtainedWithHeaderAuthentication() throws Exception { + assertEquals(HttpStatus.OK, http.getStatusCode("/admin/beans")); + int expiry = context.getAccessToken().getExpiresIn(); + assertTrue("Expiry not overridden in config: " + expiry, expiry < 1000); + assertEquals(new MediaType("application", "json", Charset.forName("UTF-8")), tokenEndpointResponse.getHeaders() + .getContentType()); + } + + @Test + @OAuth2ContextConfiguration(ResourceOwnerQuery.class) + public void testTokenObtainedWithQueryAuthentication() throws Exception { + assertEquals(HttpStatus.OK, http.getStatusCode("/admin/beans")); + } + + @Test + @OAuth2ContextConfiguration(resource = ResourceOwnerNoSecretProvided.class, initialize = false) + public void testTokenNotGrantedIfSecretNotProvided() throws Exception { + try { + context.getAccessToken(); + } + catch (HttpClientErrorException e) { + assertEquals(HttpStatus.UNAUTHORIZED, e.getStatusCode()); + List values = tokenEndpointResponse.getHeaders().get("WWW-Authenticate"); + assertEquals(1, values.size()); + String header = values.get(0); + assertTrue("Wrong header " + header, header.contains("Basic realm=\"oauth2/client\"")); + } + } + + @Test + @OAuth2ContextConfiguration(ResourceOwnerSecretProvidedInForm.class) + public void testSecretProvidedInForm() throws Exception { + assertEquals(HttpStatus.OK, http.getStatusCode("/admin/beans")); + } + + @Test + @OAuth2ContextConfiguration(ResourceOwnerSecretProvided.class) + public void testSecretProvidedInHeader() throws Exception { + assertEquals(HttpStatus.OK, http.getStatusCode("/admin/beans")); + } + + @Test + @OAuth2ContextConfiguration(resource = NoSuchClient.class, initialize = false) + public void testNoSuchClient() throws Exception { + + // The error comes back as additional information because OAuth2AccessToken is so extensible! + try { + context.getAccessToken(); + } + catch (Exception e) { + // assertEquals("invalid_client", e.getOAuth2ErrorCode()); + } + + assertEquals(HttpStatus.UNAUTHORIZED, tokenEndpointResponse.getStatusCode()); + + List newCookies = tokenEndpointResponse.getHeaders().get("Set-Cookie"); + if (newCookies != null && !newCookies.isEmpty()) { + fail("No cookies should be set. Found: " + newCookies.get(0) + "."); + } + + } + + @Test + @OAuth2ContextConfiguration(resource = InvalidGrantType.class, initialize = false) + public void testInvalidGrantType() throws Exception { + + // The error comes back as additional information because OAuth2AccessToken is so extensible! + try { + context.getAccessToken(); + } + catch (Exception e) { + // assertEquals("invalid_client", e.getOAuth2ErrorCode()); + } + + assertEquals(HttpStatus.UNAUTHORIZED, tokenEndpointResponse.getStatusCode()); + + List newCookies = tokenEndpointResponse.getHeaders().get("Set-Cookie"); + if (newCookies != null && !newCookies.isEmpty()) { + fail("No cookies should be set. Found: " + newCookies.get(0) + "."); + } + + } + + /** + * tests that we get the correct error response if the media type is unacceptable. + */ + @Test + public void testMissingGrantType() throws Exception { + HttpHeaders headers = new HttpHeaders(); + headers.set("Authorization", String.format("Basic %s", new String(Base64.encode("my-trusted-client:".getBytes())))); + headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); + ResponseEntity response = http.postForString(tokenPath(), headers, new LinkedMultiValueMap()); + assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); + assertTrue(response.getBody().contains("invalid_request")); + } + + static class ResourceOwner extends ResourceOwnerPasswordResourceDetails { + public ResourceOwner(Object target) { + setClientId("my-trusted-client"); + setScope(Arrays.asList("read")); + setId(getClientId()); + setUsername("user"); + setPassword("password"); + AbstractResourceOwnerPasswordProviderTests test = (AbstractResourceOwnerPasswordProviderTests) target; + setAccessTokenUri(test.http.getUrl(tokenPath())); + } + } + + static class ResourceOwnerQuery extends ResourceOwner { + public ResourceOwnerQuery(Object target) { + super(target); + setAuthenticationScheme(AuthenticationScheme.query); + } + } + + static class ResourceOwnerNoSecretProvided extends ResourceOwner { + public ResourceOwnerNoSecretProvided(Object target) { + super(target); + setClientId("my-client-with-secret"); + } + } + + static class ResourceOwnerSecretProvided extends ResourceOwner { + public ResourceOwnerSecretProvided(Object target) { + super(target); + setClientId("my-client-with-secret"); + setClientSecret("secret"); + } + } + + static class ResourceOwnerSecretProvidedInForm extends ResourceOwnerSecretProvided { + public ResourceOwnerSecretProvidedInForm(Object target) { + super(target); + setAuthenticationScheme(AuthenticationScheme.form); + } + } + + static class InvalidGrantType extends ResourceOwner { + public InvalidGrantType(Object target) { + super(target); + setClientId("my-client-with-registered-redirect"); + } + } + + static class NoSuchClient extends ResourceOwner { + public NoSuchClient(Object target) { + super(target); + setClientId("no-such-client"); + } + } + +} diff --git a/tests/xml/common/src/main/java/sparklr/common/HttpTestUtils.java b/tests/xml/common/src/main/java/sparklr/common/HttpTestUtils.java new file mode 100644 index 000000000..2b3cb220c --- /dev/null +++ b/tests/xml/common/src/main/java/sparklr/common/HttpTestUtils.java @@ -0,0 +1,306 @@ +package sparklr.common; + +import java.net.HttpURLConnection; +import java.net.URI; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +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.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.oauth2.client.test.RestTemplateHolder; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestOperations; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriTemplate; + +/** + *

    + * A rule that provides HTTP connectivity to test cases on the assumption that the server is available when test methods + * fire. + *

    + * + * @author Dave Syer + * + */ +public class HttpTestUtils implements MethodRule, RestTemplateHolder { + + private static Log logger = LogFactory.getLog(HttpTestUtils.class); + + private static int DEFAULT_PORT = 8080; + + private static String DEFAULT_HOST = "localhost"; + + private int port; + + private String hostName = DEFAULT_HOST; + + private RestOperations client; + + private PortHolder portHolder; + + /** + * @return a new rule that sets up default host and port etc. + */ + public static HttpTestUtils standard() { + return new HttpTestUtils(); + } + + private HttpTestUtils() { + setPort(DEFAULT_PORT); + } + + /** + * @param port the port to set + */ + public HttpTestUtils setPort(int port) { + this.port = port; + if (client == null) { + client = createRestTemplate(); + } + return this; + } + + /** + * @param port the port holder to set + */ + public HttpTestUtils setPortHolder(PortHolder port) { + this.portHolder = port; + return this; + } + + /** + * @param hostName the hostName to set + */ + public HttpTestUtils setHostName(String hostName) { + this.hostName = hostName; + return this; + } + + public Statement apply(final Statement base, FrameworkMethod method, Object target) { + + if (portHolder!=null) { + setPort(portHolder.getPort()); + } + + RestTemplate client = new RestTemplate(); + boolean followRedirects = HttpURLConnection.getFollowRedirects(); + HttpURLConnection.setFollowRedirects(false); + try { + client.getForEntity(new UriTemplate(getUrl("/admin/info")).toString(), String.class); + logger.info("Basic connectivity test passed"); + } + catch (RestClientException e) { + logger.warn(String.format( + "Not executing tests because basic connectivity test failed for hostName=%s, port=%d", hostName, + port), e); + } + finally { + HttpURLConnection.setFollowRedirects(followRedirects); + } + + return new Statement() { + @Override + public void evaluate() throws Throwable { + base.evaluate(); + } + }; + + } + + public String getBaseUrl() { + return "http://" + hostName + ":" + port; + } + + public String getUrl(String path) { + if (path.startsWith("http")) { + return path; + } + if (!path.startsWith("/")) { + path = "/" + path; + } + return "http://" + hostName + ":" + port + path; + } + + public ResponseEntity postForString(String path, MultiValueMap formData) { + HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); + return client.exchange(getUrl(path), HttpMethod.POST, new HttpEntity>(formData, + headers), String.class); + } + + public ResponseEntity postForString(String path, HttpHeaders headers, MultiValueMap formData) { + HttpHeaders actualHeaders = new HttpHeaders(); + actualHeaders.putAll(headers); + headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); + return client.exchange(getUrl(path), HttpMethod.POST, new HttpEntity>(formData, + actualHeaders), String.class); + } + + @SuppressWarnings("rawtypes") + public ResponseEntity postForMap(String path, MultiValueMap formData) { + return postForMap(path, new HttpHeaders(), formData); + } + + @SuppressWarnings("rawtypes") + public ResponseEntity postForMap(String path, HttpHeaders headers, MultiValueMap formData) { + if (headers.getContentType() == null) { + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + } + return client.exchange(getUrl(path), HttpMethod.POST, new HttpEntity>(formData, + headers), Map.class); + } + + public ResponseEntity postForStatus(String path, MultiValueMap formData) { + return postForStatus(this.client, path, formData); + } + + public ResponseEntity postForStatus(String path, HttpHeaders headers, MultiValueMap formData) { + return postForStatus(this.client, path, headers, formData); + } + + private ResponseEntity postForStatus(RestOperations client, String path, + MultiValueMap formData) { + return postForStatus(client, path, new HttpHeaders(), formData); + } + + private ResponseEntity postForStatus(RestOperations client, String path, HttpHeaders headers, + MultiValueMap formData) { + HttpHeaders actualHeaders = new HttpHeaders(); + actualHeaders.putAll(headers); + actualHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + return client.exchange(getUrl(path), HttpMethod.POST, new HttpEntity>(formData, + actualHeaders), (Class) null); + } + + public ResponseEntity postForRedirect(String path, HttpHeaders headers, MultiValueMap params) { + ResponseEntity exchange = postForStatus(path, headers, params); + + if (exchange.getStatusCode() != HttpStatus.FOUND) { + throw new IllegalStateException("Expected 302 but server returned status code " + exchange.getStatusCode()); + } + + if (exchange.getHeaders().containsKey("Set-Cookie")) { + String cookie = exchange.getHeaders().getFirst("Set-Cookie"); + headers.set("Cookie", cookie); + } + + String location = exchange.getHeaders().getLocation().toString(); + + return client.exchange(location, HttpMethod.GET, new HttpEntity(null, headers), (Class) null); + } + + public ResponseEntity getForString(String path) { + return getForString(path, new HttpHeaders()); + } + + public ResponseEntity getForString(String path, final HttpHeaders headers) { + return client.exchange(getUrl(path), HttpMethod.GET, new HttpEntity((Void) null, headers), String.class); + } + + public ResponseEntity getForString(String path, final HttpHeaders headers, Map uriVariables) { + return client.exchange(getUrl(path), HttpMethod.GET, new HttpEntity((Void) null, headers), String.class, + uriVariables); + } + + public ResponseEntity getForResponse(String path, final HttpHeaders headers, Map uriVariables) { + HttpEntity request = new HttpEntity(null, headers); + return client.exchange(getUrl(path), HttpMethod.GET, request, (Class) null, uriVariables); + } + + public ResponseEntity getForResponse(String path, HttpHeaders headers) { + return getForResponse(path, headers, Collections. emptyMap()); + } + + public HttpStatus getStatusCode(String path, final HttpHeaders headers) { + ResponseEntity response = getForResponse(path, headers); + return response.getStatusCode(); + } + + public HttpStatus getStatusCode(String path) { + return getStatusCode(getUrl(path), null); + } + + public void setRestTemplate(RestOperations restTemplate) { + client = restTemplate; + } + + public RestOperations getRestTemplate() { + return client; + } + + public RestOperations createRestTemplate() { + RestTemplate client = new TestRestTemplate(); + return client; + } + + public UriBuilder buildUri(String url) { + return UriBuilder.fromUri(url.startsWith("http:") ? url : getUrl(url)); + } + + public static class UriBuilder { + + private final String url; + + private Map params = new LinkedHashMap(); + + public UriBuilder(String url) { + this.url = url; + } + + public static UriBuilder fromUri(String url) { + return new UriBuilder(url); + } + + public UriBuilder queryParam(String key, String value) { + params.put(key, value); + return this; + } + + public String pattern() { + StringBuilder builder = new StringBuilder(); + // try { + builder.append(url.replace(" ", "+")); + if (!params.isEmpty()) { + builder.append("?"); + boolean first = true; + for (String key : params.keySet()) { + if (!first) { + builder.append("&"); + } + else { + first = false; + } + String value = params.get(key); + if (value.contains("=")) { + value = value.replace("=", "%3D"); + } + builder.append(key + "={" + key + "}"); + } + } + return builder.toString(); + + } + + public Map params() { + return params; + } + + public URI build() { + return new UriTemplate(pattern()).expand(params); + } + } + +} diff --git a/tests/xml/common/src/main/java/sparklr/common/PortHolder.java b/tests/xml/common/src/main/java/sparklr/common/PortHolder.java new file mode 100644 index 000000000..362dceda8 --- /dev/null +++ b/tests/xml/common/src/main/java/sparklr/common/PortHolder.java @@ -0,0 +1,24 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package sparklr.common; + +/** + * @author Dave Syer + * + */ +public interface PortHolder { + + int getPort(); + +} diff --git a/tests/xml/form/README.md b/tests/xml/form/README.md new file mode 100644 index 000000000..7d1ce46a6 --- /dev/null +++ b/tests/xml/form/README.md @@ -0,0 +1,7 @@ +In this project the Authorization Server allows form-based +authentication on the /oauth/token endpoint. This is not best +practice from a security point of view so it is disabled by default. + +In the Authorization Server we call `allowFormAuthenticationForClients()` +on the configurer. That's it. + diff --git a/tests/xml/form/pom.xml b/tests/xml/form/pom.xml new file mode 100644 index 000000000..444a0e50c --- /dev/null +++ b/tests/xml/form/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + + spring-oauth2-tests-xml-form + + spring-oauth2-tests-xml-form + Demo project + + + org.demo + spring-oauth2-tests-xml-parent + 2.0.2.RELEASE + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.security.oauth + spring-security-oauth2 + + + org.demo + spring-oauth2-tests-xml-common + ${project.version} + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/tests/xml/form/src/main/java/demo/Application.java b/tests/xml/form/src/main/java/demo/Application.java new file mode 100644 index 000000000..a4beff6fb --- /dev/null +++ b/tests/xml/form/src/main/java/demo/Application.java @@ -0,0 +1,166 @@ +package demo; + +import javax.servlet.Filter; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.context.embedded.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ImportResource; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter; +import org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService; +import org.springframework.security.oauth2.provider.endpoint.WhitelabelApprovalEndpoint; +import org.springframework.security.oauth2.provider.endpoint.WhitelabelErrorEndpoint; +import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; +import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint; +import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler; +import org.springframework.security.oauth2.provider.token.DefaultTokenServices; +import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.access.AccessDeniedHandler; +import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter; +import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.util.matcher.NegatedRequestMatcher; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Configuration +@ComponentScan +@EnableAutoConfiguration +@ImportResource("classpath:/application.xml") +@RestController +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + @RequestMapping("/") + public String home() { + return "Hello World"; + } + + @Configuration + protected static class OAuth2Config { + + @Autowired + private ClientDetailsService clientDetailsService; + + @Bean + public DefaultTokenServices tokenServices() { + DefaultTokenServices services = new DefaultTokenServices(); + services.setClientDetailsService(clientDetailsService); + services.setSupportRefreshToken(true); + services.setTokenStore(new InMemoryTokenStore()); + return services; + } + + @Bean + public WhitelabelErrorEndpoint oauth2ErrorEndpoint() { + return new WhitelabelErrorEndpoint(); + } + + @Bean + public WhitelabelApprovalEndpoint oauth2ApprovalEndpoint() { + return new WhitelabelApprovalEndpoint(); + } + + } + + @Configuration + protected static class ResourceServer extends WebSecurityConfigurerAdapter { + + @Autowired + @Qualifier("resourceFilter") + private Filter resourceFilter; + + @Bean + public FilterRegistrationBean resourceFilterRegistration() { + FilterRegistrationBean bean = new FilterRegistrationBean(); + bean.setFilter(resourceFilter); + bean.setEnabled(false); + return bean; + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http.addFilterBefore(resourceFilter, AbstractPreAuthenticatedProcessingFilter.class) + .requestMatcher(new NegatedRequestMatcher(new AntPathRequestMatcher("/oauth/**"))) + .authorizeRequests().anyRequest().authenticated().expressionHandler(new OAuth2WebSecurityExpressionHandler()) + .and() + .anonymous().disable() + .csrf().disable() + .exceptionHandling() + .authenticationEntryPoint(new OAuth2AuthenticationEntryPoint()) + .accessDeniedHandler(new OAuth2AccessDeniedHandler()); + // @formatter:on + } + + } + + @Configuration + @Order(Ordered.HIGHEST_PRECEDENCE) + protected static class TokenEndpointSecurity extends WebSecurityConfigurerAdapter { + + @Autowired + private ClientDetailsService clientDetailsService; + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.userDetailsService(clientDetailsUserService()); + } + + @Bean + protected UserDetailsService clientDetailsUserService() { + return new ClientDetailsUserDetailsService(clientDetailsService); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http.anonymous().disable() + .antMatcher("/oauth/token") + .authorizeRequests().anyRequest().authenticated() + .and() + .httpBasic().authenticationEntryPoint(authenticationEntryPoint()) + .and() + .csrf().requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/token")).disable() + .exceptionHandling().accessDeniedHandler(accessDeniedHandler()) + .and() + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); + // @formatter:on + ClientCredentialsTokenEndpointFilter filter = new ClientCredentialsTokenEndpointFilter(); + filter.setAuthenticationManager(super.authenticationManagerBean()); + filter.afterPropertiesSet(); + http.addFilterBefore(filter, BasicAuthenticationFilter.class); + } + + @Bean + protected AccessDeniedHandler accessDeniedHandler() { + return new OAuth2AccessDeniedHandler(); + } + + @Bean + protected AuthenticationEntryPoint authenticationEntryPoint() { + OAuth2AuthenticationEntryPoint entryPoint = new OAuth2AuthenticationEntryPoint(); + entryPoint.setTypeName("Basic"); + entryPoint.setRealmName("oauth2/client"); + return entryPoint; + } + + } +} diff --git a/tests/xml/form/src/main/resources/application.xml b/tests/xml/form/src/main/resources/application.xml new file mode 100644 index 000000000..fd38cb4c0 --- /dev/null +++ b/tests/xml/form/src/main/resources/application.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/tests/xml/form/src/main/resources/application.yml b/tests/xml/form/src/main/resources/application.yml new file mode 100644 index 000000000..147340301 --- /dev/null +++ b/tests/xml/form/src/main/resources/application.yml @@ -0,0 +1,8 @@ +spring: + application: + name: form +management: + context_path: /admin +security: + user: + password: password diff --git a/tests/xml/form/src/test/java/demo/ApplicationTests.java b/tests/xml/form/src/test/java/demo/ApplicationTests.java new file mode 100644 index 000000000..8da63b411 --- /dev/null +++ b/tests/xml/form/src/test/java/demo/ApplicationTests.java @@ -0,0 +1,20 @@ +package demo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = Application.class) +@WebAppConfiguration +@ActiveProfiles("test") +public class ApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/tests/xml/form/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/xml/form/src/test/java/demo/AuthorizationCodeProviderTests.java new file mode 100755 index 000000000..632098bf1 --- /dev/null +++ b/tests/xml/form/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -0,0 +1,25 @@ +/* + * Copyright 2006-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 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/xml/form/src/test/java/demo/ClientCredentialsProviderTests.java b/tests/xml/form/src/test/java/demo/ClientCredentialsProviderTests.java new file mode 100644 index 000000000..3d9ccf4f6 --- /dev/null +++ b/tests/xml/form/src/test/java/demo/ClientCredentialsProviderTests.java @@ -0,0 +1,87 @@ +package demo; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +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; +import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration; +import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsAccessTokenProvider; +import org.springframework.security.oauth2.common.AuthenticationScheme; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.web.client.DefaultResponseErrorHandler; +import org.springframework.web.client.ResponseErrorHandler; + +import sparklr.common.AbstractClientCredentialsProviderTests; + +/** + * @author Dave Syer + */ +@SpringApplicationConfiguration(classes=Application.class) +public class ClientCredentialsProviderTests extends AbstractClientCredentialsProviderTests { + + private HttpHeaders responseHeaders; + + private HttpStatus responseStatus; + + /** + * tests the basic provider with form based client credentials + */ + @Test + @OAuth2ContextConfiguration(FormClientCredentials.class) + public void testPostForTokenWithForm() throws Exception { + OAuth2AccessToken token = context.getAccessToken(); + assertNull(token.getRefreshToken()); + } + + @Test + @OAuth2ContextConfiguration(resource = InvalidClientCredentials.class, initialize = false) + public void testInvalidCredentialsWithFormAuthentication() throws Exception { + context.setAccessTokenProvider(new ClientCredentialsAccessTokenProvider() { + @Override + protected ResponseErrorHandler getResponseErrorHandler() { + return new DefaultResponseErrorHandler() { + public void handleError(ClientHttpResponse response) throws IOException { + responseHeaders = response.getHeaders(); + responseStatus = response.getStatusCode(); + } + }; + } + }); + try { + context.getAccessToken(); + fail("Expected ResourceAccessException"); + } + catch (Exception e) { + // ignore + } + // System.err.println(responseHeaders); + String header = responseHeaders.getFirst("WWW-Authenticate"); + assertTrue("Wrong header: " + header, header.contains("Form realm")); + assertEquals(HttpStatus.UNAUTHORIZED, responseStatus); + } + + static class FormClientCredentials extends ClientCredentials { + public FormClientCredentials(Object target) { + super(target); + setClientAuthenticationScheme(AuthenticationScheme.form); + } + } + + static class InvalidClientCredentials extends ClientCredentials { + public InvalidClientCredentials(Object target) { + super(target); + setClientId("my-client-with-secret"); + setClientSecret("wrong"); + setClientAuthenticationScheme(AuthenticationScheme.form); + } + } + +} diff --git a/tests/xml/form/src/test/java/demo/ImplicitProviderTests.java b/tests/xml/form/src/test/java/demo/ImplicitProviderTests.java new file mode 100644 index 000000000..7a8958187 --- /dev/null +++ b/tests/xml/form/src/test/java/demo/ImplicitProviderTests.java @@ -0,0 +1,13 @@ +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/xml/form/src/test/java/demo/ProtectedResourceTests.java b/tests/xml/form/src/test/java/demo/ProtectedResourceTests.java new file mode 100644 index 000000000..c752cbe12 --- /dev/null +++ b/tests/xml/form/src/test/java/demo/ProtectedResourceTests.java @@ -0,0 +1,27 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package 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/xml/form/src/test/java/demo/RefreshTokenSupportTests.java b/tests/xml/form/src/test/java/demo/RefreshTokenSupportTests.java new file mode 100644 index 000000000..4ed370eea --- /dev/null +++ b/tests/xml/form/src/test/java/demo/RefreshTokenSupportTests.java @@ -0,0 +1,13 @@ +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/xml/form/src/test/java/demo/ResourceOwnerPasswordProviderTests.java b/tests/xml/form/src/test/java/demo/ResourceOwnerPasswordProviderTests.java new file mode 100644 index 000000000..aa5786098 --- /dev/null +++ b/tests/xml/form/src/test/java/demo/ResourceOwnerPasswordProviderTests.java @@ -0,0 +1,13 @@ +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/xml/form/src/test/resources/test.properties b/tests/xml/form/src/test/resources/test.properties new file mode 100644 index 000000000..24466e50d --- /dev/null +++ b/tests/xml/form/src/test/resources/test.properties @@ -0,0 +1 @@ +server.port: 0 \ No newline at end of file diff --git a/tests/xml/jdbc/README.md b/tests/xml/jdbc/README.md new file mode 100644 index 000000000..b88f1fd85 --- /dev/null +++ b/tests/xml/jdbc/README.md @@ -0,0 +1,21 @@ +This project shows what you can do with the minimum configuration to +set up an Authorization Server and Resource Server with JDBC backends. + +The Authorization Server has JDBC backends for clients +(`ClientDetailsStore`), tokens (`TokenStore`), authorization codes +(`AuthorizationCodeStore`) and user accounts +(`UserDetailsManager`). Even with these services, a horizontally +scaled Authorization Server needs to be fronted by a load balancer +with sticky sessions (or else a Spring `SessionAttributeStore` should +be provided in addition to wht you see here), if the stateful grant +types are used (authorization code or implicit). + +An `AuthenticationManager` is created (it has a single user, named +"user", with password "password", per `application.yml`). It is needed +in the Authorization Server to provide authentication for the Resource +Owner Password grant type. + +The Resource Server shares the `TokenStore` with the Authorization +Server, but it doesn't need to know about the other services (so they +could be in-memory if there is a single instance of the Authorization +Server). diff --git a/tests/xml/jdbc/pom.xml b/tests/xml/jdbc/pom.xml new file mode 100644 index 000000000..a1f36b357 --- /dev/null +++ b/tests/xml/jdbc/pom.xml @@ -0,0 +1,58 @@ + + + 4.0.0 + + spring-oauth2-tests-xml-jdbc + + spring-oauth2-tests-xml-jdbc + Demo project + + + org.demo + spring-oauth2-tests-xml-parent + 2.0.2.RELEASE + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-jdbc + + + org.springframework.security.oauth + spring-security-oauth2 + + + com.h2database + h2 + + + org.demo + spring-oauth2-tests-xml-common + ${project.version} + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/tests/xml/jdbc/src/main/java/demo/Application.java b/tests/xml/jdbc/src/main/java/demo/Application.java new file mode 100644 index 000000000..aa302dba3 --- /dev/null +++ b/tests/xml/jdbc/src/main/java/demo/Application.java @@ -0,0 +1,201 @@ +package demo; + +import javax.servlet.Filter; +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.security.SecurityProperties; +import org.springframework.boot.autoconfigure.security.SecurityProperties.User; +import org.springframework.boot.context.embedded.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ImportResource; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService; +import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService; +import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; +import org.springframework.security.oauth2.provider.code.JdbcAuthorizationCodeServices; +import org.springframework.security.oauth2.provider.endpoint.WhitelabelApprovalEndpoint; +import org.springframework.security.oauth2.provider.endpoint.WhitelabelErrorEndpoint; +import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; +import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint; +import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler; +import org.springframework.security.oauth2.provider.token.DefaultTokenServices; +import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.access.AccessDeniedHandler; +import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.util.matcher.NegatedRequestMatcher; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Configuration +@EnableAutoConfiguration +@RestController +@ImportResource("classpath:/application.xml") +public class Application { + + @Order(Ordered.LOWEST_PRECEDENCE - 8) + protected static class ApplicationSecurity extends WebSecurityConfigurerAdapter { + + @Autowired + private DataSource dataSource; + + @Autowired + private SecurityProperties security; + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + User user = security.getUser(); + // @formatter:off + auth.jdbcAuthentication().dataSource(dataSource) + .withUser(user.getName()) + .password(user.getPassword()) + .roles(user.getRole().toArray(new String[0])); + // @formatter:on + } + } + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + @RequestMapping("/") + public String home() { + return "Hello World"; + } + + @Configuration + protected static class ResourceServer extends WebSecurityConfigurerAdapter { + + @Autowired + @Qualifier("resourceFilter") + private Filter resourceFilter; + + @Bean + public FilterRegistrationBean resourceFilterRegistration() { + FilterRegistrationBean bean = new FilterRegistrationBean(); + bean.setFilter(resourceFilter); + bean.setEnabled(false); + return bean; + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http.addFilterBefore(resourceFilter, AbstractPreAuthenticatedProcessingFilter.class) + .requestMatcher(new NegatedRequestMatcher(new AntPathRequestMatcher("/oauth/**"))) + .authorizeRequests().anyRequest().authenticated().expressionHandler(new OAuth2WebSecurityExpressionHandler()) + .and() + .anonymous().disable() + .csrf().disable() + .exceptionHandling() + .authenticationEntryPoint(new OAuth2AuthenticationEntryPoint()) + .accessDeniedHandler(new OAuth2AccessDeniedHandler()); + // @formatter:on + } + + } + + @Configuration + protected static class OAuth2Config { + + @Autowired + private DataSource dataSource; + + @Bean + public JdbcClientDetailsService clientDetailsService() { + return new JdbcClientDetailsService(dataSource); + } + + @Bean + public JdbcTokenStore tokenStore() { + return new JdbcTokenStore(dataSource); + } + + @Bean + protected AuthorizationCodeServices authorizationCodeServices() { + return new JdbcAuthorizationCodeServices(dataSource); + } + + @Bean + public DefaultTokenServices tokenServices() { + DefaultTokenServices services = new DefaultTokenServices(); + services.setClientDetailsService(clientDetailsService()); + services.setSupportRefreshToken(true); + services.setTokenStore(tokenStore()); + return services; + } + + @Bean + public WhitelabelErrorEndpoint oauth2ErrorEndpoint() { + return new WhitelabelErrorEndpoint(); + } + + @Bean + public WhitelabelApprovalEndpoint oauth2ApprovalEndpoint() { + return new WhitelabelApprovalEndpoint(); + } + + } + + @Configuration + @Order(Ordered.HIGHEST_PRECEDENCE) + protected static class TokenEndpointSecurity extends WebSecurityConfigurerAdapter { + + @Autowired + private ClientDetailsService clientDetailsService; + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.userDetailsService(clientDetailsUserService()); + } + + @Bean + protected UserDetailsService clientDetailsUserService() { + return new ClientDetailsUserDetailsService(clientDetailsService); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http.anonymous().disable() + .antMatcher("/oauth/token") + .authorizeRequests().anyRequest().authenticated() + .and() + .httpBasic().authenticationEntryPoint(authenticationEntryPoint()) + .and() + .csrf().requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/token")).disable() + .exceptionHandling().accessDeniedHandler(accessDeniedHandler()) + .and() + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); + // @formatter:on + } + + @Bean + protected AccessDeniedHandler accessDeniedHandler() { + return new OAuth2AccessDeniedHandler(); + } + + @Bean + protected AuthenticationEntryPoint authenticationEntryPoint() { + OAuth2AuthenticationEntryPoint entryPoint = new OAuth2AuthenticationEntryPoint(); + entryPoint.setTypeName("Basic"); + entryPoint.setRealmName("oauth2/client"); + return entryPoint; + } + + } + +} diff --git a/tests/xml/jdbc/src/main/java/demo/ClientApplication.java b/tests/xml/jdbc/src/main/java/demo/ClientApplication.java new file mode 100644 index 000000000..82e4612c1 --- /dev/null +++ b/tests/xml/jdbc/src/main/java/demo/ClientApplication.java @@ -0,0 +1,89 @@ +package demo; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import javax.annotation.Resource; +import javax.sql.DataSource; + +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.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Scope; +import org.springframework.context.annotation.ScopedProxyMode; +import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext; +import org.springframework.security.oauth2.client.OAuth2RestOperations; +import org.springframework.security.oauth2.client.OAuth2RestTemplate; +import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails; +import org.springframework.security.oauth2.client.token.AccessTokenProviderChain; +import org.springframework.security.oauth2.client.token.AccessTokenRequest; +import org.springframework.security.oauth2.client.token.ClientTokenServices; +import org.springframework.security.oauth2.client.token.JdbcClientTokenServices; +import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider; +import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails; +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Configuration +@EnableAutoConfiguration +@EnableOAuth2Client +@RestController +public class ClientApplication { + + public static void main(String[] args) { + new SpringApplicationBuilder().profiles("client").sources(ClientApplication.class).run(args); + } + + @Value("${oauth.resource:http://localhost:8080}") + private String baseUrl; + + @Value("${oauth.authorize:http://localhost:8080/oauth/authorize}") + private String authorizeUrl; + + @Value("${oauth.token:http://localhost:8080/oauth/token}") + private String tokenUrl; + + @Resource + @Qualifier("accessTokenRequest") + private AccessTokenRequest accessTokenRequest; + + @Autowired + private DataSource dataSource; + + @RequestMapping("/") + public List> home() { + @SuppressWarnings("unchecked") + List> result = restTemplate().getForObject(baseUrl + "/admin/beans", List.class); + return result; + } + + @Bean + @Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES) + public OAuth2RestOperations restTemplate() { + OAuth2RestTemplate template = new OAuth2RestTemplate(resource(), new DefaultOAuth2ClientContext(accessTokenRequest)); + AccessTokenProviderChain provider = new AccessTokenProviderChain(Arrays.asList(new AuthorizationCodeAccessTokenProvider())); + provider.setClientTokenServices(clientTokenServices()); + return template; + } + + @Bean + public ClientTokenServices clientTokenServices() { + return new JdbcClientTokenServices(dataSource); + } + + @Bean + protected OAuth2ProtectedResourceDetails resource() { + AuthorizationCodeResourceDetails resource = new AuthorizationCodeResourceDetails(); + resource.setAccessTokenUri(tokenUrl); + resource.setUserAuthorizationUri(authorizeUrl); + resource.setClientId("my-trusted-client"); + return resource; + } + +} diff --git a/tests/xml/jdbc/src/main/resources/application.xml b/tests/xml/jdbc/src/main/resources/application.xml new file mode 100644 index 000000000..e09a254df --- /dev/null +++ b/tests/xml/jdbc/src/main/resources/application.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + diff --git a/tests/xml/jdbc/src/main/resources/application.yml b/tests/xml/jdbc/src/main/resources/application.yml new file mode 100644 index 000000000..c2b03892c --- /dev/null +++ b/tests/xml/jdbc/src/main/resources/application.yml @@ -0,0 +1,15 @@ +spring: + application: + name: jdbc +management: + context_path: /admin +security: + user: + password: password + +--- + +spring: + profiles: client +server: + port: 8081 \ No newline at end of file diff --git a/tests/xml/jdbc/src/main/resources/data.sql b/tests/xml/jdbc/src/main/resources/data.sql new file mode 100644 index 000000000..ccb9d2481 --- /dev/null +++ b/tests/xml/jdbc/src/main/resources/data.sql @@ -0,0 +1,8 @@ +insert into oauth_client_details (client_id, resource_ids, scope, authorized_grant_types, authorities, access_token_validity) + values ('my-trusted-client', 'oauth2-resource', 'read,write,trust', 'password,authorization_code,refresh_token,implicit', 'ROLE_CLIENT,ROLE_TRUSTED_CLIENT', 60); + +insert into oauth_client_details (client_id, resource_ids, scope, authorized_grant_types, authorities, web_server_redirect_uri) + values ('my-client-with-registered-redirect', 'oauth2-resource', 'read,trust', 'authorization_code', 'ROLE_CLIENT', 'http://anywhere/?key=value'); + +insert into oauth_client_details (client_id, client_secret, resource_ids, scope, authorized_grant_types, authorities) + values ('my-client-with-secret', 'secret', 'oauth2-resource', 'read', 'password,client_credentials', 'ROLE_CLIENT'); diff --git a/tests/xml/jdbc/src/main/resources/logback.xml b/tests/xml/jdbc/src/main/resources/logback.xml new file mode 100644 index 000000000..8ddbd55bf --- /dev/null +++ b/tests/xml/jdbc/src/main/resources/logback.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tests/xml/jdbc/src/main/resources/schema.sql b/tests/xml/jdbc/src/main/resources/schema.sql new file mode 100644 index 000000000..5ffe631a8 --- /dev/null +++ b/tests/xml/jdbc/src/main/resources/schema.sql @@ -0,0 +1,53 @@ +create table users ( + username varchar(256), + password varchar(256), + enabled boolean +); + +create table authorities ( + username varchar(256), + authority varchar(256) +); + +create table oauth_client_details ( + client_id VARCHAR(256) PRIMARY KEY, + resource_ids VARCHAR(256), + client_secret VARCHAR(256), + scope VARCHAR(256), + authorized_grant_types VARCHAR(256), + web_server_redirect_uri VARCHAR(256), + authorities VARCHAR(256), + access_token_validity INTEGER, + refresh_token_validity INTEGER, + additional_information VARCHAR(4096), + autoapprove VARCHAR(256) +); + +create table oauth_client_token ( + token_id VARCHAR(256), + token LONGVARBINARY, + authentication_id VARCHAR(256), + user_name VARCHAR(256), + client_id VARCHAR(256) +); + +create table oauth_access_token ( + token_id VARCHAR(256), + token LONGVARBINARY, + authentication_id VARCHAR(256), + user_name VARCHAR(256), + client_id VARCHAR(256), + authentication LONGVARBINARY, + refresh_token VARCHAR(256) +); + +create table oauth_refresh_token ( + token_id VARCHAR(256), + token LONGVARBINARY, + authentication LONGVARBINARY +); + +create table oauth_code ( + code VARCHAR(256), authentication LONGVARBINARY +); + diff --git a/tests/xml/jdbc/src/test/java/demo/AdHocTests.java b/tests/xml/jdbc/src/test/java/demo/AdHocTests.java new file mode 100644 index 000000000..a7d0087ca --- /dev/null +++ b/tests/xml/jdbc/src/test/java/demo/AdHocTests.java @@ -0,0 +1,39 @@ +/* + * Copyright 20013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package demo; + +import org.junit.Ignore; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +/** + * @author Dave Syer + * + */ +@RunWith(Suite.class) +// @formatter:off +@SuiteClasses({ + AuthorizationCodeProviderTests.class, + RefreshTokenSupportTests.class, + ClientCredentialsProviderTests.class, + ApplicationTests.class, + ProtectedResourceTests.class, + ImplicitProviderTests.class, + ResourceOwnerPasswordProviderTests.class }) +// @formatter:on +@Ignore("Test suite for tracking order dependencies") +public class AdHocTests { + +} diff --git a/tests/xml/jdbc/src/test/java/demo/ApplicationTests.java b/tests/xml/jdbc/src/test/java/demo/ApplicationTests.java new file mode 100644 index 000000000..055467fe5 --- /dev/null +++ b/tests/xml/jdbc/src/test/java/demo/ApplicationTests.java @@ -0,0 +1,29 @@ +package demo; + +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.SpringApplicationConfiguration; +import org.springframework.security.oauth2.provider.token.TokenStore; +import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = Application.class) +@WebAppConfiguration +@ActiveProfiles("test") +public class ApplicationTests { + + @Autowired + private TokenStore tokenStore; + + @Test + public void contextLoads() { + assertTrue("Wrong token store type: " + tokenStore, tokenStore instanceof JdbcTokenStore); + } + +} diff --git a/tests/xml/jdbc/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/xml/jdbc/src/test/java/demo/AuthorizationCodeProviderTests.java new file mode 100755 index 000000000..8c4082abd --- /dev/null +++ b/tests/xml/jdbc/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -0,0 +1,33 @@ +/* + * Copyright 2006-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 demo; + +import static org.junit.Assert.assertFalse; +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) { + assertTrue(page.contains("action='http://github.com/oauth/authorize'")); + assertTrue(page.contains(" + + 4.0.0 + + spring-oauth2-tests-xml-mappings + + spring-oauth2-tests-xml-mappings + Demo project + + + org.demo + spring-oauth2-tests-xml-parent + 2.0.2.RELEASE + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.security.oauth + spring-security-oauth2 + + + org.demo + spring-oauth2-tests-xml-common + ${project.version} + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/tests/xml/mappings/src/main/java/demo/Application.java b/tests/xml/mappings/src/main/java/demo/Application.java new file mode 100644 index 000000000..d467e4c06 --- /dev/null +++ b/tests/xml/mappings/src/main/java/demo/Application.java @@ -0,0 +1,163 @@ +package demo; + +import javax.servlet.Filter; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.context.embedded.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ImportResource; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService; +import org.springframework.security.oauth2.provider.endpoint.WhitelabelApprovalEndpoint; +import org.springframework.security.oauth2.provider.endpoint.WhitelabelErrorEndpoint; +import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; +import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint; +import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler; +import org.springframework.security.oauth2.provider.token.DefaultTokenServices; +import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.access.AccessDeniedHandler; +import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Configuration +@ComponentScan +@EnableAutoConfiguration +@RestController +@ImportResource("classpath:/application.xml") +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + @RequestMapping("/") + public String home() { + return "Hello World"; + } + + @Configuration + protected static class OAuth2Config { + + @Autowired + private ClientDetailsService clientDetailsService; + + @Bean + public DefaultTokenServices tokenServices() { + DefaultTokenServices services = new DefaultTokenServices(); + services.setClientDetailsService(clientDetailsService); + services.setSupportRefreshToken(true); + services.setTokenStore(new InMemoryTokenStore()); + return services; + } + + @Bean + public WhitelabelErrorEndpoint oauth2ErrorEndpoint() { + return new WhitelabelErrorEndpoint(); + } + + @Bean + public WhitelabelApprovalEndpoint oauth2ApprovalEndpoint() { + return new WhitelabelApprovalEndpoint(); + } + + } + + @Configuration + protected static class ResourceServer extends WebSecurityConfigurerAdapter { + + @Autowired + @Qualifier("resourceFilter") + private Filter resourceFilter; + + @Bean + public FilterRegistrationBean resourceFilterRegistration() { + FilterRegistrationBean bean = new FilterRegistrationBean(); + bean.setFilter(resourceFilter); + bean.setEnabled(false); + return bean; + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http.addFilterBefore(resourceFilter, AbstractPreAuthenticatedProcessingFilter.class) + // Just for laughs, apply OAuth protection to only 2 resources + .requestMatchers().antMatchers("/","/admin/beans") + .and() + .authorizeRequests() + .anyRequest().access("#oauth2.hasScope('read')").expressionHandler(new OAuth2WebSecurityExpressionHandler()) + .and() + .anonymous().disable() + .csrf().disable() + .exceptionHandling() + .authenticationEntryPoint(new OAuth2AuthenticationEntryPoint()) + .accessDeniedHandler(new OAuth2AccessDeniedHandler()); + // @formatter:on + } + + } + + @Configuration + @Order(Ordered.HIGHEST_PRECEDENCE) + protected static class TokenEndpointSecurity extends WebSecurityConfigurerAdapter { + + @Autowired + private ClientDetailsService clientDetailsService; + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.userDetailsService(clientDetailsUserService()); + } + + @Bean + protected UserDetailsService clientDetailsUserService() { + return new ClientDetailsUserDetailsService(clientDetailsService); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http.anonymous().disable() + .antMatcher("/token") + .authorizeRequests().anyRequest().authenticated() + .and() + .httpBasic().authenticationEntryPoint(authenticationEntryPoint()) + .and() + .csrf().requireCsrfProtectionMatcher(new AntPathRequestMatcher("/token")).disable() + .exceptionHandling().accessDeniedHandler(accessDeniedHandler()) + .and() + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); + // @formatter:on + } + + @Bean + protected AccessDeniedHandler accessDeniedHandler() { + return new OAuth2AccessDeniedHandler(); + } + + @Bean + protected AuthenticationEntryPoint authenticationEntryPoint() { + OAuth2AuthenticationEntryPoint entryPoint = new OAuth2AuthenticationEntryPoint(); + entryPoint.setTypeName("Basic"); + entryPoint.setRealmName("oauth2/client"); + return entryPoint; + } + + } + +} diff --git a/tests/xml/mappings/src/main/resources/application.xml b/tests/xml/mappings/src/main/resources/application.xml new file mode 100644 index 000000000..ff0f8820d --- /dev/null +++ b/tests/xml/mappings/src/main/resources/application.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/tests/xml/mappings/src/main/resources/application.yml b/tests/xml/mappings/src/main/resources/application.yml new file mode 100644 index 000000000..ffdf6ad3b --- /dev/null +++ b/tests/xml/mappings/src/main/resources/application.yml @@ -0,0 +1,14 @@ +spring: + application: + name: mappings +management: + context_path: /admin +security: + user: + password: password + +oauth: + paths: + token: /token + authorize: /authorize + confirm: forward:/approve \ No newline at end of file diff --git a/tests/xml/mappings/src/test/java/demo/ApplicationTests.java b/tests/xml/mappings/src/test/java/demo/ApplicationTests.java new file mode 100644 index 000000000..8da63b411 --- /dev/null +++ b/tests/xml/mappings/src/test/java/demo/ApplicationTests.java @@ -0,0 +1,20 @@ +package demo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = Application.class) +@WebAppConfiguration +@ActiveProfiles("test") +public class ApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/tests/xml/mappings/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/xml/mappings/src/test/java/demo/AuthorizationCodeProviderTests.java new file mode 100755 index 000000000..36e02d25f --- /dev/null +++ b/tests/xml/mappings/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -0,0 +1,51 @@ +/* + * Copyright 2006-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 demo; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +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; + +import sparklr.common.AbstractAuthorizationCodeProviderTests; + +/** + * @author Dave Syer + */ +@SpringApplicationConfiguration(classes = Application.class) +public class AuthorizationCodeProviderTests extends AbstractAuthorizationCodeProviderTests { + + @Test + @OAuth2ContextConfiguration(resource = MyClientWithRegisteredRedirect.class, initialize = false) + public void testInsufficientScopeInResourceRequest() throws Exception { + AuthorizationCodeResourceDetails resource = (AuthorizationCodeResourceDetails) context.getResource(); + resource.setScope(Arrays.asList("trust")); + approveAccessTokenGrant("http://anywhere/?key=value", true); + assertNotNull(context.getAccessToken()); + try { + http.getForString("/admin/beans"); + fail("Should have thrown exception"); + } + catch (InsufficientScopeException ex) { + assertTrue("Wrong summary: " + ex, ex.getSummary().contains("scope=\"read")); + } + } + +} diff --git a/tests/xml/mappings/src/test/java/demo/ClientCredentialsProviderTests.java b/tests/xml/mappings/src/test/java/demo/ClientCredentialsProviderTests.java new file mode 100644 index 000000000..af8190074 --- /dev/null +++ b/tests/xml/mappings/src/test/java/demo/ClientCredentialsProviderTests.java @@ -0,0 +1,14 @@ +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/xml/mappings/src/test/java/demo/ImplicitProviderTests.java b/tests/xml/mappings/src/test/java/demo/ImplicitProviderTests.java new file mode 100644 index 000000000..7a8958187 --- /dev/null +++ b/tests/xml/mappings/src/test/java/demo/ImplicitProviderTests.java @@ -0,0 +1,13 @@ +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/xml/mappings/src/test/java/demo/ProtectedResourceTests.java b/tests/xml/mappings/src/test/java/demo/ProtectedResourceTests.java new file mode 100644 index 000000000..743d9158b --- /dev/null +++ b/tests/xml/mappings/src/test/java/demo/ProtectedResourceTests.java @@ -0,0 +1,41 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package demo; + +import static org.junit.Assert.assertEquals; +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 sparklr.common.AbstractProtectedResourceTests; + +/** + * @author Dave Syer + * + */ +@SpringApplicationConfiguration(classes = Application.class) +public class ProtectedResourceTests extends AbstractProtectedResourceTests { + + @Test + public void testDumpResourceIsProtected() throws Exception { + ResponseEntity response = http.getForString("/admin/dump"); + assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); + assertTrue("Wrong header: " + response.getHeaders(), response.getHeaders().getFirst("WWW-Authenticate") + .startsWith("Basic realm=")); + } + +} diff --git a/tests/xml/mappings/src/test/java/demo/RefreshTokenSupportTests.java b/tests/xml/mappings/src/test/java/demo/RefreshTokenSupportTests.java new file mode 100644 index 000000000..4ed370eea --- /dev/null +++ b/tests/xml/mappings/src/test/java/demo/RefreshTokenSupportTests.java @@ -0,0 +1,13 @@ +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/xml/mappings/src/test/java/demo/ResourceOwnerPasswordProviderTests.java b/tests/xml/mappings/src/test/java/demo/ResourceOwnerPasswordProviderTests.java new file mode 100644 index 000000000..aa5786098 --- /dev/null +++ b/tests/xml/mappings/src/test/java/demo/ResourceOwnerPasswordProviderTests.java @@ -0,0 +1,13 @@ +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/xml/mappings/src/test/resources/test.properties b/tests/xml/mappings/src/test/resources/test.properties new file mode 100644 index 000000000..73bcdecd2 --- /dev/null +++ b/tests/xml/mappings/src/test/resources/test.properties @@ -0,0 +1 @@ +server.port: 0 diff --git a/tests/xml/pom.xml b/tests/xml/pom.xml new file mode 100644 index 000000000..b8ecb640c --- /dev/null +++ b/tests/xml/pom.xml @@ -0,0 +1,130 @@ + + + 4.0.0 + + org.demo + spring-oauth2-tests-xml-parent + 2.0.2.RELEASE + pom + + + common + vanilla + mappings + form + jwt + approval + jdbc + client + + + spring-oauth2-tests-xml + Demo project for OAuth2 and Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 1.1.0.RELEASE + + + + + + org.springframework.security.oauth + spring-security-oauth2 + 2.0.2.RELEASE + + + jackson-mapper-asl + org.codehaus.jackson + + + + + org.springframework.security + spring-security-jwt + 1.0.1.RELEASE + + + + + + + + + maven-surefire-plugin + + + **/*Tests.java + + + **/Abstract*.java + + + file:/dev/./urandom + true + + -Xmx1024m -XX:MaxPermSize=256m + + + + + maven-deploy-plugin + + true + + + + + + + + demo.Application + 1.7 + + + + + spring-snapshots + Spring Snapshots + http://repo.spring.io/snapshot + + true + + + + spring-milestones + Spring Milestones + http://repo.spring.io/milestone + + false + + + + spring-staging + Spring Milestones + http://repo.spring.io/libs-staging-local + + false + + + + + + spring-snapshots + Spring Snapshots + http://repo.spring.io/snapshot + + true + + + + spring-staging + Spring Milestones + http://repo.spring.io/libs-staging-local + + false + + + + diff --git a/tests/xml/vanilla/README.md b/tests/xml/vanilla/README.md new file mode 100644 index 000000000..acb89fbf6 --- /dev/null +++ b/tests/xml/vanilla/README.md @@ -0,0 +1,18 @@ +This project shows what you can do with the minimum configuration to +set up an Authorization Server and Resource Server. + +For the Authorization Server you need to `@EnableAuthorizationServer` +and also configure at least one client registration +(`OAuth2ClientDetails`). You can see this is the bulk of +`Application.java`. + +An `AuthenticationManager` is created by Spring Boot (it has a single +user, named "user", with password "password", per +`application.yml`). It is needed in the Authorization Server to +provide authentication for the Resource Owner Password grant type. + +For the Resource Server all that is needed is the +`@EnableResourceServer` annotation. By default it protects all +resources that are not explicitly ignored and not exposed by the +`AuthorizationEndpoint` (if there is an Authorization Server in the +same application). diff --git a/tests/xml/vanilla/pom.xml b/tests/xml/vanilla/pom.xml new file mode 100644 index 000000000..0e6f22d5d --- /dev/null +++ b/tests/xml/vanilla/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + + spring-oauth2-tests-xml-vanilla + + spring-oauth2-tests-xml-vanilla + Demo project + + + org.demo + spring-oauth2-tests-xml-parent + 2.0.2.RELEASE + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.security.oauth + spring-security-oauth2 + + + org.demo + spring-oauth2-tests-xml-common + ${project.version} + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/tests/xml/vanilla/src/main/java/demo/Application.java b/tests/xml/vanilla/src/main/java/demo/Application.java new file mode 100644 index 000000000..64c1a39ec --- /dev/null +++ b/tests/xml/vanilla/src/main/java/demo/Application.java @@ -0,0 +1,162 @@ +package demo; + +import javax.servlet.Filter; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.context.embedded.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ImportResource; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService; +import org.springframework.security.oauth2.provider.endpoint.WhitelabelApprovalEndpoint; +import org.springframework.security.oauth2.provider.endpoint.WhitelabelErrorEndpoint; +import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; +import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint; +import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler; +import org.springframework.security.oauth2.provider.token.DefaultTokenServices; +import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.access.AccessDeniedHandler; +import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.util.matcher.NegatedRequestMatcher; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Configuration +@ComponentScan +@EnableAutoConfiguration +@RestController +@ImportResource("classpath:/application.xml") +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + @RequestMapping("/") + public String home() { + return "Hello World"; + } + + @Configuration + protected static class OAuth2Config { + + @Autowired + private ClientDetailsService clientDetailsService; + + @Bean + public DefaultTokenServices tokenServices() { + DefaultTokenServices services = new DefaultTokenServices(); + services.setClientDetailsService(clientDetailsService); + services.setSupportRefreshToken(true); + services.setTokenStore(new InMemoryTokenStore()); + return services; + } + + @Bean + public WhitelabelErrorEndpoint oauth2ErrorEndpoint() { + return new WhitelabelErrorEndpoint(); + } + + @Bean + public WhitelabelApprovalEndpoint oauth2ApprovalEndpoint() { + return new WhitelabelApprovalEndpoint(); + } + + } + + @Configuration + protected static class ResourceServer extends WebSecurityConfigurerAdapter { + + @Autowired + @Qualifier("resourceFilter") + private Filter resourceFilter; + + @Bean + public FilterRegistrationBean resourceFilterRegistration() { + FilterRegistrationBean bean = new FilterRegistrationBean(); + bean.setFilter(resourceFilter); + bean.setEnabled(false); + return bean; + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http.addFilterBefore(resourceFilter, AbstractPreAuthenticatedProcessingFilter.class) + .requestMatcher(new NegatedRequestMatcher(new AntPathRequestMatcher("/oauth/**"))) + .authorizeRequests().anyRequest().authenticated().expressionHandler(new OAuth2WebSecurityExpressionHandler()) + .and() + .anonymous().disable() + .csrf().disable() + .exceptionHandling() + .authenticationEntryPoint(new OAuth2AuthenticationEntryPoint()) + .accessDeniedHandler(new OAuth2AccessDeniedHandler()); + // @formatter:on + } + + + } + + @Configuration + @Order(Ordered.HIGHEST_PRECEDENCE) + protected static class TokenEndpointSecurity extends WebSecurityConfigurerAdapter { + + @Autowired + private ClientDetailsService clientDetailsService; + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.userDetailsService(clientDetailsUserService()); + } + + @Bean + protected UserDetailsService clientDetailsUserService() { + return new ClientDetailsUserDetailsService(clientDetailsService); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http.anonymous().disable() + .antMatcher("/oauth/token") + .authorizeRequests().anyRequest().authenticated() + .and() + .httpBasic().authenticationEntryPoint(authenticationEntryPoint()) + .and() + .csrf().requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/token")).disable() + .exceptionHandling().accessDeniedHandler(accessDeniedHandler()) + .and() + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); + // @formatter:on + } + + @Bean + protected AccessDeniedHandler accessDeniedHandler() { + return new OAuth2AccessDeniedHandler(); + } + + @Bean + protected AuthenticationEntryPoint authenticationEntryPoint() { + OAuth2AuthenticationEntryPoint entryPoint = new OAuth2AuthenticationEntryPoint(); + entryPoint.setTypeName("Basic"); + entryPoint.setRealmName("oauth2/client"); + return entryPoint; + } + + } + +} diff --git a/tests/xml/vanilla/src/main/resources/application.xml b/tests/xml/vanilla/src/main/resources/application.xml new file mode 100644 index 000000000..fd38cb4c0 --- /dev/null +++ b/tests/xml/vanilla/src/main/resources/application.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/tests/xml/vanilla/src/main/resources/application.yml b/tests/xml/vanilla/src/main/resources/application.yml new file mode 100644 index 000000000..a9c0149f0 --- /dev/null +++ b/tests/xml/vanilla/src/main/resources/application.yml @@ -0,0 +1,8 @@ +spring: + application: + name: vanilla +management: + context_path: /admin +security: + user: + password: password diff --git a/tests/xml/vanilla/src/test/java/demo/ApplicationTests.java b/tests/xml/vanilla/src/test/java/demo/ApplicationTests.java new file mode 100644 index 000000000..8da63b411 --- /dev/null +++ b/tests/xml/vanilla/src/test/java/demo/ApplicationTests.java @@ -0,0 +1,20 @@ +package demo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = Application.class) +@WebAppConfiguration +@ActiveProfiles("test") +public class ApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/tests/xml/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/xml/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java new file mode 100755 index 000000000..632098bf1 --- /dev/null +++ b/tests/xml/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -0,0 +1,25 @@ +/* + * Copyright 2006-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 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/xml/vanilla/src/test/java/demo/ClientCredentialsProviderTests.java b/tests/xml/vanilla/src/test/java/demo/ClientCredentialsProviderTests.java new file mode 100644 index 000000000..af8190074 --- /dev/null +++ b/tests/xml/vanilla/src/test/java/demo/ClientCredentialsProviderTests.java @@ -0,0 +1,14 @@ +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/xml/vanilla/src/test/java/demo/ImplicitProviderTests.java b/tests/xml/vanilla/src/test/java/demo/ImplicitProviderTests.java new file mode 100644 index 000000000..7a8958187 --- /dev/null +++ b/tests/xml/vanilla/src/test/java/demo/ImplicitProviderTests.java @@ -0,0 +1,13 @@ +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/xml/vanilla/src/test/java/demo/ProtectedResourceTests.java b/tests/xml/vanilla/src/test/java/demo/ProtectedResourceTests.java new file mode 100644 index 000000000..c752cbe12 --- /dev/null +++ b/tests/xml/vanilla/src/test/java/demo/ProtectedResourceTests.java @@ -0,0 +1,27 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package 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/xml/vanilla/src/test/java/demo/RefreshTokenSupportTests.java b/tests/xml/vanilla/src/test/java/demo/RefreshTokenSupportTests.java new file mode 100644 index 000000000..4ed370eea --- /dev/null +++ b/tests/xml/vanilla/src/test/java/demo/RefreshTokenSupportTests.java @@ -0,0 +1,13 @@ +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/xml/vanilla/src/test/java/demo/ResourceOwnerPasswordProviderTests.java b/tests/xml/vanilla/src/test/java/demo/ResourceOwnerPasswordProviderTests.java new file mode 100644 index 000000000..aa5786098 --- /dev/null +++ b/tests/xml/vanilla/src/test/java/demo/ResourceOwnerPasswordProviderTests.java @@ -0,0 +1,13 @@ +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/xml/vanilla/src/test/resources/test.properties b/tests/xml/vanilla/src/test/resources/test.properties new file mode 100644 index 000000000..24466e50d --- /dev/null +++ b/tests/xml/vanilla/src/test/resources/test.properties @@ -0,0 +1 @@ +server.port: 0 \ No newline at end of file From 5a6a06817c3f09a3ce7c6e8c02bca71221c183ce Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 11 Jun 2014 09:20:02 +0100 Subject: [PATCH 271/831] Update to new dev version --- pom.xml | 2 +- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- tests/annotation/approval/pom.xml | 2 +- tests/annotation/client/pom.xml | 2 +- tests/annotation/common/pom.xml | 2 +- tests/annotation/form/pom.xml | 2 +- tests/annotation/jdbc/pom.xml | 2 +- tests/annotation/jwt/pom.xml | 2 +- tests/annotation/mappings/pom.xml | 2 +- tests/annotation/multi/pom.xml | 2 +- tests/annotation/pom.xml | 4 ++-- tests/annotation/resource/pom.xml | 2 +- tests/annotation/vanilla/pom.xml | 2 +- tests/pom.xml | 2 +- tests/xml/approval/pom.xml | 2 +- tests/xml/client/pom.xml | 2 +- tests/xml/common/pom.xml | 2 +- tests/xml/form/pom.xml | 2 +- tests/xml/jdbc/pom.xml | 2 +- tests/xml/jwt/pom.xml | 2 +- tests/xml/mappings/pom.xml | 2 +- tests/xml/pom.xml | 4 ++-- tests/xml/vanilla/pom.xml | 2 +- 29 files changed, 31 insertions(+), 31 deletions(-) diff --git a/pom.xml b/pom.xml index e0d6095d3..40013db3f 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.2.RELEASE + 2.0.3.BUILD-SNAPSHOT http://static.springframework.org/spring-security/oauth diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index 6ac6f16fe..5aaf4e074 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.2.RELEASE + 2.0.3.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index 5208ef565..2436e03b9 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.2.RELEASE + 2.0.3.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 55c42c466..652bd4424 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.2.RELEASE + 2.0.3.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 270ea6a02..f109dd729 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.2.RELEASE + 2.0.3.BUILD-SNAPSHOT ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index 279338864..53fd71e85 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.2.RELEASE + 2.0.3.BUILD-SNAPSHOT spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index 472897cae..c38f0e7bb 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.2.RELEASE + 2.0.3.BUILD-SNAPSHOT spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 8ca0e0188..616885aea 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.2.RELEASE + 2.0.3.BUILD-SNAPSHOT spring-security-oauth2 diff --git a/tests/annotation/approval/pom.xml b/tests/annotation/approval/pom.xml index 6b004eedd..b1f4eceef 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.2.RELEASE + 2.0.3.BUILD-SNAPSHOT diff --git a/tests/annotation/client/pom.xml b/tests/annotation/client/pom.xml index 4fe123979..cf2b1255d 100644 --- a/tests/annotation/client/pom.xml +++ b/tests/annotation/client/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.0.2.RELEASE + 2.0.3.BUILD-SNAPSHOT diff --git a/tests/annotation/common/pom.xml b/tests/annotation/common/pom.xml index f60499b23..90cdbc051 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.2.RELEASE + 2.0.3.BUILD-SNAPSHOT diff --git a/tests/annotation/form/pom.xml b/tests/annotation/form/pom.xml index 89a0fc3f4..83a161a51 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.2.RELEASE + 2.0.3.BUILD-SNAPSHOT diff --git a/tests/annotation/jdbc/pom.xml b/tests/annotation/jdbc/pom.xml index 4f9fe30d6..b467bb083 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.2.RELEASE + 2.0.3.BUILD-SNAPSHOT diff --git a/tests/annotation/jwt/pom.xml b/tests/annotation/jwt/pom.xml index 2b64d7d45..af8cb1bc3 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.2.RELEASE + 2.0.3.BUILD-SNAPSHOT diff --git a/tests/annotation/mappings/pom.xml b/tests/annotation/mappings/pom.xml index 7a66dde14..db5246d9c 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.2.RELEASE + 2.0.3.BUILD-SNAPSHOT diff --git a/tests/annotation/multi/pom.xml b/tests/annotation/multi/pom.xml index 81c3e9feb..dce5cd5b4 100644 --- a/tests/annotation/multi/pom.xml +++ b/tests/annotation/multi/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.0.2.RELEASE + 2.0.3.BUILD-SNAPSHOT diff --git a/tests/annotation/pom.xml b/tests/annotation/pom.xml index 9043c5948..5a342d427 100644 --- a/tests/annotation/pom.xml +++ b/tests/annotation/pom.xml @@ -4,7 +4,7 @@ org.demo spring-oauth2-tests-parent - 2.0.2.RELEASE + 2.0.3.BUILD-SNAPSHOT pom @@ -34,7 +34,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.0.2.RELEASE + 2.0.3.BUILD-SNAPSHOT jackson-mapper-asl diff --git a/tests/annotation/resource/pom.xml b/tests/annotation/resource/pom.xml index ea7f66f2c..d369d92dc 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.2.RELEASE + 2.0.3.BUILD-SNAPSHOT diff --git a/tests/annotation/vanilla/pom.xml b/tests/annotation/vanilla/pom.xml index d5eaf3e2e..bcc9e0e40 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.2.RELEASE + 2.0.3.BUILD-SNAPSHOT diff --git a/tests/pom.xml b/tests/pom.xml index f0a503e1d..22c71cf71 100644 --- a/tests/pom.xml +++ b/tests/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.2.RELEASE + 2.0.3.BUILD-SNAPSHOT spring-security-oauth-tests diff --git a/tests/xml/approval/pom.xml b/tests/xml/approval/pom.xml index 2145afa1b..38be519c2 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.2.RELEASE + 2.0.3.BUILD-SNAPSHOT diff --git a/tests/xml/client/pom.xml b/tests/xml/client/pom.xml index a43aec0a7..3487371b9 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.2.RELEASE + 2.0.3.BUILD-SNAPSHOT diff --git a/tests/xml/common/pom.xml b/tests/xml/common/pom.xml index 50f03c395..afc5be7c8 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.2.RELEASE + 2.0.3.BUILD-SNAPSHOT diff --git a/tests/xml/form/pom.xml b/tests/xml/form/pom.xml index 444a0e50c..b54641236 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.2.RELEASE + 2.0.3.BUILD-SNAPSHOT diff --git a/tests/xml/jdbc/pom.xml b/tests/xml/jdbc/pom.xml index a1f36b357..ec8fc8c87 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.2.RELEASE + 2.0.3.BUILD-SNAPSHOT diff --git a/tests/xml/jwt/pom.xml b/tests/xml/jwt/pom.xml index 7e2b6c0a7..f81eead5e 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.2.RELEASE + 2.0.3.BUILD-SNAPSHOT diff --git a/tests/xml/mappings/pom.xml b/tests/xml/mappings/pom.xml index 64e170382..fb0ed638e 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.2.RELEASE + 2.0.3.BUILD-SNAPSHOT diff --git a/tests/xml/pom.xml b/tests/xml/pom.xml index b8ecb640c..b71183ab9 100644 --- a/tests/xml/pom.xml +++ b/tests/xml/pom.xml @@ -4,7 +4,7 @@ org.demo spring-oauth2-tests-xml-parent - 2.0.2.RELEASE + 2.0.3.BUILD-SNAPSHOT pom @@ -32,7 +32,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.0.2.RELEASE + 2.0.3.BUILD-SNAPSHOT jackson-mapper-asl diff --git a/tests/xml/vanilla/pom.xml b/tests/xml/vanilla/pom.xml index 0e6f22d5d..4b93f2f1c 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.2.RELEASE + 2.0.3.BUILD-SNAPSHOT From c439a431788ab4ec638f0bc03f34541d5bac8458 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 12 Jun 2014 11:05:53 +0100 Subject: [PATCH 272/831] Added prefix() to AuthorizationServerEndpointsConfigurer If user has DispatcherServlet mapped to a different servlet path (i.e. not the root /) then he also needs a way to tell that to the AuthorizationServer. This method provides that feature. Tested in tests/annotation/mappings Fixes gh-214 --- ...horizationServerSecurityConfiguration.java | 6 +-- ...uthorizationServerEndpointsConfigurer.java | 8 ++++ ...AuthorizationServerSecurityConfigurer.java | 2 +- .../FrameworkEndpointHandlerMapping.java | 22 ++++++++++ ...bstractAuthorizationCodeProviderTests.java | 3 -- ...bstractClientCredentialsProviderTests.java | 6 --- .../common/AbstractImplicitProviderTests.java | 3 -- .../common/AbstractIntegrationTests.java | 26 +++++++++++- ...actResourceOwnerPasswordProviderTests.java | 2 - .../java/sparklr/common/HttpTestUtils.java | 41 ++++++++----------- .../src/main/java/demo/Application.java | 6 +++ .../demo/ClientCredentialsProviderTests.java | 3 +- ...letPathClientCredentialsProviderTests.java | 32 +++++++++++++++ .../test/java/demo/ImplicitProviderTests.java | 2 - 14 files changed, 114 insertions(+), 48 deletions(-) create mode 100644 tests/annotation/mappings/src/test/java/demo/ServletPathClientCredentialsProviderTests.java diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java index 161c9f5a6..2f235baa8 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java @@ -69,9 +69,9 @@ protected void configure(HttpSecurity http) throws Exception { http.setSharedObject(FrameworkEndpointHandlerMapping.class, handlerMapping); configure(configurer); http.apply(configurer); - String tokenEndpointPath = handlerMapping.getPath("/oauth/token"); - String tokenKeyPath = handlerMapping.getPath("/oauth/token_key"); - String checkTokenPath = handlerMapping.getPath("/oauth/check_token"); + String tokenEndpointPath = handlerMapping.getServletPath("/oauth/token"); + String tokenKeyPath = handlerMapping.getServletPath("/oauth/token_key"); + String checkTokenPath = handlerMapping.getServletPath("/oauth/check_token"); // @formatter:off http .authorizeRequests() 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 db6988c99..2f8275773 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 @@ -92,6 +92,8 @@ public final class AuthorizationServerEndpointsConfigurer { private AuthenticationManager authenticationManager; private ClientDetailsService clientDetailsService; + + private String prefix; private Map patternMap = new HashMap(); @@ -175,6 +177,11 @@ public AuthorizationServerEndpointsConfigurer approvalStoreDisabled() { return this; } + public AuthorizationServerEndpointsConfigurer prefix(String prefix) { + this.prefix = prefix; + return this; + } + public AuthorizationServerEndpointsConfigurer pathMapping(String defaultPath, String customPath) { this.patternMap.put(defaultPath, customPath); return this; @@ -401,6 +408,7 @@ private FrameworkEndpointHandlerMapping frameworkEndpointHandlerMapping() { if (frameworkEndpointHandlerMapping == null) { frameworkEndpointHandlerMapping = new FrameworkEndpointHandlerMapping(); frameworkEndpointHandlerMapping.setMappings(patternMap); + frameworkEndpointHandlerMapping.setPrefix(prefix); frameworkEndpointHandlerMapping.setInterceptors(interceptors .toArray()); } return frameworkEndpointHandlerMapping; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java index 40e5c5cf4..9da067e87 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java @@ -133,7 +133,7 @@ public void configure(HttpSecurity http) throws Exception { private ClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilter(HttpSecurity http) { ClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilter = new ClientCredentialsTokenEndpointFilter( - frameworkEndpointHandlerMapping().getPath("/oauth/token")); + frameworkEndpointHandlerMapping().getServletPath("/oauth/token")); clientCredentialsTokenEndpointFilter .setAuthenticationManager(http.getSharedObject(AuthenticationManager.class)); clientCredentialsTokenEndpointFilter = postProcess(clientCredentialsTokenEndpointFilter); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java index ccae70d93..a3b133af2 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java @@ -23,6 +23,7 @@ import org.springframework.core.annotation.AnnotationUtils; import org.springframework.security.oauth2.common.util.OAuth2Utils; import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.util.StringUtils; import org.springframework.web.servlet.mvc.condition.NameValueExpression; import org.springframework.web.servlet.mvc.condition.ParamsRequestCondition; import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition; @@ -48,6 +49,20 @@ public class FrameworkEndpointHandlerMapping extends RequestMappingHandlerMappin private Set paths = new HashSet(); + private String prefix; + + /** + * @param prefix the prefix to set + */ + public void setPrefix(String prefix) { + if (!StringUtils.hasText(prefix)) { + prefix = ""; + } else while (prefix.endsWith("/")) { + prefix = prefix.substring(0, prefix.lastIndexOf("/")); + } + this.prefix = prefix; + } + /** * Custom mappings for framework endpoint paths. The keys in the map are the default framework endpoint path, e.g. * "/oauth/authorize", and the values are the desired runtime paths. @@ -68,6 +83,13 @@ public void setMappings(Map patternMap) { } } + /** + * @return the mapping from default endpoint paths to custom ones (or the default if no customization is known) + */ + public String getServletPath(String defaultPath) { + return (prefix == null ? "" : prefix ) + getPath(defaultPath); + } + /** * @return the mapping from default endpoint paths to custom ones (or the default if no customization is known) */ diff --git a/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java b/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java index bcebe3a2d..8a9610a4e 100755 --- a/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java @@ -414,9 +414,6 @@ public MyTrustedClient(Object target) { setClientId("my-trusted-client"); setScope(Arrays.asList("read")); setId(getClientId()); - AbstractAuthorizationCodeProviderTests test = (AbstractAuthorizationCodeProviderTests) target; - setAccessTokenUri(test.http.getUrl(tokenPath())); - setUserAuthorizationUri(test.http.getUrl(authorizePath())); } } diff --git a/tests/annotation/common/src/main/java/sparklr/common/AbstractClientCredentialsProviderTests.java b/tests/annotation/common/src/main/java/sparklr/common/AbstractClientCredentialsProviderTests.java index 9b273e600..1f58b814d 100644 --- a/tests/annotation/common/src/main/java/sparklr/common/AbstractClientCredentialsProviderTests.java +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractClientCredentialsProviderTests.java @@ -84,8 +84,6 @@ public ClientCredentials(Object target) { setClientSecret("secret"); setScope(Arrays.asList("read")); setId(getClientId()); - AbstractClientCredentialsProviderTests test = (AbstractClientCredentialsProviderTests) target; - setAccessTokenUri(test.http.getUrl(tokenPath())); } } @@ -95,8 +93,6 @@ public TrustedClientCredentials(Object target) { setClientId("my-truusted-client"); setScope(Arrays.asList("read")); setId(getClientId()); - AbstractClientCredentialsProviderTests test = (AbstractClientCredentialsProviderTests) target; - setAccessTokenUri(test.http.getUrl(tokenPath())); } } @@ -113,8 +109,6 @@ public NoScopeClientCredentials(Object target) { setClientId("my-client-with-secret"); setClientSecret("secret"); setId(getClientId()); - AbstractClientCredentialsProviderTests test = (AbstractClientCredentialsProviderTests) target; - setAccessTokenUri(test.http.getUrl(tokenPath())); } } diff --git a/tests/annotation/common/src/main/java/sparklr/common/AbstractImplicitProviderTests.java b/tests/annotation/common/src/main/java/sparklr/common/AbstractImplicitProviderTests.java index 2f0cf9cc9..5e1c47d55 100644 --- a/tests/annotation/common/src/main/java/sparklr/common/AbstractImplicitProviderTests.java +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractImplicitProviderTests.java @@ -43,9 +43,6 @@ public NonAutoApproveImplicit(Object target) { setClientId("my-trusted-client"); setId(getClientId()); setPreEstablishedRedirectUri("http://anywhere/"); - AbstractImplicitProviderTests test = (AbstractImplicitProviderTests) target; - setAccessTokenUri(test.http.getUrl(authorizePath())); - setUserAuthorizationUri(test.http.getUrl(authorizePath())); } } 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 70b5e21f9..b78763e89 100644 --- a/tests/annotation/common/src/main/java/sparklr/common/AbstractIntegrationTests.java +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractIntegrationTests.java @@ -21,13 +21,18 @@ import org.springframework.aop.framework.Advised; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.context.embedded.EmbeddedWebApplicationContext; import org.springframework.boot.test.IntegrationTest; import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.security.oauth2.client.resource.BaseOAuth2ProtectedResourceDetails; +import org.springframework.security.oauth2.client.test.BeforeOAuth2Context; import org.springframework.security.oauth2.client.test.OAuth2ContextSetup; +import org.springframework.security.oauth2.client.token.grant.implicit.ImplicitResourceDetails; +import org.springframework.security.oauth2.client.token.grant.redirect.AbstractRedirectResourceDetails; import org.springframework.security.oauth2.provider.approval.ApprovalStore; import org.springframework.security.oauth2.provider.approval.InMemoryApprovalStore; import org.springframework.security.oauth2.provider.approval.JdbcApprovalStore; @@ -60,7 +65,7 @@ public abstract class AbstractIntegrationTests implements PortHolder { public OAuth2ContextSetup context = OAuth2ContextSetup.standard(http); @Autowired - private EmbeddedWebApplicationContext server; + private EmbeddedWebApplicationContext container; @Autowired(required = false) private TokenStore tokenStore; @@ -73,7 +78,24 @@ public abstract class AbstractIntegrationTests implements PortHolder { @Override public int getPort() { - return server == null ? 8080 : server.getEmbeddedServletContainer().getPort(); + return container == null ? 8080 : container.getEmbeddedServletContainer().getPort(); + } + + @Autowired + private ServerProperties server; + + @BeforeOAuth2Context + public void fixPaths() { + String prefix = server.getServletPrefix(); + http.setPrefix(prefix); + BaseOAuth2ProtectedResourceDetails resource = (BaseOAuth2ProtectedResourceDetails) context.getResource(); + resource.setAccessTokenUri(http.getUrl(tokenPath())); + if (resource instanceof AbstractRedirectResourceDetails) { + ((AbstractRedirectResourceDetails) resource).setUserAuthorizationUri(http.getUrl(authorizePath())); + } + if (resource instanceof ImplicitResourceDetails) { + resource.setAccessTokenUri(http.getUrl(authorizePath())); + } } @After diff --git a/tests/annotation/common/src/main/java/sparklr/common/AbstractResourceOwnerPasswordProviderTests.java b/tests/annotation/common/src/main/java/sparklr/common/AbstractResourceOwnerPasswordProviderTests.java index 319c19f67..2e881d956 100644 --- a/tests/annotation/common/src/main/java/sparklr/common/AbstractResourceOwnerPasswordProviderTests.java +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractResourceOwnerPasswordProviderTests.java @@ -216,8 +216,6 @@ public ResourceOwner(Object target) { setId(getClientId()); setUsername("user"); setPassword("password"); - AbstractResourceOwnerPasswordProviderTests test = (AbstractResourceOwnerPasswordProviderTests) target; - setAccessTokenUri(test.http.getUrl(tokenPath())); } } 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 2b3cb220c..f27baa146 100644 --- a/tests/annotation/common/src/main/java/sparklr/common/HttpTestUtils.java +++ b/tests/annotation/common/src/main/java/sparklr/common/HttpTestUtils.java @@ -1,14 +1,11 @@ package sparklr.common; -import java.net.HttpURLConnection; import java.net.URI; import java.util.Arrays; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.junit.rules.MethodRule; import org.junit.runners.model.FrameworkMethod; import org.junit.runners.model.Statement; @@ -21,7 +18,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.security.oauth2.client.test.RestTemplateHolder; import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestClientException; +import org.springframework.util.StringUtils; import org.springframework.web.client.RestOperations; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriTemplate; @@ -37,8 +34,6 @@ */ public class HttpTestUtils implements MethodRule, RestTemplateHolder { - private static Log logger = LogFactory.getLog(HttpTestUtils.class); - private static int DEFAULT_PORT = 8080; private static String DEFAULT_HOST = "localhost"; @@ -51,6 +46,8 @@ public class HttpTestUtils implements MethodRule, RestTemplateHolder { private PortHolder portHolder; + private String prefix = ""; + /** * @return a new rule that sets up default host and port etc. */ @@ -62,6 +59,18 @@ private HttpTestUtils() { setPort(DEFAULT_PORT); } + /** + * @param prefix + */ + public void setPrefix(String prefix) { + if (!StringUtils.hasText(prefix)) { + prefix = ""; + } else while (prefix.endsWith("/")) { + prefix = prefix.substring(0, prefix.lastIndexOf("/")); + } + this.prefix = prefix; + } + /** * @param port the port to set */ @@ -95,22 +104,6 @@ public Statement apply(final Statement base, FrameworkMethod method, Object targ setPort(portHolder.getPort()); } - RestTemplate client = new RestTemplate(); - boolean followRedirects = HttpURLConnection.getFollowRedirects(); - HttpURLConnection.setFollowRedirects(false); - try { - client.getForEntity(new UriTemplate(getUrl("/admin/info")).toString(), String.class); - logger.info("Basic connectivity test passed"); - } - catch (RestClientException e) { - logger.warn(String.format( - "Not executing tests because basic connectivity test failed for hostName=%s, port=%d", hostName, - port), e); - } - finally { - HttpURLConnection.setFollowRedirects(followRedirects); - } - return new Statement() { @Override public void evaluate() throws Throwable { @@ -121,7 +114,7 @@ public void evaluate() throws Throwable { } public String getBaseUrl() { - return "http://" + hostName + ":" + port; + return "http://" + hostName + ":" + port + prefix; } public String getUrl(String path) { @@ -131,7 +124,7 @@ public String getUrl(String path) { if (!path.startsWith("/")) { path = "/" + path; } - return "http://" + hostName + ":" + port + path; + return "http://" + hostName + ":" + port + prefix + path; } public ResponseEntity postForString(String path, MultiValueMap formData) { diff --git a/tests/annotation/mappings/src/main/java/demo/Application.java b/tests/annotation/mappings/src/main/java/demo/Application.java index d0821d2d3..b004a55ad 100644 --- a/tests/annotation/mappings/src/main/java/demo/Application.java +++ b/tests/annotation/mappings/src/main/java/demo/Application.java @@ -4,6 +4,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; @@ -79,6 +80,9 @@ protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter @Autowired private AuthenticationManager authenticationManager; + @Autowired + private ServerProperties server; + @Override public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { oauthServer.checkTokenAccess("hasRole('ROLE_TRUSTED_CLIENT')"); @@ -86,6 +90,8 @@ public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + String prefix = server.getServletPrefix(); + endpoints.prefix(prefix); // @formatter:off endpoints.authenticationManager(authenticationManager) .pathMapping("/oauth/confirm_access", confirmPath) diff --git a/tests/annotation/mappings/src/test/java/demo/ClientCredentialsProviderTests.java b/tests/annotation/mappings/src/test/java/demo/ClientCredentialsProviderTests.java index a514345e7..8c5a6ceac 100644 --- a/tests/annotation/mappings/src/test/java/demo/ClientCredentialsProviderTests.java +++ b/tests/annotation/mappings/src/test/java/demo/ClientCredentialsProviderTests.java @@ -25,8 +25,7 @@ */ @SpringApplicationConfiguration(classes=Application.class) public class ClientCredentialsProviderTests extends AbstractClientCredentialsProviderTests { - - + /** * tests the check_token endpoint */ diff --git a/tests/annotation/mappings/src/test/java/demo/ServletPathClientCredentialsProviderTests.java b/tests/annotation/mappings/src/test/java/demo/ServletPathClientCredentialsProviderTests.java new file mode 100644 index 000000000..dd85f62d4 --- /dev/null +++ b/tests/annotation/mappings/src/test/java/demo/ServletPathClientCredentialsProviderTests.java @@ -0,0 +1,32 @@ +package demo; + +import static org.junit.Assert.assertEquals; + +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.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +import sparklr.common.AbstractClientCredentialsProviderTests; + +/** + * @author Dave Syer + */ +@SpringApplicationConfiguration(classes=Application.class) +@IntegrationTest("server.servlet_path:/server") +public class ServletPathClientCredentialsProviderTests extends AbstractClientCredentialsProviderTests { + + @Test + public void testTokenKey() throws Exception { + @SuppressWarnings("rawtypes") + ResponseEntity response = new TestRestTemplate("my-client-with-secret", "secret").getForEntity( + http.getUrl(tokenKeyPath()), Map.class); + // This app has no token key. + assertEquals(HttpStatus.FORBIDDEN, response.getStatusCode()); + } + +} diff --git a/tests/annotation/vanilla/src/test/java/demo/ImplicitProviderTests.java b/tests/annotation/vanilla/src/test/java/demo/ImplicitProviderTests.java index cd17d9a0f..92379335a 100644 --- a/tests/annotation/vanilla/src/test/java/demo/ImplicitProviderTests.java +++ b/tests/annotation/vanilla/src/test/java/demo/ImplicitProviderTests.java @@ -68,8 +68,6 @@ public ResourceOwner(Object target) { setId(getClientId()); setUsername("user"); setPassword("password"); - AbstractImplicitProviderTests test = (AbstractImplicitProviderTests) target; - setAccessTokenUri(test.http.getUrl(tokenPath())); } } From 650c756349b8a9ebcb13787117657018aca2d51f Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 18 Jun 2014 10:42:49 +0100 Subject: [PATCH 273/831] Fix JDBC samples to ensure DataSource is initialized Ideally Spring Boot would initialize the data source for us (see https://github.com/spring-projects/spring-boot/issues/1115), but we can work around it with @DependsOn. The main new thing in this approach though is to use a GlobalAuthenticationConfigurerAdapter to configure the authentication manager (much better than using a WebSecurityConfigurerAdapter) Fixes gh-222 --- ...bstractAuthorizationCodeProviderTests.java | 3 +- .../common/AbstractImplicitProviderTests.java | 3 +- .../common/AbstractIntegrationTests.java | 16 ++++++ .../AbstractRefreshTokenSupportTests.java | 4 +- .../jdbc/src/main/java/demo/Application.java | 49 +++++++++++-------- .../src/test/java/demo/ApplicationTests.java | 7 +++ tests/annotation/pom.xml | 2 +- tests/xml/pom.xml | 2 +- 8 files changed, 58 insertions(+), 28 deletions(-) diff --git a/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java b/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java index 8a9610a4e..5e9451cf4 100755 --- a/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java @@ -30,7 +30,6 @@ import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.http.client.ClientHttpResponse; -import org.springframework.security.crypto.codec.Base64; import org.springframework.security.oauth2.client.OAuth2RestTemplate; import org.springframework.security.oauth2.client.resource.UserApprovalRequiredException; import org.springframework.security.oauth2.client.resource.UserRedirectRequiredException; @@ -319,7 +318,7 @@ private ResponseEntity attemptToGetConfirmationPage(String clientId, Str private HttpHeaders getAuthenticatedHeaders() { HttpHeaders headers = new HttpHeaders(); headers.setAccept(Arrays.asList(MediaType.TEXT_HTML)); - headers.set("Authorization", "Basic " + new String(Base64.encode("user:password".getBytes()))); + headers.set("Authorization", getBasicAuthentication()); if (context.getRestTemplate() != null) { context.getAccessTokenRequest().setHeaders(headers); } diff --git a/tests/annotation/common/src/main/java/sparklr/common/AbstractImplicitProviderTests.java b/tests/annotation/common/src/main/java/sparklr/common/AbstractImplicitProviderTests.java index 5e1c47d55..3e98cd8cb 100644 --- a/tests/annotation/common/src/main/java/sparklr/common/AbstractImplicitProviderTests.java +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractImplicitProviderTests.java @@ -5,7 +5,6 @@ import org.junit.Test; import org.springframework.http.HttpHeaders; -import org.springframework.security.crypto.codec.Base64; import org.springframework.security.oauth2.client.resource.UserRedirectRequiredException; import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration; import org.springframework.security.oauth2.client.token.grant.implicit.ImplicitResourceDetails; @@ -22,7 +21,7 @@ public abstract class AbstractImplicitProviderTests extends AbstractIntegrationT public void testPostForNonAutomaticApprovalToken() throws Exception { HttpHeaders headers = new HttpHeaders(); - headers.set("Authorization", "Basic " + new String(Base64.encode("user:password".getBytes()))); + headers.set("Authorization", getBasicAuthentication()); context.getAccessTokenRequest().setHeaders(headers); try { assertNotNull(context.getAccessToken()); 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 b78763e89..adf59f1ee 100644 --- a/tests/annotation/common/src/main/java/sparklr/common/AbstractIntegrationTests.java +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractIntegrationTests.java @@ -21,6 +21,7 @@ import org.springframework.aop.framework.Advised; import org.springframework.beans.factory.annotation.Autowired; 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.context.embedded.EmbeddedWebApplicationContext; import org.springframework.boot.test.IntegrationTest; @@ -28,10 +29,12 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.security.crypto.codec.Base64; import org.springframework.security.oauth2.client.resource.BaseOAuth2ProtectedResourceDetails; import org.springframework.security.oauth2.client.test.BeforeOAuth2Context; import org.springframework.security.oauth2.client.test.OAuth2ContextSetup; import org.springframework.security.oauth2.client.token.grant.implicit.ImplicitResourceDetails; +import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordResourceDetails; import org.springframework.security.oauth2.client.token.grant.redirect.AbstractRedirectResourceDetails; import org.springframework.security.oauth2.provider.approval.ApprovalStore; import org.springframework.security.oauth2.provider.approval.InMemoryApprovalStore; @@ -81,6 +84,9 @@ public int getPort() { return container == null ? 8080 : container.getEmbeddedServletContainer().getPort(); } + @Autowired + protected SecurityProperties security; + @Autowired private ServerProperties server; @@ -96,6 +102,10 @@ public void fixPaths() { if (resource instanceof ImplicitResourceDetails) { resource.setAccessTokenUri(http.getUrl(authorizePath())); } + if (resource instanceof ResourceOwnerPasswordResourceDetails) { + ((ResourceOwnerPasswordResourceDetails) resource).setUsername(security.getUser().getName()); + ((ResourceOwnerPasswordResourceDetails) resource).setPassword(security.getUser().getPassword()); + } } @After @@ -104,6 +114,12 @@ public void init() throws Exception { clear(approvalStore); } + protected String getBasicAuthentication() { + return "Basic " + + new String(Base64.encode((security.getUser().getName() + ":" + security.getUser().getPassword()) + .getBytes())); + } + private void clear(ApprovalStore approvalStore) throws Exception { if (approvalStore instanceof Advised) { Advised advised = (Advised) tokenStore; diff --git a/tests/annotation/common/src/main/java/sparklr/common/AbstractRefreshTokenSupportTests.java b/tests/annotation/common/src/main/java/sparklr/common/AbstractRefreshTokenSupportTests.java index dd3b7b6c6..75223068d 100644 --- a/tests/annotation/common/src/main/java/sparklr/common/AbstractRefreshTokenSupportTests.java +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractRefreshTokenSupportTests.java @@ -101,8 +101,8 @@ private MultiValueMap getTokenFormData(String scope, String clie formData.add("client_id", clientId); } formData.add("scope", scope); - formData.add("username", "user"); - formData.add("password", "password"); + formData.add("username", security.getUser().getName()); + formData.add("password", security.getUser().getPassword()); return formData; } } diff --git a/tests/annotation/jdbc/src/main/java/demo/Application.java b/tests/annotation/jdbc/src/main/java/demo/Application.java index 715962ef2..c752fa832 100644 --- a/tests/annotation/jdbc/src/main/java/demo/Application.java +++ b/tests/annotation/jdbc/src/main/java/demo/Application.java @@ -9,12 +9,13 @@ import org.springframework.boot.autoconfigure.security.SecurityProperties.User; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.DependsOn; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter; import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; @@ -34,25 +35,11 @@ @RestController public class Application { - @Order(Ordered.LOWEST_PRECEDENCE - 8) - protected static class ApplicationSecurity extends WebSecurityConfigurerAdapter { - - @Autowired - private DataSource dataSource; - - @Autowired - private SecurityProperties security; - - @Override - protected void configure(AuthenticationManagerBuilder auth) throws Exception { - User user = security.getUser(); - // @formatter:off - auth.jdbcAuthentication().dataSource(dataSource) - .withUser(user.getName()) - .password(user.getPassword()) - .roles(user.getRole().toArray(new String[0])); - // @formatter:on - } + @Bean + @DependsOn("dataSourceAutoConfigurationInitializer") + // @DependsOn only works if it is on a @Bean, so we can't use an @Import here + protected AuthenticationManagerConfiguration authenticationManagerConfiguration() { + return new AuthenticationManagerConfiguration(); } public static void main(String[] args) { @@ -139,3 +126,25 @@ public void configure(ClientDetailsServiceConfigurer clients) throws Exception { } } + +@Configuration +@Order(Ordered.HIGHEST_PRECEDENCE + 10) +class AuthenticationManagerConfiguration extends GlobalAuthenticationConfigurerAdapter { + + @Autowired + private DataSource dataSource; + + @Autowired + private SecurityProperties security; + + @Override + public void init(AuthenticationManagerBuilder auth) throws Exception { + User user = security.getUser(); + // @formatter:off + auth.jdbcAuthentication().dataSource(dataSource) + .withUser(user.getName()) + .password(user.getPassword()) + .roles(user.getRole().toArray(new String[0])); + // @formatter:on + } +} diff --git a/tests/annotation/jdbc/src/test/java/demo/ApplicationTests.java b/tests/annotation/jdbc/src/test/java/demo/ApplicationTests.java index 055467fe5..206254701 100644 --- a/tests/annotation/jdbc/src/test/java/demo/ApplicationTests.java +++ b/tests/annotation/jdbc/src/test/java/demo/ApplicationTests.java @@ -4,8 +4,11 @@ import org.junit.Test; import org.junit.runner.RunWith; +import org.springframework.aop.support.AopUtils; import org.springframework.beans.factory.annotation.Autowired; 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.ActiveProfiles; @@ -21,9 +24,13 @@ public class ApplicationTests { @Autowired private TokenStore tokenStore; + @Autowired + private ClientDetailsService clientDetailsService; + @Test public void contextLoads() { assertTrue("Wrong token store type: " + tokenStore, tokenStore instanceof JdbcTokenStore); + assertTrue("Wrong client details type: " + clientDetailsService, JdbcClientDetailsService.class.isAssignableFrom(AopUtils.getTargetClass(clientDetailsService))); } } diff --git a/tests/annotation/pom.xml b/tests/annotation/pom.xml index 5a342d427..82e74179c 100644 --- a/tests/annotation/pom.xml +++ b/tests/annotation/pom.xml @@ -26,7 +26,7 @@ org.springframework.boot spring-boot-starter-parent - 1.1.0.RELEASE + 1.1.1.RELEASE diff --git a/tests/xml/pom.xml b/tests/xml/pom.xml index b71183ab9..853d73c1c 100644 --- a/tests/xml/pom.xml +++ b/tests/xml/pom.xml @@ -24,7 +24,7 @@ org.springframework.boot spring-boot-starter-parent - 1.1.0.RELEASE + 1.1.1.RELEASE From 5f4b2a3d393221ac84c5cb501534d87108b68ef6 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 18 Jun 2014 10:50:17 +0100 Subject: [PATCH 274/831] Change throws in declaration of *TokenServices Fixes gh-206 --- .../security/oauth2/provider/token/DefaultTokenServices.java | 2 +- .../security/oauth2/provider/token/RemoteTokenServices.java | 2 +- .../oauth2/provider/token/ResourceServerTokenServices.java | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java index 983269d61..50989c38e 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java @@ -203,7 +203,7 @@ public OAuth2AccessToken readAccessToken(String accessToken) { return tokenStore.readAccessToken(accessToken); } - public OAuth2Authentication loadAuthentication(String accessTokenValue) throws AuthenticationException { + public OAuth2Authentication loadAuthentication(String accessTokenValue) throws AuthenticationException, InvalidTokenException { OAuth2AccessToken accessToken = tokenStore.readAccessToken(accessTokenValue); if (accessToken == null) { throw new InvalidTokenException("Invalid access token: " + accessTokenValue); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/RemoteTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/RemoteTokenServices.java index ddf1fb214..8ae7c9e62 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/RemoteTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/RemoteTokenServices.java @@ -92,7 +92,7 @@ public void setAccessTokenConverter(AccessTokenConverter accessTokenConverter) { } @Override - public OAuth2Authentication loadAuthentication(String accessToken) throws AuthenticationException { + public OAuth2Authentication loadAuthentication(String accessToken) throws AuthenticationException, InvalidTokenException { MultiValueMap formData = new LinkedMultiValueMap(); formData.add("token", accessToken); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/ResourceServerTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/ResourceServerTokenServices.java index 4db99308f..23795bc43 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/ResourceServerTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/ResourceServerTokenServices.java @@ -2,6 +2,7 @@ import org.springframework.security.core.AuthenticationException; import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; import org.springframework.security.oauth2.provider.OAuth2Authentication; public interface ResourceServerTokenServices { @@ -12,8 +13,9 @@ public interface ResourceServerTokenServices { * @param accessToken The access token value. * @return The authentication for the access token. * @throws AuthenticationException If the access token is expired + * @throws InvalidTokenException if the token isn't valid */ - OAuth2Authentication loadAuthentication(String accessToken) throws AuthenticationException; + OAuth2Authentication loadAuthentication(String accessToken) throws AuthenticationException, InvalidTokenException; /** * Retrieve the full access token details from just the value. From 03b488bbdbea8c8829d5ce2f643b47581b59fc67 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 18 Jun 2014 10:59:47 +0100 Subject: [PATCH 275/831] Check that client-details-services-ref is provided in parser Fixes gh-213 --- ...thorizationServerBeanDefinitionParser.java | 5 +++ ...AuthorizationServerInvalidParserTests.java | 32 +++++++++++++++++++ .../xml/authorization-server-invalid.xml | 12 +++++++ 3 files changed, 49 insertions(+) create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/AuthorizationServerInvalidParserTests.java create mode 100644 spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-invalid.xml 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 48a7da559..afc8f8d42 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 @@ -73,6 +73,11 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P BeanDefinitionBuilder authorizationEndpointBean = BeanDefinitionBuilder .rootBeanDefinition(AuthorizationEndpoint.class); + if (!StringUtils.hasText(clientDetailsRef)) { + parserContext.getReaderContext().error("ClientDetailsService must be provided", element); + return null; + } + if (!StringUtils.hasText(oAuth2RequestValidatorRef)) { oAuth2RequestValidatorRef = "defaultOAuth2RequestValidator"; BeanDefinitionBuilder oAuth2RequestValidator = BeanDefinitionBuilder diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/AuthorizationServerInvalidParserTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/AuthorizationServerInvalidParserTests.java new file mode 100644 index 000000000..372d310d1 --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/AuthorizationServerInvalidParserTests.java @@ -0,0 +1,32 @@ +package org.springframework.security.oauth2.config.xml; + +import static org.junit.Assert.assertNotNull; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.springframework.beans.factory.parsing.BeanDefinitionParsingException; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.support.GenericXmlApplicationContext; +import org.springframework.security.oauth2.provider.CompositeTokenGranter; +import org.springframework.security.oauth2.provider.TokenGranter; + +public class AuthorizationServerInvalidParserTests { + + private static String RESOURCE_NAME = "authorization-server-invalid.xml"; + + private ConfigurableApplicationContext context; + + @Rule + public ExpectedException expected = ExpectedException.none(); + + @Test + public void testCustomGrantRegistered() { + expected.expect(BeanDefinitionParsingException.class); + expected.expectMessage("ClientDetailsService"); + context = new GenericXmlApplicationContext(getClass(), RESOURCE_NAME); + TokenGranter granter = context.getBean(CompositeTokenGranter.class); + assertNotNull(granter); + } + +} diff --git a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-invalid.xml b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-invalid.xml new file mode 100644 index 000000000..da8b5318e --- /dev/null +++ b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-invalid.xml @@ -0,0 +1,12 @@ + + + + + + + + + From 3e6621c6ddbf2d87a396c5dc6928ad3776d8ef9d Mon Sep 17 00:00:00 2001 From: Lucas Espindola Date: Tue, 17 Jun 2014 21:32:02 -0300 Subject: [PATCH 276/831] Add OAuth2RequestValidator reference to TokenEndpoint when parsing AuthorizationServer bean Fixes gh-221 --- .../xml/AuthorizationServerBeanDefinitionParser.java | 3 +++ .../security/oauth2/provider/endpoint/TokenEndpoint.java | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) 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 afc8f8d42..c282b239c 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 @@ -250,6 +250,9 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P if (StringUtils.hasText(oAuth2RequestFactoryRef)) { tokenEndpointBean.addPropertyReference("oAuth2RequestFactory", oAuth2RequestFactoryRef); } + if (StringUtils.hasText(oAuth2RequestValidatorRef)) { + tokenEndpointBean.addPropertyReference("oAuth2RequestValidator", oAuth2RequestValidatorRef); + } // Register a handler mapping that can detect the auth server endpoints BeanDefinitionBuilder handlerMappingBean = BeanDefinitionBuilder diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java index 7e1c6132a..64d776b92 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java @@ -64,7 +64,7 @@ @FrameworkEndpoint public class TokenEndpoint extends AbstractEndpoint { - private OAuth2RequestValidator oauth2RequestValidator = new DefaultOAuth2RequestValidator(); + private OAuth2RequestValidator oAuth2RequestValidator = new DefaultOAuth2RequestValidator(); @RequestMapping(value = "/oauth/token") public ResponseEntity getAccessToken(Principal principal, @RequestParam @@ -90,7 +90,7 @@ public ResponseEntity getAccessToken(Principal principal, @Re } } if (authenticatedClient != null) { - oauth2RequestValidator.validateScope(tokenRequest, authenticatedClient); + oAuth2RequestValidator.validateScope(tokenRequest, authenticatedClient); } if (!StringUtils.hasText(tokenRequest.getGrantType())) { throw new InvalidRequestException("Missing grant type"); @@ -165,8 +165,8 @@ private boolean isAuthCodeRequest(Map parameters) { return "authorization_code".equals(parameters.get("grant_type")) && parameters.get("code") != null; } - public void setOAuth2RequestValidator(OAuth2RequestValidator oauth2RequestValidator) { - this.oauth2RequestValidator = oauth2RequestValidator; + public void setOAuth2RequestValidator(OAuth2RequestValidator oAuth2RequestValidator) { + this.oAuth2RequestValidator = oAuth2RequestValidator; } } From 6d9de66787cb60249f0de00ffe9075366a803924 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Sun, 22 Jun 2014 09:47:23 +0100 Subject: [PATCH 277/831] Fix link in README (fixes gh-225) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 724da83d3..e58a4ead2 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ Lists of issues addressed per release can be found in [github](https://github.co ## Additional Resources -* [Spring Security OAuth User Guide](docs/Home.html) +* [Spring Security OAuth User Guide](http://projects.spring.io/spring-security-oauth/docs/Home.html) * [Spring Security OAuth Source](http://github.com/spring-projects/spring-security-oauth) * [Stackoverflow](http://stackoverflow.com/questions/tagged/spring-security+spring+oauth) From 4e42df86795dddca37126b41e358f57f639e5dc6 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 22 Aug 2014 16:10:45 +0100 Subject: [PATCH 278/831] Fix typo (fixes gh-242) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e58a4ead2..3e9b33be7 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ request but before a merge. * Make sure all new .java files to have a simple Javadoc class comment with at least an @author tag identifying you, and preferably at least a paragraph on what the class is for. * Add the ASF license header comment to all new .java files (copy from existing files in the project) -* Add yourself as an @author to the .java files that you modify substantially (moew than cosmetic changes). +* Add yourself as an @author to the .java files that you modify substantially (more than cosmetic changes). * Add some Javadocs and, if you change the namespace, some XSD doc elements. * A few unit tests would help a lot as well - someone has to do it. * If no-one else is using your branch, please rebase it against the current master (or other target branch in the main project). From 22634032e611445955cae666a315d2a6ba0b09eb Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 22 Aug 2014 16:31:50 +0100 Subject: [PATCH 279/831] Fix validation of JwtAccessTokenConverter Because of the order of the validation checks, before this change it was impossible to use the JwtAccessTokenConverter purely for RSA verification (i.e. public key only). Also moved token store tests into subpackage to match the classes they test. Fixes gh-245 --- .../token/store/JwtAccessTokenConverter.java | 25 +++++----------- .../{ => store}/InMemoryTokenStoreTests.java | 2 +- .../{ => store}/JdbcTokenStoreTests.java | 2 +- .../{ => store}/JwtTokenEnhancerTests.java | 29 +++++++++++++++++-- .../token/{ => store}/JwtTokenStoreTests.java | 2 +- .../{ => store}/TokenStoreBaseTests.java | 3 +- 6 files changed, 39 insertions(+), 24 deletions(-) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/{ => store}/InMemoryTokenStoreTests.java (97%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/{ => store}/JdbcTokenStoreTests.java (92%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/{ => store}/JwtTokenEnhancerTests.java (89%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/{ => store}/JwtTokenStoreTests.java (98%) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/{ => store}/TokenStoreBaseTests.java (98%) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java index 6c225237c..dc016598c 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java @@ -224,17 +224,15 @@ protected Map decode(String token) { } public void afterPropertiesSet() throws Exception { + SignatureVerifier verifier = new MacSigner(verifierKey); + try { + verifier = new RsaVerifier(verifierKey); + } + catch (Exception e) { + logger.warn("Unable to create an RSA verifier from verifierKey (ignoreable if using MAC)"); + } // Check the signing and verification keys match if (signer instanceof RsaSigner) { - RsaVerifier verifier; - try { - verifier = new RsaVerifier(verifierKey); - } - catch (Exception e) { - logger.warn("Unable to create an RSA verifier from verifierKey"); - return; - } - byte[] test = "test".getBytes(); try { verifier.verify(test, signer.sign(test)); @@ -244,18 +242,11 @@ public void afterPropertiesSet() throws Exception { logger.error("Signing and verification RSA keys do not match"); } } - else { + else if (verifier instanceof MacSigner){ // Avoid a race condition where setters are called in the wrong order. Use of == is intentional. Assert.state(this.signingKey == this.verifierKey, "For MAC signing you do not need to specify the verifier key separately, and if you do it must match the signing key"); } - SignatureVerifier verifier = new MacSigner(verifierKey); - try { - verifier = new RsaVerifier(verifierKey); - } - catch (Exception e) { - logger.warn("Unable to create an RSA verifier from verifierKey"); - } this.verifier = verifier; } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStoreTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/InMemoryTokenStoreTests.java similarity index 97% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStoreTests.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/InMemoryTokenStoreTests.java index 9ac0cca73..43a9baebd 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/InMemoryTokenStoreTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/InMemoryTokenStoreTests.java @@ -1,4 +1,4 @@ -package org.springframework.security.oauth2.provider.token; +package org.springframework.security.oauth2.provider.token.store; import static org.junit.Assert.assertEquals; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JdbcTokenStoreTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JdbcTokenStoreTests.java similarity index 92% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JdbcTokenStoreTests.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JdbcTokenStoreTests.java index 66c9ce2ad..108ac61db 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JdbcTokenStoreTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JdbcTokenStoreTests.java @@ -1,4 +1,4 @@ -package org.springframework.security.oauth2.provider.token; +package org.springframework.security.oauth2.provider.token.store; import org.junit.After; import org.junit.Before; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtTokenEnhancerTests.java similarity index 89% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancerTests.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtTokenEnhancerTests.java index 0b03590dd..15f3cec28 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenEnhancerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtTokenEnhancerTests.java @@ -7,7 +7,7 @@ * This product includes a number of subcomponents with separate copyright notices and license terms. Your use of these * subcomponents is subject to the terms and conditions of the subcomponent's license, as noted in the LICENSE file. */ -package org.springframework.security.oauth2.provider.token; +package org.springframework.security.oauth2.provider.token.store; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -19,6 +19,7 @@ import org.junit.Before; import org.junit.Test; +import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.jwt.JwtHelper; import org.springframework.security.jwt.crypto.sign.RsaVerifier; @@ -27,8 +28,8 @@ import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; -import org.springframework.security.oauth2.provider.token.AbstractDefaultTokenServicesTests.TestAuthentication; -import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; +import org.springframework.security.oauth2.provider.token.AccessTokenConverter; +import org.springframework.security.oauth2.provider.token.UserAuthenticationConverter; /** * @author Dave Syer @@ -109,6 +110,7 @@ public void publicKeyStringIsReturnedFromTokenKeyEndpoint() throws Exception { + "MGgCYQDk3m+AGfjcDrT4fspyIBqmulFjVXuiciYvpaD5j2XaR7c6Krm5wsBLOiUo\n" + "kmd6wbrRAMPMpoC1eogWNNoXY7Jd4eWdDVmscfHczGX13uBKXwdOCEqKqoWQsXIb\n" + "7kgz+HkCAwEAAQ==\n" + "-----END RSA PUBLIC KEY-----"); + tokenEnhancer.afterPropertiesSet(); Map key = tokenEnhancer.getKey(); assertTrue("Wrong key: " + key, key.get("value").contains("-----BEGIN")); } @@ -142,4 +144,25 @@ private OAuth2Request createOAuth2Request(String clientId, Set scope) { null, null); } + protected static class TestAuthentication extends AbstractAuthenticationToken { + + private static final long serialVersionUID = 1L; + + private String principal; + + public TestAuthentication(String name, boolean authenticated) { + super(null); + setAuthenticated(authenticated); + this.principal = name; + } + + public Object getCredentials() { + return null; + } + + public Object getPrincipal() { + return this.principal; + } + } + } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenStoreTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStoreTests.java similarity index 98% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenStoreTests.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStoreTests.java index fd45a958f..9e8b0c4e7 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/JwtTokenStoreTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStoreTests.java @@ -1,4 +1,4 @@ -package org.springframework.security.oauth2.provider.token; +package org.springframework.security.oauth2.provider.token.store; import static org.junit.Assert.assertEquals; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenStoreBaseTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/TokenStoreBaseTests.java similarity index 98% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenStoreBaseTests.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/TokenStoreBaseTests.java index 13e56a548..e17e21af1 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenStoreBaseTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/TokenStoreBaseTests.java @@ -10,7 +10,7 @@ * 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; +package org.springframework.security.oauth2.provider.token.store; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -30,6 +30,7 @@ import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.RequestTokenFactory; +import org.springframework.security.oauth2.provider.token.TokenStore; /** * @author Dave Syer From 83028e7a1a1931dbb45011ac5edccf32a3bc38eb Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 22 Aug 2014 16:52:09 +0100 Subject: [PATCH 280/831] Ensure EXP claim is stored as a Long in JWT token Fixes gh-237 --- .../provider/token/DefaultAccessTokenConverter.java | 2 +- .../provider/token/store/JwtAccessTokenConverter.java | 4 ++++ .../oauth2/provider/token/store/JwtTokenStoreTests.java | 8 ++++++++ .../oauth2/provider/token/store/TokenStoreBaseTests.java | 3 ++- 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java index bd0610bd0..57d486d7d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java @@ -82,7 +82,7 @@ public OAuth2AccessToken extractAccessToken(String value, Map map) { info.remove(CLIENT_ID); info.remove(SCOPE); if (map.containsKey(EXP)) { - token.setExpiration(new Date((Integer) map.get(EXP) * 1000L)); + token.setExpiration(new Date((Long) map.get(EXP) * 1000L)); } if (map.containsKey(JTI)) { info.put(JTI, map.get(JTI)); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java index dc016598c..3a07e1d73 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java @@ -216,6 +216,10 @@ protected Map decode(String token) { String content = jwt.getClaims(); @SuppressWarnings("unchecked") Map map = objectMapper.readValue(content, Map.class); + if (map.containsKey(EXP) && map.get(EXP) instanceof Integer) { + Integer intValue = (Integer) map.get(EXP); + map.put(EXP, new Long(intValue)); + } return map; } catch (Exception e) { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStoreTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStoreTests.java index 9e8b0c4e7..0c0ba0d2f 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStoreTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStoreTests.java @@ -59,6 +59,14 @@ public void testReadAccessToken() throws Exception { assertEquals(expectedOAuth2AccessToken, tokenStore.readAccessToken(expectedOAuth2AccessToken.getValue())); } + @Test + public void testReadAccessTokenWithLongExpiration() throws Exception { + DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(expectedOAuth2AccessToken); + token.setExpiration(new Date(Long.MAX_VALUE-1)); + expectedOAuth2AccessToken = enhancer.enhance(token, expectedAuthentication); + assertEquals(expectedOAuth2AccessToken, tokenStore.readAccessToken(expectedOAuth2AccessToken.getValue())); + } + @Test public void testReadRefreshToken() throws Exception { assertEquals(expectedOAuth2AccessToken, tokenStore.readRefreshToken(expectedOAuth2AccessToken.getValue())); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/TokenStoreBaseTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/TokenStoreBaseTests.java index e17e21af1..adb1db0f2 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/TokenStoreBaseTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/TokenStoreBaseTests.java @@ -79,7 +79,8 @@ public void testRetrieveAccessToken() { //Test approved request OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request("id", true); OAuth2Authentication authentication = new OAuth2Authentication(storedOAuth2Request, new TestAuthentication("test2", true)); - OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); + DefaultOAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); + expectedOAuth2AccessToken.setExpiration(new Date(Long.MAX_VALUE-1)); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, authentication); //Test unapproved request From c0d83536fbc28525a0dbef0ded784c605c7db261 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 22 Aug 2014 16:55:03 +0100 Subject: [PATCH 281/831] Don't declare checked exception with @PostConstruct Fixes gh-244 --- .../AuthorizationServerEndpointsConfiguration.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) 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 a3565b975..15d954fdb 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 @@ -72,9 +72,14 @@ public class AuthorizationServerEndpointsConfiguration { private List configurers = Collections.emptyList(); @PostConstruct - public void init() throws Exception { + public void init() { for (AuthorizationServerConfigurer configurer : configurers) { - configurer.configure(endpoints); + try { + configurer.configure(endpoints); + } + catch (Exception e) { + throw new IllegalStateException("Cannot configure enpdoints", e); + } } endpoints.clientDetailsService(clientDetailsService); } From 66fa4bc5a38f40c9251598e24b33f18ac72412f6 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 26 Jun 2014 10:10:55 +0100 Subject: [PATCH 282/831] Fixes gh-225 (broken links) --- docs/oauth2.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/oauth2.md b/docs/oauth2.md index 9b354da6c..f5b71b15b 100644 --- a/docs/oauth2.md +++ b/docs/oauth2.md @@ -208,17 +208,17 @@ To use Facebook as an example, there is a Facebook feature in the `tonr2` applic Facebook token responses also contain a non-compliant JSON entry for the expiry time of the token (they use `expires` instead of `expires_in`), so if you want to use the expiry time in your application you will have to decode it manually using a custom `OAuth2SerializationService`. - [AuthorizationEndpoint]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.html "AuthorizationEndpoint" - [TokenEndpoint]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.html "TokenEndpoint" - [DefaultTokenServices]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/token/DefaultTokenServices.html "DefaultTokenServices" - [InMemoryTokenStore]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/token/InMemoryTokenStore.html "InMemoryTokenStore" - [JdbcTokenStore]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/token/JdbcTokenStore.html "JdbcTokenStore" - [ClientDetailsService]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/ClientDetailsService.html "ClientDetailsService" - [ClientDetails]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/ClientDetails.html "ClientDetails" - [InMemoryClientDetailsService]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/InMemoryClientDetailsService.html "InMemoryClientDetailsService" - [BaseClientDetails]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/BaseClientDetails.html "BaseClientDetails" - [AuthorizationServerTokenServices]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/token/AuthorizationServerTokenServices.html "AuthorizationServerTokenServices" - [OAuth2AuthenticationProcessingFilter]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/filter/OAuth2AuthenticationProcessingFilter.html "OAuth2AuthenticationProcessingFilter" + [AuthorizationEndpoint]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.html "AuthorizationEndpoint" + [TokenEndpoint]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.html "TokenEndpoint" + [DefaultTokenServices]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/token/DefaultTokenServices.html "DefaultTokenServices" + [InMemoryTokenStore]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/token/store/InMemoryTokenStore.html "InMemoryTokenStore" + [JdbcTokenStore]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/token/store/JdbcTokenStore.html "JdbcTokenStore" + [ClientDetailsService]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/ClientDetailsService.html "ClientDetailsService" + [ClientDetails]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/ClientDetails.html "ClientDetails" + [InMemoryClientDetailsService]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/InMemoryClientDetailsService.html "InMemoryClientDetailsService" + [BaseClientDetails]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/BaseClientDetails.html "BaseClientDetails" + [AuthorizationServerTokenServices]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/token/AuthorizationServerTokenServices.html "AuthorizationServerTokenServices" + [OAuth2AuthenticationProcessingFilter]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/filter/OAuth2AuthenticationProcessingFilter.html "OAuth2AuthenticationProcessingFilter" [oauth2.xsd]: http://www.springframework.org/schema/security/spring-security-oauth2.xsd "oauth2.xsd" [expressions]: http://static.springsource.org/spring-security/site/docs/3.2.x/reference/el-access.html "Expression Access Control" From 8c1e281a790bd04f9e223ea52c496cec336b26b9 Mon Sep 17 00:00:00 2001 From: Andres Koetter Date: Mon, 28 Jul 2014 00:07:32 +0200 Subject: [PATCH 283/831] FIx naming, match constructor args to fields --- .../security/oauth2/provider/OAuth2Authentication.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Authentication.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Authentication.java index 28afb593c..8f34613bb 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Authentication.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Authentication.java @@ -21,12 +21,12 @@ public class OAuth2Authentication extends AbstractAuthenticationToken { * Construct an OAuth 2 authentication. Since some grant types don't require user authentication, the user * authentication may be null. * - * @param authorizationRequest The authorization request (must not be null). + * @param storedRequest The authorization request (must not be null). * @param userAuthentication The user authentication (possibly null). */ - public OAuth2Authentication(OAuth2Request clientAuthentication, Authentication userAuthentication) { - super(userAuthentication == null ? clientAuthentication.getAuthorities() : userAuthentication.getAuthorities()); - this.storedRequest = clientAuthentication; + public OAuth2Authentication(OAuth2Request storedRequest, Authentication userAuthentication) { + super(userAuthentication == null ? storedRequest.getAuthorities() : userAuthentication.getAuthorities()); + this.storedRequest = storedRequest; this.userAuthentication = userAuthentication; } From e31ff96c2a90be082ee59e9c9719cef0f25af6f5 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Sat, 23 Aug 2014 06:57:23 +0100 Subject: [PATCH 284/831] Modernize tests --- tests/annotation/approval/.gitignore | 7 ++++++ .../src/test/java/demo/ApplicationTests.java | 4 ++-- .../src/test/resources/test.properties | 1 - tests/annotation/client/.gitignore | 9 +++++++ .../test/java/client/ApplicationTests.java | 4 ++-- .../client/src/test/resources/test.properties | 1 - tests/annotation/common/.gitignore | 11 +++++++++ .../common/AbstractIntegrationTests.java | 23 +++++++++++------- .../java/sparklr/common/HttpTestUtils.java | 14 ----------- .../main/java/sparklr/common/PortHolder.java | 24 ------------------- tests/annotation/form/.gitignore | 6 +++++ .../src/test/java/demo/ApplicationTests.java | 4 ++-- .../form/src/test/resources/test.properties | 1 - tests/annotation/jdbc/.gitignore | 6 +++++ .../src/test/java/demo/ApplicationTests.java | 4 ++-- .../jdbc/src/test/resources/test.properties | 1 - tests/annotation/jwt/.gitignore | 6 +++++ .../src/test/java/demo/ApplicationTests.java | 4 ++-- .../jwt/src/test/resources/test.properties | 1 - tests/annotation/mappings/.gitignore | 7 ++++++ .../src/test/java/demo/ApplicationTests.java | 4 ++-- .../src/test/resources/test.properties | 1 - tests/annotation/multi/.gitignore | 6 +++++ .../src/test/java/demo/ApplicationTests.java | 4 ++-- .../multi/src/test/resources/test.properties | 1 - tests/annotation/resource/.gitignore | 6 +++++ .../src/test/java/demo/ApplicationTests.java | 4 ++-- .../src/test/resources/test.properties | 1 - tests/annotation/vanilla/.gitignore | 6 +++++ .../src/test/java/demo/ApplicationTests.java | 4 ++-- .../src/test/resources/test.properties | 1 - 31 files changed, 102 insertions(+), 74 deletions(-) create mode 100644 tests/annotation/approval/.gitignore delete mode 100644 tests/annotation/approval/src/test/resources/test.properties create mode 100644 tests/annotation/client/.gitignore delete mode 100644 tests/annotation/client/src/test/resources/test.properties create mode 100644 tests/annotation/common/.gitignore delete mode 100644 tests/annotation/common/src/main/java/sparklr/common/PortHolder.java create mode 100644 tests/annotation/form/.gitignore delete mode 100644 tests/annotation/form/src/test/resources/test.properties create mode 100644 tests/annotation/jdbc/.gitignore create mode 100644 tests/annotation/jwt/.gitignore delete mode 100644 tests/annotation/jwt/src/test/resources/test.properties create mode 100644 tests/annotation/mappings/.gitignore delete mode 100644 tests/annotation/mappings/src/test/resources/test.properties create mode 100644 tests/annotation/multi/.gitignore delete mode 100644 tests/annotation/multi/src/test/resources/test.properties create mode 100644 tests/annotation/resource/.gitignore delete mode 100644 tests/annotation/resource/src/test/resources/test.properties create mode 100644 tests/annotation/vanilla/.gitignore delete mode 100644 tests/annotation/vanilla/src/test/resources/test.properties diff --git a/tests/annotation/approval/.gitignore b/tests/annotation/approval/.gitignore new file mode 100644 index 000000000..a227dd5ab --- /dev/null +++ b/tests/annotation/approval/.gitignore @@ -0,0 +1,7 @@ +/target/ +/target/ +/target/ +/target/ +/target/ +/target/ +/target/ diff --git a/tests/annotation/approval/src/test/java/demo/ApplicationTests.java b/tests/annotation/approval/src/test/java/demo/ApplicationTests.java index 8da63b411..15eca8da6 100644 --- a/tests/annotation/approval/src/test/java/demo/ApplicationTests.java +++ b/tests/annotation/approval/src/test/java/demo/ApplicationTests.java @@ -2,15 +2,15 @@ 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.ActiveProfiles; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class) @WebAppConfiguration -@ActiveProfiles("test") +@IntegrationTest("server.port=0") public class ApplicationTests { @Test diff --git a/tests/annotation/approval/src/test/resources/test.properties b/tests/annotation/approval/src/test/resources/test.properties deleted file mode 100644 index 24466e50d..000000000 --- a/tests/annotation/approval/src/test/resources/test.properties +++ /dev/null @@ -1 +0,0 @@ -server.port: 0 \ No newline at end of file diff --git a/tests/annotation/client/.gitignore b/tests/annotation/client/.gitignore new file mode 100644 index 000000000..8352667a7 --- /dev/null +++ b/tests/annotation/client/.gitignore @@ -0,0 +1,9 @@ +/target/ +/target/ +/target/ +/target/ +/target/ +/target/ +/target/ +/target/ +/target/ diff --git a/tests/annotation/client/src/test/java/client/ApplicationTests.java b/tests/annotation/client/src/test/java/client/ApplicationTests.java index a8ea1b1c1..8c5aef34a 100644 --- a/tests/annotation/client/src/test/java/client/ApplicationTests.java +++ b/tests/annotation/client/src/test/java/client/ApplicationTests.java @@ -2,15 +2,15 @@ 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.ActiveProfiles; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = ClientApplication.class) @WebAppConfiguration -@ActiveProfiles("test") +@IntegrationTest("server.port=0") public class ApplicationTests { @Test diff --git a/tests/annotation/client/src/test/resources/test.properties b/tests/annotation/client/src/test/resources/test.properties deleted file mode 100644 index 24466e50d..000000000 --- a/tests/annotation/client/src/test/resources/test.properties +++ /dev/null @@ -1 +0,0 @@ -server.port: 0 \ No newline at end of file diff --git a/tests/annotation/common/.gitignore b/tests/annotation/common/.gitignore new file mode 100644 index 000000000..32362a30c --- /dev/null +++ b/tests/annotation/common/.gitignore @@ -0,0 +1,11 @@ +/target/ +/target/ +/target/ +/target/ +/target/ +/target/ +/target/ +/target/ +/target/ +/target/ +/target/ 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 adf59f1ee..95aafef77 100644 --- a/tests/annotation/common/src/main/java/sparklr/common/AbstractIntegrationTests.java +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractIntegrationTests.java @@ -16,6 +16,7 @@ import javax.sql.DataSource; import org.junit.After; +import org.junit.Before; import org.junit.Rule; import org.junit.runner.RunWith; import org.springframework.aop.framework.Advised; @@ -50,8 +51,8 @@ @SpringApplicationConfiguration(classes = TestConfiguration.class, inheritLocations = true) @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration -@IntegrationTest -public abstract class AbstractIntegrationTests implements PortHolder { +@IntegrationTest("server.port=0") +public abstract class AbstractIntegrationTests { private static String globalTokenPath; @@ -60,9 +61,12 @@ public abstract class AbstractIntegrationTests implements PortHolder { private static String globalCheckTokenPath; private static String globalAuthorizePath; + + @Value("${local.server.port}") + private int port; @Rule - public HttpTestUtils http = HttpTestUtils.standard().setPortHolder(this); + public HttpTestUtils http = HttpTestUtils.standard(); @Rule public OAuth2ContextSetup context = OAuth2ContextSetup.standard(http); @@ -79,20 +83,21 @@ public abstract class AbstractIntegrationTests implements PortHolder { @Autowired(required = false) private DataSource dataSource; - @Override - public int getPort() { - return container == null ? 8080 : container.getEmbeddedServletContainer().getPort(); - } - @Autowired protected SecurityProperties security; @Autowired private ServerProperties server; + + @Before + public void init() { + http.setPort(port); + } @BeforeOAuth2Context public void fixPaths() { String prefix = server.getServletPrefix(); + http.setPort(port); http.setPrefix(prefix); BaseOAuth2ProtectedResourceDetails resource = (BaseOAuth2ProtectedResourceDetails) context.getResource(); resource.setAccessTokenUri(http.getUrl(tokenPath())); @@ -109,7 +114,7 @@ public void fixPaths() { } @After - public void init() throws Exception { + public void close() throws Exception { clear(tokenStore); clear(approvalStore); } 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 f27baa146..6d7595c85 100644 --- a/tests/annotation/common/src/main/java/sparklr/common/HttpTestUtils.java +++ b/tests/annotation/common/src/main/java/sparklr/common/HttpTestUtils.java @@ -44,8 +44,6 @@ public class HttpTestUtils implements MethodRule, RestTemplateHolder { private RestOperations client; - private PortHolder portHolder; - private String prefix = ""; /** @@ -82,14 +80,6 @@ public HttpTestUtils setPort(int port) { return this; } - /** - * @param port the port holder to set - */ - public HttpTestUtils setPortHolder(PortHolder port) { - this.portHolder = port; - return this; - } - /** * @param hostName the hostName to set */ @@ -100,10 +90,6 @@ public HttpTestUtils setHostName(String hostName) { public Statement apply(final Statement base, FrameworkMethod method, Object target) { - if (portHolder!=null) { - setPort(portHolder.getPort()); - } - return new Statement() { @Override public void evaluate() throws Throwable { diff --git a/tests/annotation/common/src/main/java/sparklr/common/PortHolder.java b/tests/annotation/common/src/main/java/sparklr/common/PortHolder.java deleted file mode 100644 index 362dceda8..000000000 --- a/tests/annotation/common/src/main/java/sparklr/common/PortHolder.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2013-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ - -package sparklr.common; - -/** - * @author Dave Syer - * - */ -public interface PortHolder { - - int getPort(); - -} diff --git a/tests/annotation/form/.gitignore b/tests/annotation/form/.gitignore new file mode 100644 index 000000000..993e2e793 --- /dev/null +++ b/tests/annotation/form/.gitignore @@ -0,0 +1,6 @@ +/target/ +/target/ +/target/ +/target/ +/target/ +/target/ diff --git a/tests/annotation/form/src/test/java/demo/ApplicationTests.java b/tests/annotation/form/src/test/java/demo/ApplicationTests.java index 8da63b411..15eca8da6 100644 --- a/tests/annotation/form/src/test/java/demo/ApplicationTests.java +++ b/tests/annotation/form/src/test/java/demo/ApplicationTests.java @@ -2,15 +2,15 @@ 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.ActiveProfiles; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class) @WebAppConfiguration -@ActiveProfiles("test") +@IntegrationTest("server.port=0") public class ApplicationTests { @Test diff --git a/tests/annotation/form/src/test/resources/test.properties b/tests/annotation/form/src/test/resources/test.properties deleted file mode 100644 index 24466e50d..000000000 --- a/tests/annotation/form/src/test/resources/test.properties +++ /dev/null @@ -1 +0,0 @@ -server.port: 0 \ No newline at end of file diff --git a/tests/annotation/jdbc/.gitignore b/tests/annotation/jdbc/.gitignore new file mode 100644 index 000000000..993e2e793 --- /dev/null +++ b/tests/annotation/jdbc/.gitignore @@ -0,0 +1,6 @@ +/target/ +/target/ +/target/ +/target/ +/target/ +/target/ diff --git a/tests/annotation/jdbc/src/test/java/demo/ApplicationTests.java b/tests/annotation/jdbc/src/test/java/demo/ApplicationTests.java index 206254701..c251a6506 100644 --- a/tests/annotation/jdbc/src/test/java/demo/ApplicationTests.java +++ b/tests/annotation/jdbc/src/test/java/demo/ApplicationTests.java @@ -6,19 +6,19 @@ import org.junit.runner.RunWith; import org.springframework.aop.support.AopUtils; 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.ActiveProfiles; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class) @WebAppConfiguration -@ActiveProfiles("test") +@IntegrationTest("server.port=0") public class ApplicationTests { @Autowired diff --git a/tests/annotation/jdbc/src/test/resources/test.properties b/tests/annotation/jdbc/src/test/resources/test.properties index bf241d8a4..5be638806 100644 --- a/tests/annotation/jdbc/src/test/resources/test.properties +++ b/tests/annotation/jdbc/src/test/resources/test.properties @@ -1,2 +1 @@ -server.port: 0 spring.datasource.url: jdbc:h2:mem:otherdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE \ No newline at end of file diff --git a/tests/annotation/jwt/.gitignore b/tests/annotation/jwt/.gitignore new file mode 100644 index 000000000..993e2e793 --- /dev/null +++ b/tests/annotation/jwt/.gitignore @@ -0,0 +1,6 @@ +/target/ +/target/ +/target/ +/target/ +/target/ +/target/ diff --git a/tests/annotation/jwt/src/test/java/demo/ApplicationTests.java b/tests/annotation/jwt/src/test/java/demo/ApplicationTests.java index b6abb23ed..e7dd671c2 100644 --- a/tests/annotation/jwt/src/test/java/demo/ApplicationTests.java +++ b/tests/annotation/jwt/src/test/java/demo/ApplicationTests.java @@ -5,17 +5,17 @@ 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.token.TokenStore; import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; -import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class) @WebAppConfiguration -@ActiveProfiles("test") +@IntegrationTest("server.port=0") public class ApplicationTests { @Autowired diff --git a/tests/annotation/jwt/src/test/resources/test.properties b/tests/annotation/jwt/src/test/resources/test.properties deleted file mode 100644 index 24466e50d..000000000 --- a/tests/annotation/jwt/src/test/resources/test.properties +++ /dev/null @@ -1 +0,0 @@ -server.port: 0 \ No newline at end of file diff --git a/tests/annotation/mappings/.gitignore b/tests/annotation/mappings/.gitignore new file mode 100644 index 000000000..a227dd5ab --- /dev/null +++ b/tests/annotation/mappings/.gitignore @@ -0,0 +1,7 @@ +/target/ +/target/ +/target/ +/target/ +/target/ +/target/ +/target/ diff --git a/tests/annotation/mappings/src/test/java/demo/ApplicationTests.java b/tests/annotation/mappings/src/test/java/demo/ApplicationTests.java index 8da63b411..15eca8da6 100644 --- a/tests/annotation/mappings/src/test/java/demo/ApplicationTests.java +++ b/tests/annotation/mappings/src/test/java/demo/ApplicationTests.java @@ -2,15 +2,15 @@ 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.ActiveProfiles; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class) @WebAppConfiguration -@ActiveProfiles("test") +@IntegrationTest("server.port=0") public class ApplicationTests { @Test diff --git a/tests/annotation/mappings/src/test/resources/test.properties b/tests/annotation/mappings/src/test/resources/test.properties deleted file mode 100644 index 73bcdecd2..000000000 --- a/tests/annotation/mappings/src/test/resources/test.properties +++ /dev/null @@ -1 +0,0 @@ -server.port: 0 diff --git a/tests/annotation/multi/.gitignore b/tests/annotation/multi/.gitignore new file mode 100644 index 000000000..993e2e793 --- /dev/null +++ b/tests/annotation/multi/.gitignore @@ -0,0 +1,6 @@ +/target/ +/target/ +/target/ +/target/ +/target/ +/target/ diff --git a/tests/annotation/multi/src/test/java/demo/ApplicationTests.java b/tests/annotation/multi/src/test/java/demo/ApplicationTests.java index 8da63b411..15eca8da6 100644 --- a/tests/annotation/multi/src/test/java/demo/ApplicationTests.java +++ b/tests/annotation/multi/src/test/java/demo/ApplicationTests.java @@ -2,15 +2,15 @@ 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.ActiveProfiles; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class) @WebAppConfiguration -@ActiveProfiles("test") +@IntegrationTest("server.port=0") public class ApplicationTests { @Test diff --git a/tests/annotation/multi/src/test/resources/test.properties b/tests/annotation/multi/src/test/resources/test.properties deleted file mode 100644 index 24466e50d..000000000 --- a/tests/annotation/multi/src/test/resources/test.properties +++ /dev/null @@ -1 +0,0 @@ -server.port: 0 \ No newline at end of file diff --git a/tests/annotation/resource/.gitignore b/tests/annotation/resource/.gitignore new file mode 100644 index 000000000..993e2e793 --- /dev/null +++ b/tests/annotation/resource/.gitignore @@ -0,0 +1,6 @@ +/target/ +/target/ +/target/ +/target/ +/target/ +/target/ diff --git a/tests/annotation/resource/src/test/java/demo/ApplicationTests.java b/tests/annotation/resource/src/test/java/demo/ApplicationTests.java index 8da63b411..15eca8da6 100644 --- a/tests/annotation/resource/src/test/java/demo/ApplicationTests.java +++ b/tests/annotation/resource/src/test/java/demo/ApplicationTests.java @@ -2,15 +2,15 @@ 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.ActiveProfiles; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class) @WebAppConfiguration -@ActiveProfiles("test") +@IntegrationTest("server.port=0") public class ApplicationTests { @Test diff --git a/tests/annotation/resource/src/test/resources/test.properties b/tests/annotation/resource/src/test/resources/test.properties deleted file mode 100644 index 24466e50d..000000000 --- a/tests/annotation/resource/src/test/resources/test.properties +++ /dev/null @@ -1 +0,0 @@ -server.port: 0 \ No newline at end of file diff --git a/tests/annotation/vanilla/.gitignore b/tests/annotation/vanilla/.gitignore new file mode 100644 index 000000000..993e2e793 --- /dev/null +++ b/tests/annotation/vanilla/.gitignore @@ -0,0 +1,6 @@ +/target/ +/target/ +/target/ +/target/ +/target/ +/target/ diff --git a/tests/annotation/vanilla/src/test/java/demo/ApplicationTests.java b/tests/annotation/vanilla/src/test/java/demo/ApplicationTests.java index 8da63b411..15eca8da6 100644 --- a/tests/annotation/vanilla/src/test/java/demo/ApplicationTests.java +++ b/tests/annotation/vanilla/src/test/java/demo/ApplicationTests.java @@ -2,15 +2,15 @@ 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.ActiveProfiles; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class) @WebAppConfiguration -@ActiveProfiles("test") +@IntegrationTest("server.port=0") public class ApplicationTests { @Test diff --git a/tests/annotation/vanilla/src/test/resources/test.properties b/tests/annotation/vanilla/src/test/resources/test.properties deleted file mode 100644 index 24466e50d..000000000 --- a/tests/annotation/vanilla/src/test/resources/test.properties +++ /dev/null @@ -1 +0,0 @@ -server.port: 0 \ No newline at end of file From 0b2e90a6650044410a8be8bd76bd98be7c8fb3e7 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Sat, 23 Aug 2014 12:06:28 +0100 Subject: [PATCH 285/831] Update XML tests and upgrade Spring Boot --- tests/annotation/approval/.gitignore | 3 + tests/annotation/client/.gitignore | 7 +++ tests/annotation/common/.gitignore | 3 + .../common/AbstractIntegrationTests.java | 12 ---- tests/annotation/form/.gitignore | 3 + tests/annotation/jdbc/.gitignore | 11 ++++ .../jdbc/src/main/java/demo/Application.java | 34 ++++------- tests/annotation/jwt/.gitignore | 4 ++ tests/annotation/mappings/.gitignore | 4 ++ tests/annotation/multi/.gitignore | 6 ++ tests/annotation/pom.xml | 4 +- tests/annotation/resource/.gitignore | 6 ++ tests/annotation/vanilla/.gitignore | 4 ++ .../src/test/java/demo/ApplicationTests.java | 4 +- .../src/test/resources/test.properties | 1 - .../test/java/client/ApplicationTests.java | 4 +- .../client/src/test/resources/test.properties | 1 - ...bstractAuthorizationCodeProviderTests.java | 3 - ...bstractClientCredentialsProviderTests.java | 4 -- .../common/AbstractImplicitProviderTests.java | 3 - .../common/AbstractIntegrationTests.java | 59 ++++++++++++------- ...actResourceOwnerPasswordProviderTests.java | 2 - .../java/sparklr/common/HttpTestUtils.java | 53 +++++------------ .../main/java/sparklr/common/PortHolder.java | 24 -------- .../src/test/java/demo/ApplicationTests.java | 4 +- .../form/src/test/resources/test.properties | 1 - .../jdbc/src/main/java/demo/Application.java | 53 ++++++++++------- .../jdbc/src/main/resources/application.yml | 5 ++ tests/xml/jdbc/src/main/resources/data.sql | 8 --- tests/xml/jdbc/src/main/resources/logback.xml | 8 --- tests/xml/jdbc/src/main/resources/schema.sql | 9 +++ .../src/test/java/demo/ApplicationTests.java | 4 +- .../jdbc/src/test/resources/test.properties | 1 - .../src/test/java/demo/ApplicationTests.java | 4 +- .../jwt/src/test/resources/test.properties | 1 - .../src/test/java/demo/ApplicationTests.java | 4 +- .../src/test/resources/test.properties | 1 - tests/xml/pom.xml | 4 +- .../src/test/java/demo/ApplicationTests.java | 4 +- .../src/test/resources/test.properties | 1 - 40 files changed, 180 insertions(+), 191 deletions(-) delete mode 100644 tests/xml/approval/src/test/resources/test.properties delete mode 100644 tests/xml/client/src/test/resources/test.properties delete mode 100644 tests/xml/common/src/main/java/sparklr/common/PortHolder.java delete mode 100644 tests/xml/form/src/test/resources/test.properties delete mode 100644 tests/xml/jdbc/src/main/resources/data.sql delete mode 100644 tests/xml/jdbc/src/main/resources/logback.xml delete mode 100644 tests/xml/jwt/src/test/resources/test.properties delete mode 100644 tests/xml/mappings/src/test/resources/test.properties delete mode 100644 tests/xml/vanilla/src/test/resources/test.properties diff --git a/tests/annotation/approval/.gitignore b/tests/annotation/approval/.gitignore index a227dd5ab..7b791414a 100644 --- a/tests/annotation/approval/.gitignore +++ b/tests/annotation/approval/.gitignore @@ -5,3 +5,6 @@ /target/ /target/ /target/ +/target/ +/target/ +/target/ diff --git a/tests/annotation/client/.gitignore b/tests/annotation/client/.gitignore index 8352667a7..963051b11 100644 --- a/tests/annotation/client/.gitignore +++ b/tests/annotation/client/.gitignore @@ -7,3 +7,10 @@ /target/ /target/ /target/ +/target/ +/target/ +/target/ +/target/ +/target/ +/target/ +/target/ diff --git a/tests/annotation/common/.gitignore b/tests/annotation/common/.gitignore index 32362a30c..8e1fb9a6b 100644 --- a/tests/annotation/common/.gitignore +++ b/tests/annotation/common/.gitignore @@ -9,3 +9,6 @@ /target/ /target/ /target/ +/target/ +/target/ +/target/ 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 95aafef77..2f68e61d8 100644 --- a/tests/annotation/common/src/main/java/sparklr/common/AbstractIntegrationTests.java +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractIntegrationTests.java @@ -26,9 +26,6 @@ import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.context.embedded.EmbeddedWebApplicationContext; import org.springframework.boot.test.IntegrationTest; -import org.springframework.boot.test.SpringApplicationConfiguration; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.PropertySource; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.security.crypto.codec.Base64; import org.springframework.security.oauth2.client.resource.BaseOAuth2ProtectedResourceDetails; @@ -46,9 +43,6 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; -import sparklr.common.AbstractIntegrationTests.TestConfiguration; - -@SpringApplicationConfiguration(classes = TestConfiguration.class, inheritLocations = true) @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @IntegrationTest("server.port=0") @@ -196,10 +190,4 @@ public static String authorizePath() { return globalAuthorizePath; } - @Configuration - @PropertySource(value = "classpath:test.properties", ignoreResourceNotFound = true) - protected static class TestConfiguration { - - } - } \ No newline at end of file diff --git a/tests/annotation/form/.gitignore b/tests/annotation/form/.gitignore index 993e2e793..8352667a7 100644 --- a/tests/annotation/form/.gitignore +++ b/tests/annotation/form/.gitignore @@ -4,3 +4,6 @@ /target/ /target/ /target/ +/target/ +/target/ +/target/ diff --git a/tests/annotation/jdbc/.gitignore b/tests/annotation/jdbc/.gitignore index 993e2e793..6b1fa3918 100644 --- a/tests/annotation/jdbc/.gitignore +++ b/tests/annotation/jdbc/.gitignore @@ -4,3 +4,14 @@ /target/ /target/ /target/ +/target/ +/target/ +/target/ +/target/ +/target/ +/target/ +/target/ +/target/ +/target/ +/target/ +/target/ diff --git a/tests/annotation/jdbc/src/main/java/demo/Application.java b/tests/annotation/jdbc/src/main/java/demo/Application.java index c752fa832..0f5ab8baf 100644 --- a/tests/annotation/jdbc/src/main/java/demo/Application.java +++ b/tests/annotation/jdbc/src/main/java/demo/Application.java @@ -9,7 +9,6 @@ import org.springframework.boot.autoconfigure.security.SecurityProperties.User; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.DependsOn; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.security.authentication.AuthenticationManager; @@ -35,13 +34,6 @@ @RestController public class Application { - @Bean - @DependsOn("dataSourceAutoConfigurationInitializer") - // @DependsOn only works if it is on a @Bean, so we can't use an @Import here - protected AuthenticationManagerConfiguration authenticationManagerConfiguration() { - return new AuthenticationManagerConfiguration(); - } - public static void main(String[] args) { SpringApplication.run(Application.class, args); } @@ -125,26 +117,26 @@ public void configure(ClientDetailsServiceConfigurer clients) throws Exception { } -} - -@Configuration -@Order(Ordered.HIGHEST_PRECEDENCE + 10) -class AuthenticationManagerConfiguration extends GlobalAuthenticationConfigurerAdapter { + @Configuration + @Order(Ordered.HIGHEST_PRECEDENCE + 10) + protected static class AuthenticationManagerConfiguration extends GlobalAuthenticationConfigurerAdapter { - @Autowired - private DataSource dataSource; + @Autowired + private DataSource dataSource; - @Autowired - private SecurityProperties security; + @Autowired + private SecurityProperties security; - @Override - public void init(AuthenticationManagerBuilder auth) throws Exception { - User user = security.getUser(); - // @formatter:off + @Override + public void init(AuthenticationManagerBuilder auth) throws Exception { + User user = security.getUser(); + // @formatter:off auth.jdbcAuthentication().dataSource(dataSource) .withUser(user.getName()) .password(user.getPassword()) .roles(user.getRole().toArray(new String[0])); // @formatter:on + } } + } diff --git a/tests/annotation/jwt/.gitignore b/tests/annotation/jwt/.gitignore index 993e2e793..7b791414a 100644 --- a/tests/annotation/jwt/.gitignore +++ b/tests/annotation/jwt/.gitignore @@ -4,3 +4,7 @@ /target/ /target/ /target/ +/target/ +/target/ +/target/ +/target/ diff --git a/tests/annotation/mappings/.gitignore b/tests/annotation/mappings/.gitignore index a227dd5ab..32362a30c 100644 --- a/tests/annotation/mappings/.gitignore +++ b/tests/annotation/mappings/.gitignore @@ -5,3 +5,7 @@ /target/ /target/ /target/ +/target/ +/target/ +/target/ +/target/ diff --git a/tests/annotation/multi/.gitignore b/tests/annotation/multi/.gitignore index 993e2e793..2a7c772f3 100644 --- a/tests/annotation/multi/.gitignore +++ b/tests/annotation/multi/.gitignore @@ -4,3 +4,9 @@ /target/ /target/ /target/ +/target/ +/target/ +/target/ +/target/ +/target/ +/target/ diff --git a/tests/annotation/pom.xml b/tests/annotation/pom.xml index 82e74179c..95df02f61 100644 --- a/tests/annotation/pom.xml +++ b/tests/annotation/pom.xml @@ -26,7 +26,7 @@ org.springframework.boot spring-boot-starter-parent - 1.1.1.RELEASE + 1.1.5.RELEASE @@ -45,7 +45,7 @@ org.springframework.security spring-security-jwt - 1.0.1.RELEASE + 1.0.2.RELEASE diff --git a/tests/annotation/resource/.gitignore b/tests/annotation/resource/.gitignore index 993e2e793..2a7c772f3 100644 --- a/tests/annotation/resource/.gitignore +++ b/tests/annotation/resource/.gitignore @@ -4,3 +4,9 @@ /target/ /target/ /target/ +/target/ +/target/ +/target/ +/target/ +/target/ +/target/ diff --git a/tests/annotation/vanilla/.gitignore b/tests/annotation/vanilla/.gitignore index 993e2e793..7b791414a 100644 --- a/tests/annotation/vanilla/.gitignore +++ b/tests/annotation/vanilla/.gitignore @@ -4,3 +4,7 @@ /target/ /target/ /target/ +/target/ +/target/ +/target/ +/target/ diff --git a/tests/xml/approval/src/test/java/demo/ApplicationTests.java b/tests/xml/approval/src/test/java/demo/ApplicationTests.java index 8da63b411..15eca8da6 100644 --- a/tests/xml/approval/src/test/java/demo/ApplicationTests.java +++ b/tests/xml/approval/src/test/java/demo/ApplicationTests.java @@ -2,15 +2,15 @@ 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.ActiveProfiles; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class) @WebAppConfiguration -@ActiveProfiles("test") +@IntegrationTest("server.port=0") public class ApplicationTests { @Test diff --git a/tests/xml/approval/src/test/resources/test.properties b/tests/xml/approval/src/test/resources/test.properties deleted file mode 100644 index 24466e50d..000000000 --- a/tests/xml/approval/src/test/resources/test.properties +++ /dev/null @@ -1 +0,0 @@ -server.port: 0 \ No newline at end of file diff --git a/tests/xml/client/src/test/java/client/ApplicationTests.java b/tests/xml/client/src/test/java/client/ApplicationTests.java index a8ea1b1c1..8c5aef34a 100644 --- a/tests/xml/client/src/test/java/client/ApplicationTests.java +++ b/tests/xml/client/src/test/java/client/ApplicationTests.java @@ -2,15 +2,15 @@ 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.ActiveProfiles; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = ClientApplication.class) @WebAppConfiguration -@ActiveProfiles("test") +@IntegrationTest("server.port=0") public class ApplicationTests { @Test diff --git a/tests/xml/client/src/test/resources/test.properties b/tests/xml/client/src/test/resources/test.properties deleted file mode 100644 index 24466e50d..000000000 --- a/tests/xml/client/src/test/resources/test.properties +++ /dev/null @@ -1 +0,0 @@ -server.port: 0 \ No newline at end of file diff --git a/tests/xml/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java b/tests/xml/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java index bcebe3a2d..8a9610a4e 100755 --- a/tests/xml/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java +++ b/tests/xml/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java @@ -414,9 +414,6 @@ public MyTrustedClient(Object target) { setClientId("my-trusted-client"); setScope(Arrays.asList("read")); setId(getClientId()); - AbstractAuthorizationCodeProviderTests test = (AbstractAuthorizationCodeProviderTests) target; - setAccessTokenUri(test.http.getUrl(tokenPath())); - setUserAuthorizationUri(test.http.getUrl(authorizePath())); } } diff --git a/tests/xml/common/src/main/java/sparklr/common/AbstractClientCredentialsProviderTests.java b/tests/xml/common/src/main/java/sparklr/common/AbstractClientCredentialsProviderTests.java index bc4135dc8..895462590 100644 --- a/tests/xml/common/src/main/java/sparklr/common/AbstractClientCredentialsProviderTests.java +++ b/tests/xml/common/src/main/java/sparklr/common/AbstractClientCredentialsProviderTests.java @@ -84,8 +84,6 @@ public ClientCredentials(Object target) { setClientSecret("secret"); setScope(Arrays.asList("read")); setId(getClientId()); - AbstractClientCredentialsProviderTests test = (AbstractClientCredentialsProviderTests) target; - setAccessTokenUri(test.http.getUrl(tokenPath())); } } @@ -102,8 +100,6 @@ public NoScopeClientCredentials(Object target) { setClientId("my-client-with-secret"); setClientSecret("secret"); setId(getClientId()); - AbstractClientCredentialsProviderTests test = (AbstractClientCredentialsProviderTests) target; - setAccessTokenUri(test.http.getUrl(tokenPath())); } } diff --git a/tests/xml/common/src/main/java/sparklr/common/AbstractImplicitProviderTests.java b/tests/xml/common/src/main/java/sparklr/common/AbstractImplicitProviderTests.java index 2f0cf9cc9..5e1c47d55 100644 --- a/tests/xml/common/src/main/java/sparklr/common/AbstractImplicitProviderTests.java +++ b/tests/xml/common/src/main/java/sparklr/common/AbstractImplicitProviderTests.java @@ -43,9 +43,6 @@ public NonAutoApproveImplicit(Object target) { setClientId("my-trusted-client"); setId(getClientId()); setPreEstablishedRedirectUri("http://anywhere/"); - AbstractImplicitProviderTests test = (AbstractImplicitProviderTests) target; - setAccessTokenUri(test.http.getUrl(authorizePath())); - setUserAuthorizationUri(test.http.getUrl(authorizePath())); } } diff --git a/tests/xml/common/src/main/java/sparklr/common/AbstractIntegrationTests.java b/tests/xml/common/src/main/java/sparklr/common/AbstractIntegrationTests.java index d698f9091..ac2f12db7 100644 --- a/tests/xml/common/src/main/java/sparklr/common/AbstractIntegrationTests.java +++ b/tests/xml/common/src/main/java/sparklr/common/AbstractIntegrationTests.java @@ -21,13 +21,16 @@ import org.springframework.aop.framework.Advised; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.context.embedded.EmbeddedWebApplicationContext; +import org.springframework.boot.autoconfigure.security.SecurityProperties; +import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.test.IntegrationTest; -import org.springframework.boot.test.SpringApplicationConfiguration; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.PropertySource; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.security.oauth2.client.resource.BaseOAuth2ProtectedResourceDetails; +import org.springframework.security.oauth2.client.test.BeforeOAuth2Context; import org.springframework.security.oauth2.client.test.OAuth2ContextSetup; +import org.springframework.security.oauth2.client.token.grant.implicit.ImplicitResourceDetails; +import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordResourceDetails; +import org.springframework.security.oauth2.client.token.grant.redirect.AbstractRedirectResourceDetails; import org.springframework.security.oauth2.provider.approval.ApprovalStore; import org.springframework.security.oauth2.provider.approval.InMemoryApprovalStore; import org.springframework.security.oauth2.provider.approval.JdbcApprovalStore; @@ -37,26 +40,29 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; -import sparklr.common.AbstractIntegrationTests.TestConfiguration; - -@SpringApplicationConfiguration(classes = TestConfiguration.class, inheritLocations = true) @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration -@IntegrationTest -public abstract class AbstractIntegrationTests implements PortHolder { +@IntegrationTest("server.port=0") +public abstract class AbstractIntegrationTests { + + @Value("${local.server.port}") + private int port; private static String globalTokenPath; private static String globalAuthorizePath; @Rule - public HttpTestUtils http = HttpTestUtils.standard().setPortHolder(this); + public HttpTestUtils http = HttpTestUtils.standard(); @Rule public OAuth2ContextSetup context = OAuth2ContextSetup.standard(http); @Autowired - private EmbeddedWebApplicationContext server; + private ServerProperties server; + + @Autowired + protected SecurityProperties security; @Autowired(required=false) private TokenStore tokenStore; @@ -67,17 +73,32 @@ public abstract class AbstractIntegrationTests implements PortHolder { @Autowired(required=false) private DataSource dataSource; - @Override - public int getPort() { - return server == null ? 8080 : server.getEmbeddedServletContainer().getPort(); - } - @Before public void init() throws Exception { + http.setPort(port); clear(tokenStore); clear(approvalStore); } + @BeforeOAuth2Context + public void fixPaths() { + String prefix = server.getServletPrefix(); + http.setPort(port); + http.setPrefix(prefix); + BaseOAuth2ProtectedResourceDetails resource = (BaseOAuth2ProtectedResourceDetails) context.getResource(); + resource.setAccessTokenUri(http.getUrl(tokenPath())); + if (resource instanceof AbstractRedirectResourceDetails) { + ((AbstractRedirectResourceDetails) resource).setUserAuthorizationUri(http.getUrl(authorizePath())); + } + if (resource instanceof ImplicitResourceDetails) { + resource.setAccessTokenUri(http.getUrl(authorizePath())); + } + if (resource instanceof ResourceOwnerPasswordResourceDetails) { + ((ResourceOwnerPasswordResourceDetails) resource).setUsername(security.getUser().getName()); + ((ResourceOwnerPasswordResourceDetails) resource).setPassword(security.getUser().getPassword()); + } + } + private void clear(ApprovalStore approvalStore) throws Exception { if (approvalStore instanceof Advised) { Advised advised = (Advised) tokenStore; @@ -131,10 +152,4 @@ public static String authorizePath() { return globalAuthorizePath; } - @Configuration - @PropertySource(value = "classpath:test.properties", ignoreResourceNotFound = true) - protected static class TestConfiguration { - - } - } \ No newline at end of file diff --git a/tests/xml/common/src/main/java/sparklr/common/AbstractResourceOwnerPasswordProviderTests.java b/tests/xml/common/src/main/java/sparklr/common/AbstractResourceOwnerPasswordProviderTests.java index 37536940e..1aee44bc6 100644 --- a/tests/xml/common/src/main/java/sparklr/common/AbstractResourceOwnerPasswordProviderTests.java +++ b/tests/xml/common/src/main/java/sparklr/common/AbstractResourceOwnerPasswordProviderTests.java @@ -203,8 +203,6 @@ public ResourceOwner(Object target) { setId(getClientId()); setUsername("user"); setPassword("password"); - AbstractResourceOwnerPasswordProviderTests test = (AbstractResourceOwnerPasswordProviderTests) target; - setAccessTokenUri(test.http.getUrl(tokenPath())); } } diff --git a/tests/xml/common/src/main/java/sparklr/common/HttpTestUtils.java b/tests/xml/common/src/main/java/sparklr/common/HttpTestUtils.java index 2b3cb220c..6d7595c85 100644 --- a/tests/xml/common/src/main/java/sparklr/common/HttpTestUtils.java +++ b/tests/xml/common/src/main/java/sparklr/common/HttpTestUtils.java @@ -1,14 +1,11 @@ package sparklr.common; -import java.net.HttpURLConnection; import java.net.URI; import java.util.Arrays; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.junit.rules.MethodRule; import org.junit.runners.model.FrameworkMethod; import org.junit.runners.model.Statement; @@ -21,7 +18,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.security.oauth2.client.test.RestTemplateHolder; import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestClientException; +import org.springframework.util.StringUtils; import org.springframework.web.client.RestOperations; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriTemplate; @@ -37,8 +34,6 @@ */ public class HttpTestUtils implements MethodRule, RestTemplateHolder { - private static Log logger = LogFactory.getLog(HttpTestUtils.class); - private static int DEFAULT_PORT = 8080; private static String DEFAULT_HOST = "localhost"; @@ -49,7 +44,7 @@ public class HttpTestUtils implements MethodRule, RestTemplateHolder { private RestOperations client; - private PortHolder portHolder; + private String prefix = ""; /** * @return a new rule that sets up default host and port etc. @@ -62,6 +57,18 @@ private HttpTestUtils() { setPort(DEFAULT_PORT); } + /** + * @param prefix + */ + public void setPrefix(String prefix) { + if (!StringUtils.hasText(prefix)) { + prefix = ""; + } else while (prefix.endsWith("/")) { + prefix = prefix.substring(0, prefix.lastIndexOf("/")); + } + this.prefix = prefix; + } + /** * @param port the port to set */ @@ -73,14 +80,6 @@ public HttpTestUtils setPort(int port) { return this; } - /** - * @param port the port holder to set - */ - public HttpTestUtils setPortHolder(PortHolder port) { - this.portHolder = port; - return this; - } - /** * @param hostName the hostName to set */ @@ -91,26 +90,6 @@ public HttpTestUtils setHostName(String hostName) { public Statement apply(final Statement base, FrameworkMethod method, Object target) { - if (portHolder!=null) { - setPort(portHolder.getPort()); - } - - RestTemplate client = new RestTemplate(); - boolean followRedirects = HttpURLConnection.getFollowRedirects(); - HttpURLConnection.setFollowRedirects(false); - try { - client.getForEntity(new UriTemplate(getUrl("/admin/info")).toString(), String.class); - logger.info("Basic connectivity test passed"); - } - catch (RestClientException e) { - logger.warn(String.format( - "Not executing tests because basic connectivity test failed for hostName=%s, port=%d", hostName, - port), e); - } - finally { - HttpURLConnection.setFollowRedirects(followRedirects); - } - return new Statement() { @Override public void evaluate() throws Throwable { @@ -121,7 +100,7 @@ public void evaluate() throws Throwable { } public String getBaseUrl() { - return "http://" + hostName + ":" + port; + return "http://" + hostName + ":" + port + prefix; } public String getUrl(String path) { @@ -131,7 +110,7 @@ public String getUrl(String path) { if (!path.startsWith("/")) { path = "/" + path; } - return "http://" + hostName + ":" + port + path; + return "http://" + hostName + ":" + port + prefix + path; } public ResponseEntity postForString(String path, MultiValueMap formData) { diff --git a/tests/xml/common/src/main/java/sparklr/common/PortHolder.java b/tests/xml/common/src/main/java/sparklr/common/PortHolder.java deleted file mode 100644 index 362dceda8..000000000 --- a/tests/xml/common/src/main/java/sparklr/common/PortHolder.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2013-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ - -package sparklr.common; - -/** - * @author Dave Syer - * - */ -public interface PortHolder { - - int getPort(); - -} diff --git a/tests/xml/form/src/test/java/demo/ApplicationTests.java b/tests/xml/form/src/test/java/demo/ApplicationTests.java index 8da63b411..15eca8da6 100644 --- a/tests/xml/form/src/test/java/demo/ApplicationTests.java +++ b/tests/xml/form/src/test/java/demo/ApplicationTests.java @@ -2,15 +2,15 @@ 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.ActiveProfiles; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class) @WebAppConfiguration -@ActiveProfiles("test") +@IntegrationTest("server.port=0") public class ApplicationTests { @Test diff --git a/tests/xml/form/src/test/resources/test.properties b/tests/xml/form/src/test/resources/test.properties deleted file mode 100644 index 24466e50d..000000000 --- a/tests/xml/form/src/test/resources/test.properties +++ /dev/null @@ -1 +0,0 @@ -server.port: 0 \ No newline at end of file diff --git a/tests/xml/jdbc/src/main/java/demo/Application.java b/tests/xml/jdbc/src/main/java/demo/Application.java index aa302dba3..644912f9f 100644 --- a/tests/xml/jdbc/src/main/java/demo/Application.java +++ b/tests/xml/jdbc/src/main/java/demo/Application.java @@ -12,10 +12,12 @@ import org.springframework.boot.context.embedded.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.DependsOn; import org.springframework.context.annotation.ImportResource; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.http.SessionCreationPolicy; @@ -46,30 +48,16 @@ @ImportResource("classpath:/application.xml") public class Application { - @Order(Ordered.LOWEST_PRECEDENCE - 8) - protected static class ApplicationSecurity extends WebSecurityConfigurerAdapter { - - @Autowired - private DataSource dataSource; - - @Autowired - private SecurityProperties security; - - @Override - protected void configure(AuthenticationManagerBuilder auth) throws Exception { - User user = security.getUser(); - // @formatter:off - auth.jdbcAuthentication().dataSource(dataSource) - .withUser(user.getName()) - .password(user.getPassword()) - .roles(user.getRole().toArray(new String[0])); - // @formatter:on - } - } - public static void main(String[] args) { SpringApplication.run(Application.class, args); } + + @Bean + @DependsOn("dataSourceInitializer") + // @DependsOn only works if it is on a @Bean, so we can't use an @Import here + protected AuthenticationManagerConfiguration authenticationManagerConfiguration() { + return new AuthenticationManagerConfiguration(); + } @RequestMapping("/") public String home() { @@ -113,7 +101,7 @@ protected static class OAuth2Config { @Autowired private DataSource dataSource; - + @Bean public JdbcClientDetailsService clientDetailsService() { return new JdbcClientDetailsService(dataSource); @@ -199,3 +187,24 @@ protected AuthenticationEntryPoint authenticationEntryPoint() { } } + +@Order(Ordered.LOWEST_PRECEDENCE - 8) +class AuthenticationManagerConfiguration extends GlobalAuthenticationConfigurerAdapter { + + @Autowired + private DataSource dataSource; + + @Autowired + private SecurityProperties security; + + @Override + public void init(AuthenticationManagerBuilder auth) throws Exception { + User user = security.getUser(); + // @formatter:off + auth.jdbcAuthentication().dataSource(dataSource) + .withUser(user.getName()) + .password(user.getPassword()) + .roles(user.getRole().toArray(new String[0])); + // @formatter:on + } +} diff --git a/tests/xml/jdbc/src/main/resources/application.yml b/tests/xml/jdbc/src/main/resources/application.yml index c2b03892c..b9ce01048 100644 --- a/tests/xml/jdbc/src/main/resources/application.yml +++ b/tests/xml/jdbc/src/main/resources/application.yml @@ -6,6 +6,11 @@ management: security: user: password: password +logging: + level: + org.springframework.security: DEBUG +# org.springframework.web: DEBUG + org.springframework.jdbc: DEBUG --- diff --git a/tests/xml/jdbc/src/main/resources/data.sql b/tests/xml/jdbc/src/main/resources/data.sql deleted file mode 100644 index ccb9d2481..000000000 --- a/tests/xml/jdbc/src/main/resources/data.sql +++ /dev/null @@ -1,8 +0,0 @@ -insert into oauth_client_details (client_id, resource_ids, scope, authorized_grant_types, authorities, access_token_validity) - values ('my-trusted-client', 'oauth2-resource', 'read,write,trust', 'password,authorization_code,refresh_token,implicit', 'ROLE_CLIENT,ROLE_TRUSTED_CLIENT', 60); - -insert into oauth_client_details (client_id, resource_ids, scope, authorized_grant_types, authorities, web_server_redirect_uri) - values ('my-client-with-registered-redirect', 'oauth2-resource', 'read,trust', 'authorization_code', 'ROLE_CLIENT', 'http://anywhere/?key=value'); - -insert into oauth_client_details (client_id, client_secret, resource_ids, scope, authorized_grant_types, authorities) - values ('my-client-with-secret', 'secret', 'oauth2-resource', 'read', 'password,client_credentials', 'ROLE_CLIENT'); diff --git a/tests/xml/jdbc/src/main/resources/logback.xml b/tests/xml/jdbc/src/main/resources/logback.xml deleted file mode 100644 index 8ddbd55bf..000000000 --- a/tests/xml/jdbc/src/main/resources/logback.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/tests/xml/jdbc/src/main/resources/schema.sql b/tests/xml/jdbc/src/main/resources/schema.sql index 5ffe631a8..7a969a0f7 100644 --- a/tests/xml/jdbc/src/main/resources/schema.sql +++ b/tests/xml/jdbc/src/main/resources/schema.sql @@ -51,3 +51,12 @@ create table oauth_code ( code VARCHAR(256), authentication LONGVARBINARY ); +insert into oauth_client_details (client_id, resource_ids, scope, authorized_grant_types, authorities, access_token_validity) + values ('my-trusted-client', 'oauth2-resource', 'read,write,trust', 'password,authorization_code,refresh_token,implicit', 'ROLE_CLIENT,ROLE_TRUSTED_CLIENT', 60); + +insert into oauth_client_details (client_id, resource_ids, scope, authorized_grant_types, authorities, web_server_redirect_uri) + values ('my-client-with-registered-redirect', 'oauth2-resource', 'read,trust', 'authorization_code', 'ROLE_CLIENT', 'http://anywhere/?key=value'); + +insert into oauth_client_details (client_id, client_secret, resource_ids, scope, authorized_grant_types, authorities) + values ('my-client-with-secret', 'secret', 'oauth2-resource', 'read', 'password,client_credentials', 'ROLE_CLIENT'); + diff --git a/tests/xml/jdbc/src/test/java/demo/ApplicationTests.java b/tests/xml/jdbc/src/test/java/demo/ApplicationTests.java index 055467fe5..5d1ebbbee 100644 --- a/tests/xml/jdbc/src/test/java/demo/ApplicationTests.java +++ b/tests/xml/jdbc/src/test/java/demo/ApplicationTests.java @@ -5,17 +5,17 @@ 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.token.TokenStore; import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore; -import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class) @WebAppConfiguration -@ActiveProfiles("test") +@IntegrationTest("server.port=0") public class ApplicationTests { @Autowired diff --git a/tests/xml/jdbc/src/test/resources/test.properties b/tests/xml/jdbc/src/test/resources/test.properties index bf241d8a4..5be638806 100644 --- a/tests/xml/jdbc/src/test/resources/test.properties +++ b/tests/xml/jdbc/src/test/resources/test.properties @@ -1,2 +1 @@ -server.port: 0 spring.datasource.url: jdbc:h2:mem:otherdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE \ No newline at end of file diff --git a/tests/xml/jwt/src/test/java/demo/ApplicationTests.java b/tests/xml/jwt/src/test/java/demo/ApplicationTests.java index b6abb23ed..e7dd671c2 100644 --- a/tests/xml/jwt/src/test/java/demo/ApplicationTests.java +++ b/tests/xml/jwt/src/test/java/demo/ApplicationTests.java @@ -5,17 +5,17 @@ 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.token.TokenStore; import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; -import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class) @WebAppConfiguration -@ActiveProfiles("test") +@IntegrationTest("server.port=0") public class ApplicationTests { @Autowired diff --git a/tests/xml/jwt/src/test/resources/test.properties b/tests/xml/jwt/src/test/resources/test.properties deleted file mode 100644 index 24466e50d..000000000 --- a/tests/xml/jwt/src/test/resources/test.properties +++ /dev/null @@ -1 +0,0 @@ -server.port: 0 \ No newline at end of file diff --git a/tests/xml/mappings/src/test/java/demo/ApplicationTests.java b/tests/xml/mappings/src/test/java/demo/ApplicationTests.java index 8da63b411..15eca8da6 100644 --- a/tests/xml/mappings/src/test/java/demo/ApplicationTests.java +++ b/tests/xml/mappings/src/test/java/demo/ApplicationTests.java @@ -2,15 +2,15 @@ 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.ActiveProfiles; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class) @WebAppConfiguration -@ActiveProfiles("test") +@IntegrationTest("server.port=0") public class ApplicationTests { @Test diff --git a/tests/xml/mappings/src/test/resources/test.properties b/tests/xml/mappings/src/test/resources/test.properties deleted file mode 100644 index 73bcdecd2..000000000 --- a/tests/xml/mappings/src/test/resources/test.properties +++ /dev/null @@ -1 +0,0 @@ -server.port: 0 diff --git a/tests/xml/pom.xml b/tests/xml/pom.xml index 853d73c1c..7b9ea1e75 100644 --- a/tests/xml/pom.xml +++ b/tests/xml/pom.xml @@ -24,7 +24,7 @@ org.springframework.boot spring-boot-starter-parent - 1.1.1.RELEASE + 1.1.5.RELEASE @@ -43,7 +43,7 @@ org.springframework.security spring-security-jwt - 1.0.1.RELEASE + 1.0.2.RELEASE diff --git a/tests/xml/vanilla/src/test/java/demo/ApplicationTests.java b/tests/xml/vanilla/src/test/java/demo/ApplicationTests.java index 8da63b411..15eca8da6 100644 --- a/tests/xml/vanilla/src/test/java/demo/ApplicationTests.java +++ b/tests/xml/vanilla/src/test/java/demo/ApplicationTests.java @@ -2,15 +2,15 @@ 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.ActiveProfiles; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class) @WebAppConfiguration -@ActiveProfiles("test") +@IntegrationTest("server.port=0") public class ApplicationTests { @Test diff --git a/tests/xml/vanilla/src/test/resources/test.properties b/tests/xml/vanilla/src/test/resources/test.properties deleted file mode 100644 index 24466e50d..000000000 --- a/tests/xml/vanilla/src/test/resources/test.properties +++ /dev/null @@ -1 +0,0 @@ -server.port: 0 \ No newline at end of file From c7561fb95615faf77786d2799956c348238e2f04 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 27 Aug 2014 18:57:59 +0100 Subject: [PATCH 286/831] Make OAuth2ClientAuthenticationProcessingFilter behave more like a resource server --- ...2ClientAuthenticationProcessingFilter.java | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilter.java index 1e7edf497..4c1dbac5f 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilter.java @@ -22,6 +22,8 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.springframework.security.authentication.AuthenticationDetailsSource; +import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; @@ -30,7 +32,8 @@ import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationManager; +import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails; +import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetailsSource; import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices; import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; import org.springframework.util.Assert; @@ -48,6 +51,8 @@ public class OAuth2ClientAuthenticationProcessingFilter extends AbstractAuthenti private ResourceServerTokenServices tokenServices; + private AuthenticationDetailsSource authenticationDetailsSource = new OAuth2AuthenticationDetailsSource(); + /** * Reference to a CheckTokenServices that can validate an OAuth2AccessToken * @@ -65,10 +70,11 @@ public void setTokenServices(ResourceServerTokenServices tokenServices) { public void setRestTemplate(OAuth2RestOperations restTemplate) { this.restTemplate = restTemplate; } - + public OAuth2ClientAuthenticationProcessingFilter(String defaultFilterProcessesUrl) { super(defaultFilterProcessesUrl); - setAuthenticationManager(new OAuth2AuthenticationManager()); + setAuthenticationManager(new NoopAuthenticationManager()); + setAuthenticationDetailsSource(authenticationDetailsSource); } @Override @@ -84,6 +90,10 @@ public Authentication attemptAuthentication(HttpServletRequest request, HttpServ OAuth2AccessToken accessToken = restTemplate.getAccessToken(); try { OAuth2Authentication result = tokenServices.loadAuthentication(accessToken.getValue()); + if (authenticationDetailsSource!=null) { + request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_VALUE, accessToken.getValue()); + result.setDetails(authenticationDetailsSource.buildDetails(request)); + } return result; } catch (InvalidTokenException e) { @@ -104,5 +114,15 @@ protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServle super.unsuccessfulAuthentication(request, response, failed); } } + + private static class NoopAuthenticationManager implements AuthenticationManager { + + @Override + public Authentication authenticate(Authentication authentication) + throws AuthenticationException { + throw new UnsupportedOperationException("No authentication should be done with this AuthenticationManager"); + } + + } } \ No newline at end of file From 75d63559aedf5ce0dd3794d6fb66d228fa7ec630 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 27 Aug 2014 19:06:02 +0100 Subject: [PATCH 287/831] Add additional null check --- .../security/oauth2/provider/client/BaseClientDetails.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/BaseClientDetails.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/BaseClientDetails.java index a8ec566d9..f446218d7 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/BaseClientDetails.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/BaseClientDetails.java @@ -329,7 +329,7 @@ public int hashCode() { result = prime * result + ((resourceIds == null) ? 0 : resourceIds.hashCode()); result = prime * result + ((scope == null) ? 0 : scope.hashCode()); - result = prime * result + additionalInformation.hashCode(); + result = prime * result + ((additionalInformation == null) ? 0 : additionalInformation.hashCode()); return result; } From b847c8f134aa71f74efe3098fff6d4c095d63c3c Mon Sep 17 00:00:00 2001 From: Vincent Spiewak Date: Fri, 8 Aug 2014 17:13:03 +0200 Subject: [PATCH 288/831] Fix wrong LOG.isInfoEnabled in JdbcTokenStore --- .../security/oauth2/provider/token/store/JdbcTokenStore.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JdbcTokenStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JdbcTokenStore.java index f3af1b281..65bf03d27 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JdbcTokenStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JdbcTokenStore.java @@ -113,7 +113,7 @@ public OAuth2AccessToken mapRow(ResultSet rs, int rowNum) throws SQLException { }, key); } catch (EmptyResultDataAccessException e) { - if (LOG.isInfoEnabled()) { + if (LOG.isDebugEnabled()) { LOG.debug("Failed to find access token for authentication " + authentication); } } From 8323fe776c7cf11981673b8a638dcac4858711af Mon Sep 17 00:00:00 2001 From: Bill Kuker Date: Wed, 16 Jul 2014 16:24:18 -0400 Subject: [PATCH 289/831] Update UserApprovalHandler documentation. --- .../approval/UserApprovalHandler.java | 35 +++++++++++-------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/UserApprovalHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/UserApprovalHandler.java index 7a1131bfd..ab741bb2e 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/UserApprovalHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/UserApprovalHandler.java @@ -6,7 +6,8 @@ import org.springframework.security.oauth2.provider.AuthorizationRequest; /** - * Basic interface for determining whether a given client authentication request has been approved by the current user. + * Basic interface for determining whether a given client authentication request has been + * approved by the current user. * * @author Ryan Heaton * @author Dave Syer @@ -16,21 +17,24 @@ public interface UserApprovalHandler { /** *

    - * Tests whether the specified authorization request has been approved by the current user (if there is one). + * Tests whether the specified authorization request has been approved by the current + * user (if there is one). *

    * * @param authorizationRequest the authorization request. * @param userAuthentication the user authentication for the current user. * @return true if the request has been approved, false otherwise */ - boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication); + boolean isApproved(AuthorizationRequest authorizationRequest, + Authentication userAuthentication); /** *

    - * Provides a hook for allowing requests to be pre-approved (skipping the User Approval Page). Some implementations - * may allow users to store approval decisions so that they only have to approve a site once. This method is called - * in the AuthorizationEndpoint before sending the user to the Approval page. If this method sets - * oAuth2Request.approved to true, the Approval page will be skipped. + * Provides a hook for allowing requests to be pre-approved (skipping the User + * Approval Page). Some implementations may allow users to store approval decisions so + * that they only have to approve a site once. This method is called in the + * AuthorizationEndpoint before sending the user to the Approval page. If this method + * sets oAuth2Request.approved to true, the Approval page will be skipped. *

    * * @param authorizationRequest the authorization request. @@ -42,10 +46,12 @@ AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizationReque /** *

    - * Provides an opportunity to update the authorization request before it is checked for approval in cases where the - * incoming approval parameters contain richer information than just true/false (e.g. some scopes are approved, and - * others are rejected), implementations may need to be able to modify the {@link AuthorizationRequest} before a - * token is generated from it. + * Provides an opportunity to update the authorization request after the + * {@link AuthorizationRequest#setApprovalParameters(Map) approval parameters} are set + * but before it is checked for approval. Useful in cases where the incoming approval + * parameters contain richer information than just true/false (e.g. some scopes are + * approved, and others are rejected), implementations may need to be able to modify + * the {@link AuthorizationRequest} before a token is generated from it. *

    * * @param authorizationRequest the authorization request. @@ -56,9 +62,10 @@ AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizationReque Authentication userAuthentication); /** - * Generate a request for the authorization server to ask for the user's approval. Typically this will be rendered - * into a view (HTML etc.) to prompt for the approval, so it needs to contain information about the grant (scopes - * and client id for instance). + * Generate a request for the authorization server to ask for the user's approval. + * Typically this will be rendered into a view (HTML etc.) to prompt for the approval, + * so it needs to contain information about the grant (scopes and client id for + * instance). * * @param authorizationRequest the authorization request * @param userAuthentication the user authentication From f042fadb5f4c0713073893f6ce43894db1fe6a67 Mon Sep 17 00:00:00 2001 From: james Date: Mon, 7 Jul 2014 10:27:23 +0200 Subject: [PATCH 290/831] Provide a getter for autoApproveScopes Fixes gh-230 --- .../security/oauth2/provider/client/BaseClientDetails.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/BaseClientDetails.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/BaseClientDetails.java index f446218d7..c5688b909 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/BaseClientDetails.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/BaseClientDetails.java @@ -169,6 +169,12 @@ public boolean isAutoApprove(String scope) { return false; } + @org.codehaus.jackson.annotate.JsonIgnore + @com.fasterxml.jackson.annotation.JsonIgnore + public Set getAutoApproveScopes() { + return autoApproveScopes; + } + @org.codehaus.jackson.annotate.JsonIgnore @com.fasterxml.jackson.annotation.JsonIgnore public boolean isSecretRequired() { From 058429325097e24e0db5aa0cec0ac9bc3746c3d4 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 28 Aug 2014 09:41:11 +0100 Subject: [PATCH 291/831] Don't use session scope for RestTemplate The implementation of `` was fine, but the advice in `@EnableOAuth2Client` was to use session scope for the `RestTemplate` which is not a great idea since it is not serializable (and has properties that cannot be controlled). Better to put the `OAuth2ClientContext` in session scope. Fixes gh-235 --- .../web/configuration/EnableOAuth2Client.java | 16 ++----------- .../OAuth2ClientConfiguration.java | 20 ++++++++++++++++ .../main/java/client/ClientApplication.java | 23 +++++++------------ 3 files changed, 30 insertions(+), 29 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableOAuth2Client.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableOAuth2Client.java index 843d5efb3..30abe3155 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableOAuth2Client.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableOAuth2Client.java @@ -36,21 +36,9 @@ * @EnableOAuth2Client * public class RemoteResourceConfiguration { * - * @Resource - * @Qualifier("accessTokenRequest") - * private AccessTokenRequest accessTokenRequest; - * - * @Bean - * public OAuth2ProtectedResourceDetails remote() { - * AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails(); - * // set up resource details, OAuth2 URLs etc. - * return details; - * } - * * @Bean - * @Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES) - * public OAuth2RestOperations restTemplate() { - * return new OAuth2RestTemplate(remote(), new DefaultOAuth2ClientContext(accessTokenRequest)); + * public OAuth2RestOperations restTemplate(OAuth2ClientContext oauth2ClientContext) { + * return new OAuth2RestTemplate(remote(), oauth2ClientContext); * } * * } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/OAuth2ClientConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/OAuth2ClientConfiguration.java index f8450cbc0..a5815fd19 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/OAuth2ClientConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/OAuth2ClientConfiguration.java @@ -15,11 +15,16 @@ import java.util.Map; +import javax.annotation.Resource; + +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.ScopedProxyMode; +import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext; +import org.springframework.security.oauth2.client.OAuth2ClientContext; import org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter; import org.springframework.security.oauth2.client.token.AccessTokenRequest; import org.springframework.security.oauth2.client.token.DefaultAccessTokenRequest; @@ -47,4 +52,19 @@ protected AccessTokenRequest accessTokenRequest(@Value("#{request.parameterMap}" return request; } + @Configuration + protected static class OAuth2ClientContextConfiguration { + + @Resource + @Qualifier("accessTokenRequest") + private AccessTokenRequest accessTokenRequest; + + @Bean + @Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES) + public OAuth2ClientContext oauth2ClientContext() { + return new DefaultOAuth2ClientContext(accessTokenRequest); + } + + } + } diff --git a/tests/annotation/client/src/main/java/client/ClientApplication.java b/tests/annotation/client/src/main/java/client/ClientApplication.java index 7eceb2607..cd4e7d2ff 100644 --- a/tests/annotation/client/src/main/java/client/ClientApplication.java +++ b/tests/annotation/client/src/main/java/client/ClientApplication.java @@ -3,21 +3,16 @@ import java.util.List; import java.util.Map; -import javax.annotation.Resource; - -import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Scope; -import org.springframework.context.annotation.ScopedProxyMode; -import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext; +import org.springframework.security.oauth2.client.OAuth2ClientContext; import org.springframework.security.oauth2.client.OAuth2RestOperations; import org.springframework.security.oauth2.client.OAuth2RestTemplate; import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails; -import org.springframework.security.oauth2.client.token.AccessTokenRequest; import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client; import org.springframework.web.bind.annotation.RequestMapping; @@ -42,21 +37,19 @@ public static void main(String[] args) { @Value("${oauth.token:http://localhost:8080/oauth/token}") private String tokenUrl; - @Resource - @Qualifier("accessTokenRequest") - private AccessTokenRequest accessTokenRequest; - + @Autowired + private OAuth2RestOperations restTemplate; + @RequestMapping("/") public List> home() { @SuppressWarnings("unchecked") - List> result = restTemplate().getForObject(baseUrl + "/admin/beans", List.class); + List> result = restTemplate.getForObject(baseUrl + "/admin/beans", List.class); return result; } @Bean - @Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES) - public OAuth2RestOperations restTemplate() { - return new OAuth2RestTemplate(resource(), new DefaultOAuth2ClientContext(accessTokenRequest)); + public OAuth2RestOperations restTemplate(OAuth2ClientContext oauth2ClientContext) { + return new OAuth2RestTemplate(resource(), oauth2ClientContext); } @Bean From 81f10bc78ca8079de2c2daaffe979cdc824a185f Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 28 Aug 2014 10:01:36 +0100 Subject: [PATCH 292/831] Add test for AUD claim in DefaultAccessTokenConverter --- .../DefaultAccessTokenConverterTests.java | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverterTests.java diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverterTests.java new file mode 100644 index 000000000..3822be05f --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverterTests.java @@ -0,0 +1,61 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.springframework.security.oauth2.provider.token; + +import static org.junit.Assert.*; + +import java.util.Collections; +import java.util.Map; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.RequestTokenFactory; + +/** + * @author Dave Syer + * + */ +public class DefaultAccessTokenConverterTests { + + private DefaultAccessTokenConverter converter = new DefaultAccessTokenConverter(); + + private UsernamePasswordAuthenticationToken userAuthentication = new UsernamePasswordAuthenticationToken("foo", + "bar", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"))); + + private OAuth2Authentication authentication; + + @Before + public void init() { + OAuth2Request request = RequestTokenFactory.createOAuth2Request(null, "id", + AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_CLIENT"), true, Collections.singleton("read"), + Collections.singleton("resource"), null, null, null); + authentication = new OAuth2Authentication(request, userAuthentication); + } + + @Test + public void extractAuthentication() { + DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken("FOO"); + Map map = converter.convertAccessToken(token, authentication); + assertTrue(map.containsKey(AccessTokenConverter.AUD)); + OAuth2Authentication extracted = converter.extractAuthentication(map); + assertTrue(extracted.getOAuth2Request().getResourceIds().contains("resource")); + } + +} From e6266ef8556d39e83f18e6bbb0d66a2a220b17bc Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 28 Aug 2014 10:33:31 +0100 Subject: [PATCH 293/831] Fix NPE in test --- .../OAuth2ClientAuthenticationProcessingFilterTests.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilterTests.java index 1d6039e0f..54d840f2e 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilterTests.java @@ -27,6 +27,7 @@ import org.junit.Test; import org.mockito.Mockito; +import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.client.OAuth2RestOperations; import org.springframework.security.oauth2.client.http.AccessTokenRequiredException; @@ -57,7 +58,7 @@ public void testAuthentication() throws Exception { OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request("client", false, scopes); this.authentication = new OAuth2Authentication(storedOAuth2Request, null); Mockito.when(tokenServices.loadAuthentication("FOO")).thenReturn(authentication); - Authentication authentication = filter.attemptAuthentication(null, null); + Authentication authentication = filter.attemptAuthentication(new MockHttpServletRequest(), null); assertEquals(this.authentication, authentication); } From ea77e4ca4c2878689e65c4f85218de280ea0f52a Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 28 Aug 2014 11:01:28 +0100 Subject: [PATCH 294/831] Fix integration test with /server prefix --- .../main/java/sparklr/common/AbstractIntegrationTests.java | 2 ++ .../annotation/mappings/src/main/resources/application.yml | 7 +++++-- .../demo/ServletPathClientCredentialsProviderTests.java | 4 +++- 3 files changed, 10 insertions(+), 3 deletions(-) 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 2f68e61d8..2f90d4d21 100644 --- a/tests/annotation/common/src/main/java/sparklr/common/AbstractIntegrationTests.java +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractIntegrationTests.java @@ -85,7 +85,9 @@ public abstract class AbstractIntegrationTests { @Before public void init() { + String prefix = server.getServletPrefix(); http.setPort(port); + http.setPrefix(prefix); } @BeforeOAuth2Context diff --git a/tests/annotation/mappings/src/main/resources/application.yml b/tests/annotation/mappings/src/main/resources/application.yml index b7b8b2e53..cc1cf090c 100644 --- a/tests/annotation/mappings/src/main/resources/application.yml +++ b/tests/annotation/mappings/src/main/resources/application.yml @@ -6,10 +6,13 @@ management: security: user: password: password - +logging: + level: + org.springframework.security: DEBUG oauth: paths: token: /token authorize: /authorize confirm: /approve - check_token: /decode \ No newline at end of file + check_token: /decode + token_key: /key \ No newline at end of file diff --git a/tests/annotation/mappings/src/test/java/demo/ServletPathClientCredentialsProviderTests.java b/tests/annotation/mappings/src/test/java/demo/ServletPathClientCredentialsProviderTests.java index dd85f62d4..e5344a065 100644 --- a/tests/annotation/mappings/src/test/java/demo/ServletPathClientCredentialsProviderTests.java +++ b/tests/annotation/mappings/src/test/java/demo/ServletPathClientCredentialsProviderTests.java @@ -10,6 +10,7 @@ import org.springframework.boot.test.TestRestTemplate; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.test.annotation.DirtiesContext; import sparklr.common.AbstractClientCredentialsProviderTests; @@ -17,7 +18,8 @@ * @author Dave Syer */ @SpringApplicationConfiguration(classes=Application.class) -@IntegrationTest("server.servlet_path:/server") +@IntegrationTest({"server.servlet_path:/server", "server.port=0"}) +@DirtiesContext public class ServletPathClientCredentialsProviderTests extends AbstractClientCredentialsProviderTests { @Test From 766b2d5997e45bc61ecb66b06d18f967ec62be95 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 28 Aug 2014 11:14:06 +0100 Subject: [PATCH 295/831] Add client details check to OAuth2AuthenticationManager It's optional in the sense that you can inject your own ResoureServerTokenServices, but the @Configuration style now installs it by default. Fixes gh-185 --- .../ResourceServerSecurityConfigurer.java | 1 + .../oauth2/provider/ClientDetailsService.java | 4 +-- .../OAuth2AuthenticationManager.java | 31 +++++++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java index e32dc86e2..5516ff1d0 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java @@ -158,6 +158,7 @@ private AuthenticationManager oauthAuthenticationManager(HttpSecurity http) { } oauthAuthenticationManager.setResourceId(resourceId); oauthAuthenticationManager.setTokenServices(resourceTokenServices(http)); + oauthAuthenticationManager.setClientDetailsService(clientDetails()); return oauthAuthenticationManager; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientDetailsService.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientDetailsService.java index 76c6632ef..e08aa3540 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientDetailsService.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientDetailsService.java @@ -28,8 +28,8 @@ public interface ClientDetailsService { * Load a client by the client id. This method must not return null. * * @param clientId The client id. - * @return The client details. - * @throws ClientRegistrationException If the client account is locked, expired, disabled, or for any other reason. + * @return The client details (never null). + * @throws ClientRegistrationException If the client account is locked, expired, disabled, or invalid for any other reason. */ ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java index 268ff41e9..3d3730b0d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java @@ -13,6 +13,7 @@ package org.springframework.security.oauth2.provider.authentication; import java.util.Collection; +import java.util.Set; import org.springframework.beans.factory.InitializingBean; import org.springframework.security.authentication.AuthenticationManager; @@ -21,6 +22,9 @@ import org.springframework.security.oauth2.client.resource.OAuth2AccessDeniedException; import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.ClientRegistrationException; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices; import org.springframework.util.Assert; @@ -35,12 +39,18 @@ public class OAuth2AuthenticationManager implements AuthenticationManager, Initi private ResourceServerTokenServices tokenServices; + private ClientDetailsService clientDetailsService; + private String resourceId; public void setResourceId(String resourceId) { this.resourceId = resourceId; } + public void setClientDetailsService(ClientDetailsService clientDetailsService) { + this.clientDetailsService = clientDetailsService; + } + /** * @param tokenServices the tokenServices to set */ @@ -77,10 +87,31 @@ public Authentication authenticate(Authentication authentication) throws Authent throw new OAuth2AccessDeniedException("Invalid token does not contain resource id (" + resourceId + ")"); } + checkClientDetails(auth); + auth.setDetails(authentication.getDetails()); auth.setAuthenticated(true); return auth; } + private void checkClientDetails(OAuth2Authentication auth) { + if (clientDetailsService != null) { + ClientDetails client; + try { + client = clientDetailsService.loadClientByClientId(auth.getOAuth2Request().getClientId()); + } + catch (ClientRegistrationException e) { + throw new OAuth2AccessDeniedException("Invalid token contains invalid client id"); + } + Set allowed = client.getScope(); + for (String scope : auth.getOAuth2Request().getScope()) { + if (!allowed.contains(scope)) { + throw new OAuth2AccessDeniedException("Invalid token contains disallowed scope (" + scope + + ") for this client"); + } + } + } + } + } From 9f618402c10f49f0e7a14e63ecbb1ec8e80dbccc Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 28 Aug 2014 11:29:04 +0100 Subject: [PATCH 296/831] Fix grammar in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3e9b33be7..ce47dabcf 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ request but before a merge. * Use the Spring Framework code format conventions. Import `eclipse-code-formatter.xml` from the root of the project if you are using Eclipse. If using IntelliJ, copy `spring-intellij-code-style.xml` to `~/.IntelliJIdea*/config/codestyles` and select spring-intellij-code-style from Settings -> Code Styles. -* Make sure all new .java files to have a simple Javadoc class comment with at least an @author tag identifying you, and +* Make sure all new .java files have a simple Javadoc class comment with at least an @author tag identifying you, and preferably at least a paragraph on what the class is for. * Add the ASF license header comment to all new .java files (copy from existing files in the project) * Add yourself as an @author to the .java files that you modify substantially (more than cosmetic changes). From 4e6db697ec68f7d345dccd1de18cda6006345c05 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 28 Aug 2014 11:37:02 +0100 Subject: [PATCH 297/831] Remove dead code branch in InMemoryTokenStore The InMemoryTokenStore has comments that say "don't remove the refresh token" and yet it was removing something (an access token it turns out so it's a no-op). This change removes the dead code and also fixes a typo. Fixes gh-240 --- .../token/store/InMemoryTokenStore.java | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/InMemoryTokenStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/InMemoryTokenStore.java index b70767fa0..ae287f6e3 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/InMemoryTokenStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/InMemoryTokenStore.java @@ -45,7 +45,7 @@ public class InMemoryTokenStore implements TokenStore { private final ConcurrentHashMap refreshTokenAuthenticationStore = new ConcurrentHashMap(); - private final ConcurrentHashMap refreshTokenToAcessTokenStore = new ConcurrentHashMap(); + private final ConcurrentHashMap refreshTokenToAccessTokenStore = new ConcurrentHashMap(); private final DelayQueue expiryQueue = new DelayQueue(); @@ -86,7 +86,7 @@ public void clear() { accessTokenToRefreshTokenStore.clear(); authenticationStore.clear(); refreshTokenAuthenticationStore.clear(); - refreshTokenToAcessTokenStore.clear(); + refreshTokenToAccessTokenStore.clear(); expiryQueue.clear(); } @@ -104,7 +104,7 @@ public int getAccessTokenCount() { } public int getRefreshTokenCount() { - Assert.state(refreshTokenStore.size() == refreshTokenToAcessTokenStore.size(), + Assert.state(refreshTokenStore.size() == refreshTokenToAccessTokenStore.size(), "Inconsistent refresh token store state"); return accessTokenStore.size(); } @@ -160,7 +160,7 @@ public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authe this.expiryQueue.put(expiry); } if (token.getRefreshToken() != null && token.getRefreshToken().getValue() != null) { - this.refreshTokenToAcessTokenStore.put(token.getRefreshToken().getValue(), token.getValue()); + this.refreshTokenToAccessTokenStore.put(token.getRefreshToken().getValue(), token.getValue()); this.accessTokenToRefreshTokenStore.put(token.getValue(), token.getRefreshToken().getValue()); } } @@ -197,11 +197,8 @@ public OAuth2AccessToken readAccessToken(String tokenValue) { public void removeAccessToken(String tokenValue) { OAuth2AccessToken removed = this.accessTokenStore.remove(tokenValue); - String refresh = this.accessTokenToRefreshTokenStore.remove(tokenValue); - if (refresh != null) { - // Don't remove the refresh token itself - it's up to the caller to do that - this.refreshTokenToAcessTokenStore.remove(tokenValue); - } + this.accessTokenToRefreshTokenStore.remove(tokenValue); + // Don't remove the refresh token - it's up to the caller to do that OAuth2Authentication authentication = this.authenticationStore.remove(tokenValue); if (authentication != null) { this.authenticationToAccessTokenStore.remove(authenticationKeyGenerator.extractKey(authentication)); @@ -235,7 +232,7 @@ public void removeRefreshToken(OAuth2RefreshToken refreshToken) { public void removeRefreshToken(String tokenValue) { this.refreshTokenStore.remove(tokenValue); this.refreshTokenAuthenticationStore.remove(tokenValue); - this.refreshTokenToAcessTokenStore.remove(tokenValue); + this.refreshTokenToAccessTokenStore.remove(tokenValue); } public void removeAccessTokenUsingRefreshToken(OAuth2RefreshToken refreshToken) { @@ -243,7 +240,7 @@ public void removeAccessTokenUsingRefreshToken(OAuth2RefreshToken refreshToken) } private void removeAccessTokenUsingRefreshToken(String refreshToken) { - String accessToken = this.refreshTokenToAcessTokenStore.remove(refreshToken); + String accessToken = this.refreshTokenToAccessTokenStore.remove(refreshToken); if (accessToken != null) { removeAccessToken(accessToken); } From effa7e1eacca5cfb89064e4ed7f430d71307bea4 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 28 Aug 2014 11:41:22 +0100 Subject: [PATCH 298/831] Fix index out of bounds for key-value with no value Fixes gh-249 --- .../config/annotation/builders/ClientDetailsServiceBuilder.java | 2 +- .../annotation/AuthorizationServerConfigurationTests.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java index ac0df5230..ead812ea7 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java @@ -203,7 +203,7 @@ public ClientBuilder additionalInformation(String... pairs) { } int index = pair.indexOf(separator); String key = pair.substring(0, index > 0 ? index : pair.length()); - String value = index > 0 ? null : pair.substring(index); + String value = index > 0 ? pair.substring(index) : null; this.additionalInformation.put(key, (Object) value); } return this; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java index 346fd4935..d5e1701f3 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java @@ -147,7 +147,7 @@ public void configure(ClientDetailsServiceConfigurer clients) throws Exception { .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") .scopes("read", "write", "trust") .accessTokenValiditySeconds(60) - .additionalInformation("foo:bar", "spam:bucket"); + .additionalInformation("foo:bar", "spam:bucket", "crap"); // @formatter:on } From 45b51c652168e08ad35f5ed3adef1bd90538943e Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 28 Aug 2014 11:46:41 +0100 Subject: [PATCH 299/831] Upgrade release plugin --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 40013db3f..81f094912 100644 --- a/pom.xml +++ b/pom.xml @@ -249,7 +249,7 @@ org.apache.maven.plugins maven-release-plugin - 2.3 + 2.5 org.apache.maven.plugins From 5eddb76b671db3051a715523c050526f275207ab Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 28 Aug 2014 11:53:45 +0100 Subject: [PATCH 300/831] [maven-release-plugin] prepare release 2.0.3.RELEASE --- pom.xml | 4 ++-- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- tests/annotation/approval/pom.xml | 2 +- tests/annotation/client/pom.xml | 2 +- tests/annotation/common/pom.xml | 2 +- tests/annotation/form/pom.xml | 2 +- tests/annotation/jdbc/pom.xml | 2 +- tests/annotation/jwt/pom.xml | 2 +- tests/annotation/mappings/pom.xml | 2 +- tests/annotation/multi/pom.xml | 2 +- tests/annotation/pom.xml | 8 ++++++-- tests/annotation/resource/pom.xml | 2 +- tests/annotation/vanilla/pom.xml | 2 +- tests/pom.xml | 2 +- tests/xml/approval/pom.xml | 2 +- tests/xml/client/pom.xml | 2 +- tests/xml/common/pom.xml | 2 +- tests/xml/form/pom.xml | 2 +- tests/xml/jdbc/pom.xml | 2 +- tests/xml/jwt/pom.xml | 2 +- tests/xml/mappings/pom.xml | 2 +- tests/xml/pom.xml | 8 ++++++-- tests/xml/vanilla/pom.xml | 2 +- 29 files changed, 40 insertions(+), 32 deletions(-) diff --git a/pom.xml b/pom.xml index 81f094912..8f1435641 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.3.BUILD-SNAPSHOT + 2.0.3.RELEASE http://static.springframework.org/spring-security/oauth @@ -26,7 +26,7 @@ http://github.com/SpringSource/spring-security-oauth scm:git:git://github.com/SpringSource/spring-security-oauth.git scm:git:ssh://git@github.com/SpringSource/spring-security-oauth.git - HEAD + 2.0.3.RELEASE JIRA diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index 5aaf4e074..1c33a505b 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.3.BUILD-SNAPSHOT + 2.0.3.RELEASE ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index 2436e03b9..f1ec4a2a9 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.3.BUILD-SNAPSHOT + 2.0.3.RELEASE ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 652bd4424..3f364a29d 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.3.BUILD-SNAPSHOT + 2.0.3.RELEASE ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index f109dd729..0f32bb6b5 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.3.BUILD-SNAPSHOT + 2.0.3.RELEASE ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index 53fd71e85..84addb14e 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.3.BUILD-SNAPSHOT + 2.0.3.RELEASE spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index c38f0e7bb..e3ef9f8e5 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.3.BUILD-SNAPSHOT + 2.0.3.RELEASE spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 616885aea..29c0ee402 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.3.BUILD-SNAPSHOT + 2.0.3.RELEASE spring-security-oauth2 diff --git a/tests/annotation/approval/pom.xml b/tests/annotation/approval/pom.xml index b1f4eceef..f444bb6ad 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.3.BUILD-SNAPSHOT + 2.0.3.RELEASE diff --git a/tests/annotation/client/pom.xml b/tests/annotation/client/pom.xml index cf2b1255d..62e578fda 100644 --- a/tests/annotation/client/pom.xml +++ b/tests/annotation/client/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.0.3.BUILD-SNAPSHOT + 2.0.3.RELEASE diff --git a/tests/annotation/common/pom.xml b/tests/annotation/common/pom.xml index 90cdbc051..e8ebd3a71 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.3.BUILD-SNAPSHOT + 2.0.3.RELEASE diff --git a/tests/annotation/form/pom.xml b/tests/annotation/form/pom.xml index 83a161a51..cdc277311 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.3.BUILD-SNAPSHOT + 2.0.3.RELEASE diff --git a/tests/annotation/jdbc/pom.xml b/tests/annotation/jdbc/pom.xml index b467bb083..b272d293d 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.3.BUILD-SNAPSHOT + 2.0.3.RELEASE diff --git a/tests/annotation/jwt/pom.xml b/tests/annotation/jwt/pom.xml index af8cb1bc3..f795a91c4 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.3.BUILD-SNAPSHOT + 2.0.3.RELEASE diff --git a/tests/annotation/mappings/pom.xml b/tests/annotation/mappings/pom.xml index db5246d9c..81fbf7775 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.3.BUILD-SNAPSHOT + 2.0.3.RELEASE diff --git a/tests/annotation/multi/pom.xml b/tests/annotation/multi/pom.xml index dce5cd5b4..024eeb0a8 100644 --- a/tests/annotation/multi/pom.xml +++ b/tests/annotation/multi/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.0.3.BUILD-SNAPSHOT + 2.0.3.RELEASE diff --git a/tests/annotation/pom.xml b/tests/annotation/pom.xml index 95df02f61..5a119fd58 100644 --- a/tests/annotation/pom.xml +++ b/tests/annotation/pom.xml @@ -4,7 +4,7 @@ org.demo spring-oauth2-tests-parent - 2.0.3.BUILD-SNAPSHOT + 2.0.3.RELEASE pom @@ -34,7 +34,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.0.3.BUILD-SNAPSHOT + 2.0.3.RELEASE jackson-mapper-asl @@ -129,4 +129,8 @@ + + + 2.0.3.RELEASE + diff --git a/tests/annotation/resource/pom.xml b/tests/annotation/resource/pom.xml index d369d92dc..805ef5065 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.3.BUILD-SNAPSHOT + 2.0.3.RELEASE diff --git a/tests/annotation/vanilla/pom.xml b/tests/annotation/vanilla/pom.xml index bcc9e0e40..0906b8d6c 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.3.BUILD-SNAPSHOT + 2.0.3.RELEASE diff --git a/tests/pom.xml b/tests/pom.xml index 22c71cf71..46ebbc8dc 100644 --- a/tests/pom.xml +++ b/tests/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.3.BUILD-SNAPSHOT + 2.0.3.RELEASE spring-security-oauth-tests diff --git a/tests/xml/approval/pom.xml b/tests/xml/approval/pom.xml index 38be519c2..49a6978a0 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.3.BUILD-SNAPSHOT + 2.0.3.RELEASE diff --git a/tests/xml/client/pom.xml b/tests/xml/client/pom.xml index 3487371b9..1a152c68d 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.3.BUILD-SNAPSHOT + 2.0.3.RELEASE diff --git a/tests/xml/common/pom.xml b/tests/xml/common/pom.xml index afc5be7c8..ff04df194 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.3.BUILD-SNAPSHOT + 2.0.3.RELEASE diff --git a/tests/xml/form/pom.xml b/tests/xml/form/pom.xml index b54641236..a5d84dd83 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.3.BUILD-SNAPSHOT + 2.0.3.RELEASE diff --git a/tests/xml/jdbc/pom.xml b/tests/xml/jdbc/pom.xml index ec8fc8c87..4e7b25d9d 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.3.BUILD-SNAPSHOT + 2.0.3.RELEASE diff --git a/tests/xml/jwt/pom.xml b/tests/xml/jwt/pom.xml index f81eead5e..785dcca9f 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.3.BUILD-SNAPSHOT + 2.0.3.RELEASE diff --git a/tests/xml/mappings/pom.xml b/tests/xml/mappings/pom.xml index fb0ed638e..6442e42a2 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.3.BUILD-SNAPSHOT + 2.0.3.RELEASE diff --git a/tests/xml/pom.xml b/tests/xml/pom.xml index 7b9ea1e75..341319f4b 100644 --- a/tests/xml/pom.xml +++ b/tests/xml/pom.xml @@ -4,7 +4,7 @@ org.demo spring-oauth2-tests-xml-parent - 2.0.3.BUILD-SNAPSHOT + 2.0.3.RELEASE pom @@ -32,7 +32,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.0.3.BUILD-SNAPSHOT + 2.0.3.RELEASE jackson-mapper-asl @@ -127,4 +127,8 @@ + + + 2.0.3.RELEASE + diff --git a/tests/xml/vanilla/pom.xml b/tests/xml/vanilla/pom.xml index 4b93f2f1c..ab324c0ea 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.3.BUILD-SNAPSHOT + 2.0.3.RELEASE From 691ffb197b25bd1ef93621f541fd87462557e1a5 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 28 Aug 2014 11:57:52 +0100 Subject: [PATCH 301/831] Remove references to wrong snapshots --- pom.xml | 2 +- spring-security-oauth2/pom.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 8f1435641..cc6f7f00b 100644 --- a/pom.xml +++ b/pom.xml @@ -67,7 +67,7 @@ spring4 - 4.0.2.BUILD-SNAPSHOT + 4.1.0.BUILD-SNAPSHOT diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 29c0ee402..48ffff4e1 100644 --- a/spring-security-oauth2/pom.xml +++ b/spring-security-oauth2/pom.xml @@ -15,7 +15,7 @@ 1.9.13 2.3.2 - 1.0.2.BUILD-SNAPSHOT + 1.0.2.RELEASE @@ -127,7 +127,7 @@ org.springframework.security spring-security-jwt - 1.0.2.RELEASE + ${spring.security.jwt.version} true From 79ff91f2dc02098f2b1c3bda1781d79c0ffea8a3 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 28 Aug 2014 11:53:52 +0100 Subject: [PATCH 302/831] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- tests/annotation/approval/pom.xml | 2 +- tests/annotation/client/pom.xml | 2 +- tests/annotation/common/pom.xml | 2 +- tests/annotation/form/pom.xml | 2 +- tests/annotation/jdbc/pom.xml | 2 +- tests/annotation/jwt/pom.xml | 2 +- tests/annotation/mappings/pom.xml | 2 +- tests/annotation/multi/pom.xml | 2 +- tests/annotation/pom.xml | 8 ++------ tests/annotation/resource/pom.xml | 2 +- tests/annotation/vanilla/pom.xml | 2 +- tests/pom.xml | 2 +- tests/xml/approval/pom.xml | 2 +- tests/xml/client/pom.xml | 2 +- tests/xml/common/pom.xml | 2 +- tests/xml/form/pom.xml | 2 +- tests/xml/jdbc/pom.xml | 2 +- tests/xml/jwt/pom.xml | 2 +- tests/xml/mappings/pom.xml | 2 +- tests/xml/pom.xml | 8 ++------ tests/xml/vanilla/pom.xml | 2 +- 29 files changed, 32 insertions(+), 40 deletions(-) diff --git a/pom.xml b/pom.xml index cc6f7f00b..e512d847b 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.3.RELEASE + 2.0.4.BUILD-SNAPSHOT http://static.springframework.org/spring-security/oauth @@ -26,7 +26,7 @@ http://github.com/SpringSource/spring-security-oauth scm:git:git://github.com/SpringSource/spring-security-oauth.git scm:git:ssh://git@github.com/SpringSource/spring-security-oauth.git - 2.0.3.RELEASE + HEAD JIRA diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index 1c33a505b..950ab16c6 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.3.RELEASE + 2.0.4.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index f1ec4a2a9..ea1795ca3 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.3.RELEASE + 2.0.4.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 3f364a29d..958cd950e 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.3.RELEASE + 2.0.4.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 0f32bb6b5..da80d2cf2 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.3.RELEASE + 2.0.4.BUILD-SNAPSHOT ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index 84addb14e..f7166f7ed 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.3.RELEASE + 2.0.4.BUILD-SNAPSHOT spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index e3ef9f8e5..b2e692135 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.3.RELEASE + 2.0.4.BUILD-SNAPSHOT spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 48ffff4e1..2ae42f58b 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.3.RELEASE + 2.0.4.BUILD-SNAPSHOT spring-security-oauth2 diff --git a/tests/annotation/approval/pom.xml b/tests/annotation/approval/pom.xml index f444bb6ad..547f6c88a 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.3.RELEASE + 2.0.4.BUILD-SNAPSHOT diff --git a/tests/annotation/client/pom.xml b/tests/annotation/client/pom.xml index 62e578fda..ef7722f7a 100644 --- a/tests/annotation/client/pom.xml +++ b/tests/annotation/client/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.0.3.RELEASE + 2.0.4.BUILD-SNAPSHOT diff --git a/tests/annotation/common/pom.xml b/tests/annotation/common/pom.xml index e8ebd3a71..8d8fc6c0a 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.3.RELEASE + 2.0.4.BUILD-SNAPSHOT diff --git a/tests/annotation/form/pom.xml b/tests/annotation/form/pom.xml index cdc277311..8769172e2 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.3.RELEASE + 2.0.4.BUILD-SNAPSHOT diff --git a/tests/annotation/jdbc/pom.xml b/tests/annotation/jdbc/pom.xml index b272d293d..c633107f6 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.3.RELEASE + 2.0.4.BUILD-SNAPSHOT diff --git a/tests/annotation/jwt/pom.xml b/tests/annotation/jwt/pom.xml index f795a91c4..8c37bc711 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.3.RELEASE + 2.0.4.BUILD-SNAPSHOT diff --git a/tests/annotation/mappings/pom.xml b/tests/annotation/mappings/pom.xml index 81fbf7775..809cf006d 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.3.RELEASE + 2.0.4.BUILD-SNAPSHOT diff --git a/tests/annotation/multi/pom.xml b/tests/annotation/multi/pom.xml index 024eeb0a8..6c96781f5 100644 --- a/tests/annotation/multi/pom.xml +++ b/tests/annotation/multi/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.0.3.RELEASE + 2.0.4.BUILD-SNAPSHOT diff --git a/tests/annotation/pom.xml b/tests/annotation/pom.xml index 5a119fd58..75ece76b5 100644 --- a/tests/annotation/pom.xml +++ b/tests/annotation/pom.xml @@ -4,7 +4,7 @@ org.demo spring-oauth2-tests-parent - 2.0.3.RELEASE + 2.0.4.BUILD-SNAPSHOT pom @@ -34,7 +34,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.0.3.RELEASE + 2.0.4.BUILD-SNAPSHOT jackson-mapper-asl @@ -129,8 +129,4 @@ - - - 2.0.3.RELEASE - diff --git a/tests/annotation/resource/pom.xml b/tests/annotation/resource/pom.xml index 805ef5065..b1ab11c0c 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.3.RELEASE + 2.0.4.BUILD-SNAPSHOT diff --git a/tests/annotation/vanilla/pom.xml b/tests/annotation/vanilla/pom.xml index 0906b8d6c..2c2491364 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.3.RELEASE + 2.0.4.BUILD-SNAPSHOT diff --git a/tests/pom.xml b/tests/pom.xml index 46ebbc8dc..6dbb6a4e9 100644 --- a/tests/pom.xml +++ b/tests/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.3.RELEASE + 2.0.4.BUILD-SNAPSHOT spring-security-oauth-tests diff --git a/tests/xml/approval/pom.xml b/tests/xml/approval/pom.xml index 49a6978a0..00e1bbab4 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.3.RELEASE + 2.0.4.BUILD-SNAPSHOT diff --git a/tests/xml/client/pom.xml b/tests/xml/client/pom.xml index 1a152c68d..c4d507e9a 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.3.RELEASE + 2.0.4.BUILD-SNAPSHOT diff --git a/tests/xml/common/pom.xml b/tests/xml/common/pom.xml index ff04df194..ab3a1ea4e 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.3.RELEASE + 2.0.4.BUILD-SNAPSHOT diff --git a/tests/xml/form/pom.xml b/tests/xml/form/pom.xml index a5d84dd83..eb8496b0c 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.3.RELEASE + 2.0.4.BUILD-SNAPSHOT diff --git a/tests/xml/jdbc/pom.xml b/tests/xml/jdbc/pom.xml index 4e7b25d9d..5419a64ff 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.3.RELEASE + 2.0.4.BUILD-SNAPSHOT diff --git a/tests/xml/jwt/pom.xml b/tests/xml/jwt/pom.xml index 785dcca9f..19423d0be 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.3.RELEASE + 2.0.4.BUILD-SNAPSHOT diff --git a/tests/xml/mappings/pom.xml b/tests/xml/mappings/pom.xml index 6442e42a2..27bd0a26e 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.3.RELEASE + 2.0.4.BUILD-SNAPSHOT diff --git a/tests/xml/pom.xml b/tests/xml/pom.xml index 341319f4b..eabae689b 100644 --- a/tests/xml/pom.xml +++ b/tests/xml/pom.xml @@ -4,7 +4,7 @@ org.demo spring-oauth2-tests-xml-parent - 2.0.3.RELEASE + 2.0.4.BUILD-SNAPSHOT pom @@ -32,7 +32,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.0.3.RELEASE + 2.0.4.BUILD-SNAPSHOT jackson-mapper-asl @@ -127,8 +127,4 @@ - - - 2.0.3.RELEASE - diff --git a/tests/xml/vanilla/pom.xml b/tests/xml/vanilla/pom.xml index ab324c0ea..bbd3336ff 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.3.RELEASE + 2.0.4.BUILD-SNAPSHOT From 190fbbb2b8de24c9c5a2b5aa802738738c7a9992 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 11 Sep 2014 07:22:42 -0500 Subject: [PATCH 303/831] Correct sample snippet for @EnableOAuth2Client --- docs/oauth2.md | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/docs/oauth2.md b/docs/oauth2.md index f5b71b15b..9f71c0696 100644 --- a/docs/oauth2.md +++ b/docs/oauth2.md @@ -160,22 +160,20 @@ The `AccessTokenRequest` can be used in an `OAuth2RestTemplate` like this: ``` -@Resource -@Qualifier("accessTokenRequest") -private AccessTokenRequest accessTokenRequest; +@Autowired +private OAuth2ClientContext oauth2Context; @Bean -@Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES) public OAuth2RestTemplate sparklrRestTemplate() { - return new OAuth2RestTemplate(sparklr(), new DefaultOAuth2ClientContext(accessTokenRequest)); + return new OAuth2RestTemplate(sparklr(), oauth2Context); } ``` -The rest template is placed in session scope to keep the state for -different users separate. Without that you would have to manage the -equivalent data structure yourself on the server, mapping incoming -requests to users, and associating each user with a separate instance -of the `OAuth2ClientContext`. +The OAuth2ClientContext is placed (for you) in session scope to keep +the state for different users separate. Without that you would have to +manage the equivalent data structure yourself on the server, mapping +incoming requests to users, and associating each user with a separate +instance of the `OAuth2ClientContext`. In XML there is a `` element with an `id` attribute - this is the bean id for a servlet `Filter` that must be mapped as in the `@Configuration` case to a `DelegatingFilterProxy` (with the same name). From 2f3dece94df5fa16e341482fe9351098e040383c Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 18 Sep 2014 11:37:50 +0100 Subject: [PATCH 304/831] Add setter for SQL statememt (fixes gh-254) --- .../security/oauth2/provider/approval/JdbcApprovalStore.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/JdbcApprovalStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/JdbcApprovalStore.java index eedac92d9..e6f0e128a 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/JdbcApprovalStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/JdbcApprovalStore.java @@ -106,6 +106,10 @@ public void setDeleteApprovalStatment(String deleteApprovalStatment) { public void setExpireApprovalStatement(String expireApprovalStatement) { this.expireApprovalStatement = expireApprovalStatement; } + + public void setRefreshApprovalStatement(String refreshApprovalStatement) { + this.refreshApprovalStatement = refreshApprovalStatement; + } @Override public boolean addApprovals(final Collection approvals) { From 371aad08ac93efa292d825d0e1e7604eae77f3f5 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 18 Sep 2014 11:38:51 +0100 Subject: [PATCH 305/831] Ensure token is stored in ClientTokenServices if provided (fixes gh-259) --- ...Auth2ClientAuthenticationProcessingFilter.java | 9 +++++++++ .../client/token/AccessTokenProviderChain.java | 2 +- ...ClientAuthenticationProcessingFilterTests.java | 13 +++++++++++++ tests/annotation/approval/.gitignore | 8 -------- tests/annotation/client/.gitignore | 14 -------------- tests/annotation/common/.gitignore | 13 ------------- tests/annotation/form/.gitignore | 8 -------- tests/annotation/jdbc/.gitignore | 15 --------------- tests/annotation/jwt/.gitignore | 9 --------- tests/annotation/mappings/.gitignore | 10 ---------- tests/annotation/multi/.gitignore | 10 ---------- tests/annotation/resource/.gitignore | 11 ----------- tests/annotation/vanilla/.gitignore | 9 --------- 13 files changed, 23 insertions(+), 108 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilter.java index 4c1dbac5f..95a39a805 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilter.java @@ -18,6 +18,7 @@ import java.io.IOException; +import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -101,6 +102,14 @@ public Authentication attemptAuthentication(HttpServletRequest request, HttpServ } } + + @Override + protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, + FilterChain chain, Authentication authResult) throws IOException, ServletException { + super.successfulAuthentication(request, response, chain, authResult); + // Nearly a no-op, but if there is a ClientTokenServices then the token will now be stored + restTemplate.getAccessToken(); + } @Override protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/AccessTokenProviderChain.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/AccessTokenProviderChain.java index 5597f0c36..0349b2aff 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/AccessTokenProviderChain.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/AccessTokenProviderChain.java @@ -122,7 +122,7 @@ public OAuth2AccessToken obtainAccessToken(OAuth2ProtectedResourceDetails resour } } - if (clientTokenServices != null) { + if (clientTokenServices != null && auth != null && auth.isAuthenticated()) { clientTokenServices.saveAccessToken(resource, auth, accessToken); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilterTests.java index 54d840f2e..ea99d2daf 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilterTests.java @@ -28,6 +28,7 @@ import org.junit.Test; import org.mockito.Mockito; import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.client.OAuth2RestOperations; import org.springframework.security.oauth2.client.http.AccessTokenRequiredException; @@ -60,6 +61,18 @@ public void testAuthentication() throws Exception { Mockito.when(tokenServices.loadAuthentication("FOO")).thenReturn(authentication); Authentication authentication = filter.attemptAuthentication(new MockHttpServletRequest(), null); assertEquals(this.authentication, authentication); + Mockito.verify(restTemplate, Mockito.times(1)).getAccessToken(); + } + + @Test + public void testSuccessfulAuthentication() throws Exception { + filter.setRestTemplate(restTemplate); + Set scopes = new HashSet(); + scopes.addAll(Arrays.asList("read", "write")); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request("client", false, scopes); + this.authentication = new OAuth2Authentication(storedOAuth2Request, null); + filter.successfulAuthentication(new MockHttpServletRequest(), new MockHttpServletResponse(), null, authentication); + Mockito.verify(restTemplate, Mockito.times(1)).getAccessToken(); } @Test diff --git a/tests/annotation/approval/.gitignore b/tests/annotation/approval/.gitignore index 7b791414a..1dd333108 100644 --- a/tests/annotation/approval/.gitignore +++ b/tests/annotation/approval/.gitignore @@ -1,10 +1,2 @@ /target/ /target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ diff --git a/tests/annotation/client/.gitignore b/tests/annotation/client/.gitignore index 963051b11..1dd333108 100644 --- a/tests/annotation/client/.gitignore +++ b/tests/annotation/client/.gitignore @@ -1,16 +1,2 @@ /target/ /target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ diff --git a/tests/annotation/common/.gitignore b/tests/annotation/common/.gitignore index 8e1fb9a6b..b83d22266 100644 --- a/tests/annotation/common/.gitignore +++ b/tests/annotation/common/.gitignore @@ -1,14 +1 @@ /target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ diff --git a/tests/annotation/form/.gitignore b/tests/annotation/form/.gitignore index 8352667a7..b83d22266 100644 --- a/tests/annotation/form/.gitignore +++ b/tests/annotation/form/.gitignore @@ -1,9 +1 @@ /target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ diff --git a/tests/annotation/jdbc/.gitignore b/tests/annotation/jdbc/.gitignore index 6b1fa3918..1dd333108 100644 --- a/tests/annotation/jdbc/.gitignore +++ b/tests/annotation/jdbc/.gitignore @@ -1,17 +1,2 @@ /target/ /target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ diff --git a/tests/annotation/jwt/.gitignore b/tests/annotation/jwt/.gitignore index 7b791414a..b83d22266 100644 --- a/tests/annotation/jwt/.gitignore +++ b/tests/annotation/jwt/.gitignore @@ -1,10 +1 @@ /target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ diff --git a/tests/annotation/mappings/.gitignore b/tests/annotation/mappings/.gitignore index 32362a30c..b83d22266 100644 --- a/tests/annotation/mappings/.gitignore +++ b/tests/annotation/mappings/.gitignore @@ -1,11 +1 @@ /target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ diff --git a/tests/annotation/multi/.gitignore b/tests/annotation/multi/.gitignore index 2a7c772f3..1dd333108 100644 --- a/tests/annotation/multi/.gitignore +++ b/tests/annotation/multi/.gitignore @@ -1,12 +1,2 @@ /target/ /target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ diff --git a/tests/annotation/resource/.gitignore b/tests/annotation/resource/.gitignore index 2a7c772f3..b83d22266 100644 --- a/tests/annotation/resource/.gitignore +++ b/tests/annotation/resource/.gitignore @@ -1,12 +1 @@ /target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ diff --git a/tests/annotation/vanilla/.gitignore b/tests/annotation/vanilla/.gitignore index 7b791414a..b83d22266 100644 --- a/tests/annotation/vanilla/.gitignore +++ b/tests/annotation/vanilla/.gitignore @@ -1,10 +1 @@ /target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ -/target/ From bfdf8837e7a51477c98a205c3fb9c27485743cd0 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 18 Sep 2014 13:04:05 +0100 Subject: [PATCH 306/831] Add getGrantType() to OAuth2Request The OAuth2Request (and hence OAuth2Authentication) can now be queried explicitly to find the grant type for the associated token. If the token is being refreshed the grant type in the OAuth2Request presented to the TokenEnhancer is the original grant type, not "refresh_token". Fixes gh-199, fixes gh-218 --- .../oauth2/provider/OAuth2Request.java | 19 ++++++ .../oauth2/provider/TokenRequest.java | 4 +- .../provider/AuthorizationRequestTests.java | 20 +++---- .../oauth2/provider/OAuth2RequestTests.java | 60 +++++++++++++++++++ ...faultAuthorizationRequestFactoryTests.java | 22 ++++++- tests/annotation/approval/.gitignore | 2 + tests/annotation/client/.gitignore | 1 + tests/annotation/common/.gitignore | 3 + tests/annotation/form/.gitignore | 1 + tests/annotation/jdbc/.gitignore | 2 + tests/annotation/jwt/.gitignore | 3 + tests/annotation/mappings/.gitignore | 1 + tests/annotation/multi/.gitignore | 2 + tests/annotation/resource/.gitignore | 2 + tests/annotation/vanilla/.gitignore | 1 + 15 files changed, 131 insertions(+), 12 deletions(-) create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/OAuth2RequestTests.java diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java index 7a4515696..fd6eff9c7 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java @@ -8,6 +8,7 @@ import java.util.Set; import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.oauth2.common.util.OAuth2Utils; /** * Represents a stored authorization or token request. Used as part of the OAuth2Authentication object to store a @@ -141,6 +142,24 @@ public OAuth2Request narrowScope(Set scope) { redirectUri, responseTypes, extensions); } + /** + * Tries to discover the grant type requested for the token associated with this request. + * + * @return the grant type if known, or null otherwise + */ + public String getGrantType() { + if (getRequestParameters().containsKey(OAuth2Utils.GRANT_TYPE)) { + return getRequestParameters().get(OAuth2Utils.GRANT_TYPE); + } + if (getRequestParameters().containsKey(OAuth2Utils.RESPONSE_TYPE)) { + String response = getRequestParameters().get(OAuth2Utils.RESPONSE_TYPE); + if (response.contains("token")) { + return "implicit"; + } + } + return null; + } + @Override public int hashCode() { final int prime = 31; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java index f2a9e96ba..687634219 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java @@ -89,11 +89,13 @@ public void setRequestParameters(Map requestParameters) { } public OAuth2Request createOAuth2Request(ClientDetails client) { - // Remove password if present to prevent leaks Map requestParameters = getRequestParameters(); HashMap modifiable = new HashMap( requestParameters); + // Remove password if present to prevent leaks modifiable.remove("password"); + // Add grant type so it can be retrieved from OAuth2Request + modifiable.put("grant_type", grantType); return new OAuth2Request(modifiable, client.getClientId(), client.getAuthorities(), true, this.getScope(), null, null, null, null); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/AuthorizationRequestTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/AuthorizationRequestTests.java index 638f933c9..dd1363216 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/AuthorizationRequestTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/AuthorizationRequestTests.java @@ -50,16 +50,6 @@ public void prepare() { parameters.put("redirect_uri", "http://www.callistaenterprise.se/"); } - private AuthorizationRequest createFromParameters(Map authorizationParameters) { - AuthorizationRequest request = new AuthorizationRequest(authorizationParameters, Collections. emptyMap(), - authorizationParameters.get(OAuth2Utils.CLIENT_ID), - OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Utils.SCOPE)), null, - null, false, authorizationParameters.get(OAuth2Utils.STATE), - authorizationParameters.get(OAuth2Utils.REDIRECT_URI), - OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Utils.RESPONSE_TYPE))); - return request; - } - @Test public void testApproval() throws Exception { AuthorizationRequest authorizationRequest = createFromParameters(parameters); @@ -176,4 +166,14 @@ public void testSerialization() { assertEquals(authorizationRequest, other); } + private AuthorizationRequest createFromParameters(Map authorizationParameters) { + AuthorizationRequest request = new AuthorizationRequest(authorizationParameters, Collections. emptyMap(), + authorizationParameters.get(OAuth2Utils.CLIENT_ID), + OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Utils.SCOPE)), null, + null, false, authorizationParameters.get(OAuth2Utils.STATE), + authorizationParameters.get(OAuth2Utils.REDIRECT_URI), + OAuth2Utils.parseParameterList(authorizationParameters.get(OAuth2Utils.RESPONSE_TYPE))); + return request; + } + } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/OAuth2RequestTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/OAuth2RequestTests.java new file mode 100644 index 000000000..7febc02f7 --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/OAuth2RequestTests.java @@ -0,0 +1,60 @@ +/* + * Copyright 20013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.springframework.security.oauth2.provider; + +import static org.junit.Assert.assertEquals; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.security.oauth2.common.util.OAuth2Utils; + +/** + * @author Dave Syer + * + */ +public class OAuth2RequestTests { + + private Map parameters; + + @Before + public void prepare() { + parameters = new HashMap(); + parameters.put("client_id", "theClient"); + } + + @Test + public void testImplicitGrantType() throws Exception { + parameters.put("response_type", "token"); + OAuth2Request authorizationRequest = createFromParameters(parameters); + assertEquals("implicit", authorizationRequest.getGrantType()); + } + + @Test + public void testOtherGrantType() throws Exception { + parameters.put("grant_type", "password"); + OAuth2Request authorizationRequest = createFromParameters(parameters); + assertEquals("password", authorizationRequest.getGrantType()); + } + + private OAuth2Request createFromParameters(Map parameters) { + OAuth2Request request = RequestTokenFactory.createOAuth2Request(parameters, + parameters.get(OAuth2Utils.CLIENT_ID), false, + OAuth2Utils.parseParameterList(parameters.get(OAuth2Utils.SCOPE))); + return request; + } + +} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/request/DefaultAuthorizationRequestFactoryTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/request/DefaultAuthorizationRequestFactoryTests.java index 623a99744..7e943d538 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/request/DefaultAuthorizationRequestFactoryTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/request/DefaultAuthorizationRequestFactoryTests.java @@ -16,6 +16,8 @@ import static org.junit.Assert.assertEquals; import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import org.junit.After; import org.junit.Before; @@ -27,9 +29,9 @@ import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.client.BaseClientDetails; -import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory; /** * @author Dave Syer @@ -82,6 +84,24 @@ public void testCreateAuthorizationRequestWithUserRoles() { assertEquals("[bar]", request.getScope().toString()); } + @Test + public void testCreateAuthorizationThenOAuth2RequestWithGrantType() { + factory.setCheckUserScopes(true); + Map parameters = new HashMap(); + parameters.put("client_id", "foo"); + parameters.put("response_type", "token"); + OAuth2Request request = factory.createAuthorizationRequest(parameters).createOAuth2Request(); + assertEquals("implicit", request.getGrantType()); + } + + @Test + public void testCreateTokenThenOAuth2RequestWithGrantType() { + factory.setCheckUserScopes(true); + AuthorizationRequest auth = factory.createAuthorizationRequest(Collections.singletonMap("client_id", "foo")); + OAuth2Request request = factory.createTokenRequest(auth, "password").createOAuth2Request(client); + assertEquals("password", request.getGrantType()); + } + @Test public void testCreateAuthorizationRequestWhenUserNotPermitted() { SecurityContextHolder.getContext().setAuthentication( diff --git a/tests/annotation/approval/.gitignore b/tests/annotation/approval/.gitignore index 1dd333108..b49c56399 100644 --- a/tests/annotation/approval/.gitignore +++ b/tests/annotation/approval/.gitignore @@ -1,2 +1,4 @@ /target/ /target/ +/target/ +/target/ diff --git a/tests/annotation/client/.gitignore b/tests/annotation/client/.gitignore index 1dd333108..e91d5c41b 100644 --- a/tests/annotation/client/.gitignore +++ b/tests/annotation/client/.gitignore @@ -1,2 +1,3 @@ /target/ /target/ +/target/ diff --git a/tests/annotation/common/.gitignore b/tests/annotation/common/.gitignore index b83d22266..b49c56399 100644 --- a/tests/annotation/common/.gitignore +++ b/tests/annotation/common/.gitignore @@ -1 +1,4 @@ /target/ +/target/ +/target/ +/target/ diff --git a/tests/annotation/form/.gitignore b/tests/annotation/form/.gitignore index b83d22266..1dd333108 100644 --- a/tests/annotation/form/.gitignore +++ b/tests/annotation/form/.gitignore @@ -1 +1,2 @@ /target/ +/target/ diff --git a/tests/annotation/jdbc/.gitignore b/tests/annotation/jdbc/.gitignore index 1dd333108..b49c56399 100644 --- a/tests/annotation/jdbc/.gitignore +++ b/tests/annotation/jdbc/.gitignore @@ -1,2 +1,4 @@ /target/ /target/ +/target/ +/target/ diff --git a/tests/annotation/jwt/.gitignore b/tests/annotation/jwt/.gitignore index b83d22266..b49c56399 100644 --- a/tests/annotation/jwt/.gitignore +++ b/tests/annotation/jwt/.gitignore @@ -1 +1,4 @@ /target/ +/target/ +/target/ +/target/ diff --git a/tests/annotation/mappings/.gitignore b/tests/annotation/mappings/.gitignore index b83d22266..1dd333108 100644 --- a/tests/annotation/mappings/.gitignore +++ b/tests/annotation/mappings/.gitignore @@ -1 +1,2 @@ /target/ +/target/ diff --git a/tests/annotation/multi/.gitignore b/tests/annotation/multi/.gitignore index 1dd333108..b49c56399 100644 --- a/tests/annotation/multi/.gitignore +++ b/tests/annotation/multi/.gitignore @@ -1,2 +1,4 @@ /target/ /target/ +/target/ +/target/ diff --git a/tests/annotation/resource/.gitignore b/tests/annotation/resource/.gitignore index b83d22266..e91d5c41b 100644 --- a/tests/annotation/resource/.gitignore +++ b/tests/annotation/resource/.gitignore @@ -1 +1,3 @@ /target/ +/target/ +/target/ diff --git a/tests/annotation/vanilla/.gitignore b/tests/annotation/vanilla/.gitignore index b83d22266..1dd333108 100644 --- a/tests/annotation/vanilla/.gitignore +++ b/tests/annotation/vanilla/.gitignore @@ -1 +1,2 @@ /target/ +/target/ From e1d203a36fa529608ecc7b125921e73565a9cbd4 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 24 Sep 2014 15:14:58 +0100 Subject: [PATCH 307/831] Remove .gitignores --- tests/annotation/approval/.gitignore | 1 + tests/annotation/client/.gitignore | 1 + tests/annotation/form/.gitignore | 1 + tests/annotation/jdbc/.gitignore | 1 + tests/annotation/jwt/.gitignore | 1 + tests/annotation/mappings/.gitignore | 1 + tests/annotation/multi/.gitignore | 1 + tests/annotation/resource/.gitignore | 1 + tests/annotation/vanilla/.gitignore | 1 + 9 files changed, 9 insertions(+) diff --git a/tests/annotation/approval/.gitignore b/tests/annotation/approval/.gitignore index b49c56399..9c1822dc1 100644 --- a/tests/annotation/approval/.gitignore +++ b/tests/annotation/approval/.gitignore @@ -2,3 +2,4 @@ /target/ /target/ /target/ +/target/ diff --git a/tests/annotation/client/.gitignore b/tests/annotation/client/.gitignore index e91d5c41b..b49c56399 100644 --- a/tests/annotation/client/.gitignore +++ b/tests/annotation/client/.gitignore @@ -1,3 +1,4 @@ /target/ /target/ /target/ +/target/ diff --git a/tests/annotation/form/.gitignore b/tests/annotation/form/.gitignore index 1dd333108..e91d5c41b 100644 --- a/tests/annotation/form/.gitignore +++ b/tests/annotation/form/.gitignore @@ -1,2 +1,3 @@ /target/ /target/ +/target/ diff --git a/tests/annotation/jdbc/.gitignore b/tests/annotation/jdbc/.gitignore index b49c56399..9c1822dc1 100644 --- a/tests/annotation/jdbc/.gitignore +++ b/tests/annotation/jdbc/.gitignore @@ -2,3 +2,4 @@ /target/ /target/ /target/ +/target/ diff --git a/tests/annotation/jwt/.gitignore b/tests/annotation/jwt/.gitignore index b49c56399..9c1822dc1 100644 --- a/tests/annotation/jwt/.gitignore +++ b/tests/annotation/jwt/.gitignore @@ -2,3 +2,4 @@ /target/ /target/ /target/ +/target/ diff --git a/tests/annotation/mappings/.gitignore b/tests/annotation/mappings/.gitignore index 1dd333108..e91d5c41b 100644 --- a/tests/annotation/mappings/.gitignore +++ b/tests/annotation/mappings/.gitignore @@ -1,2 +1,3 @@ /target/ /target/ +/target/ diff --git a/tests/annotation/multi/.gitignore b/tests/annotation/multi/.gitignore index b49c56399..9c1822dc1 100644 --- a/tests/annotation/multi/.gitignore +++ b/tests/annotation/multi/.gitignore @@ -2,3 +2,4 @@ /target/ /target/ /target/ +/target/ diff --git a/tests/annotation/resource/.gitignore b/tests/annotation/resource/.gitignore index e91d5c41b..b49c56399 100644 --- a/tests/annotation/resource/.gitignore +++ b/tests/annotation/resource/.gitignore @@ -1,3 +1,4 @@ /target/ /target/ /target/ +/target/ diff --git a/tests/annotation/vanilla/.gitignore b/tests/annotation/vanilla/.gitignore index 1dd333108..e91d5c41b 100644 --- a/tests/annotation/vanilla/.gitignore +++ b/tests/annotation/vanilla/.gitignore @@ -1,2 +1,3 @@ /target/ /target/ +/target/ From 464e38eb70848c54fc9d46dd46a1548cb1b5e01c Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 24 Sep 2014 15:15:07 +0100 Subject: [PATCH 308/831] Nail Maven javadoc plugin version --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index e512d847b..644ce27d6 100644 --- a/pom.xml +++ b/pom.xml @@ -185,6 +185,7 @@ maven-javadoc-plugin + 2.9.1 javadoc From aae09e0c1747e4438bc4e9c178478c646c33e487 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 30 Sep 2014 12:34:08 +0100 Subject: [PATCH 309/831] Remove .gitignores again --- tests/annotation/approval/.gitignore | 5 ----- tests/annotation/client/.gitignore | 4 ---- tests/annotation/common/.gitignore | 4 ---- tests/annotation/form/.gitignore | 3 --- tests/annotation/jdbc/.gitignore | 5 ----- tests/annotation/jwt/.gitignore | 5 ----- tests/annotation/mappings/.gitignore | 3 --- tests/annotation/multi/.gitignore | 5 ----- tests/annotation/resource/.gitignore | 4 ---- tests/annotation/vanilla/.gitignore | 3 --- 10 files changed, 41 deletions(-) delete mode 100644 tests/annotation/approval/.gitignore delete mode 100644 tests/annotation/client/.gitignore delete mode 100644 tests/annotation/common/.gitignore delete mode 100644 tests/annotation/form/.gitignore delete mode 100644 tests/annotation/jdbc/.gitignore delete mode 100644 tests/annotation/jwt/.gitignore delete mode 100644 tests/annotation/mappings/.gitignore delete mode 100644 tests/annotation/multi/.gitignore delete mode 100644 tests/annotation/resource/.gitignore delete mode 100644 tests/annotation/vanilla/.gitignore diff --git a/tests/annotation/approval/.gitignore b/tests/annotation/approval/.gitignore deleted file mode 100644 index 9c1822dc1..000000000 --- a/tests/annotation/approval/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -/target/ -/target/ -/target/ -/target/ -/target/ diff --git a/tests/annotation/client/.gitignore b/tests/annotation/client/.gitignore deleted file mode 100644 index b49c56399..000000000 --- a/tests/annotation/client/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -/target/ -/target/ -/target/ -/target/ diff --git a/tests/annotation/common/.gitignore b/tests/annotation/common/.gitignore deleted file mode 100644 index b49c56399..000000000 --- a/tests/annotation/common/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -/target/ -/target/ -/target/ -/target/ diff --git a/tests/annotation/form/.gitignore b/tests/annotation/form/.gitignore deleted file mode 100644 index e91d5c41b..000000000 --- a/tests/annotation/form/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/target/ -/target/ -/target/ diff --git a/tests/annotation/jdbc/.gitignore b/tests/annotation/jdbc/.gitignore deleted file mode 100644 index 9c1822dc1..000000000 --- a/tests/annotation/jdbc/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -/target/ -/target/ -/target/ -/target/ -/target/ diff --git a/tests/annotation/jwt/.gitignore b/tests/annotation/jwt/.gitignore deleted file mode 100644 index 9c1822dc1..000000000 --- a/tests/annotation/jwt/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -/target/ -/target/ -/target/ -/target/ -/target/ diff --git a/tests/annotation/mappings/.gitignore b/tests/annotation/mappings/.gitignore deleted file mode 100644 index e91d5c41b..000000000 --- a/tests/annotation/mappings/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/target/ -/target/ -/target/ diff --git a/tests/annotation/multi/.gitignore b/tests/annotation/multi/.gitignore deleted file mode 100644 index 9c1822dc1..000000000 --- a/tests/annotation/multi/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -/target/ -/target/ -/target/ -/target/ -/target/ diff --git a/tests/annotation/resource/.gitignore b/tests/annotation/resource/.gitignore deleted file mode 100644 index b49c56399..000000000 --- a/tests/annotation/resource/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -/target/ -/target/ -/target/ -/target/ diff --git a/tests/annotation/vanilla/.gitignore b/tests/annotation/vanilla/.gitignore deleted file mode 100644 index e91d5c41b..000000000 --- a/tests/annotation/vanilla/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/target/ -/target/ -/target/ From 1e0725fda7819c0349066e587e8ac80ad33a43de Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 30 Sep 2014 12:34:29 +0100 Subject: [PATCH 310/831] Add tests for invalid client id in /authorize See gh-265 --- .../common/AbstractAuthorizationCodeProviderTests.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java b/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java index 5e9451cf4..d1492bc8a 100755 --- a/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java @@ -200,6 +200,16 @@ public void testNoClientIdProvided() throws Exception { assertTrue("Wrong body: " + body, body.contains("Bad client credentials")); } + @Test + public void testWrongClientIdProvided() throws Exception { + ResponseEntity response = attemptToGetConfirmationPage("no-such-client", "http://anywhere/"); + // With no client id you get an InvalidClientException on the server which is forwarded to /oauth/error + assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); + String body = response.getBody(); + assertTrue("Wrong body: " + body, body.contains(" response = attemptToGetConfirmationPage("my-trusted-client", null); From 10acf7fb28b722f54f8a6e7130f845f668d73e28 Mon Sep 17 00:00:00 2001 From: Saket Date: Mon, 29 Sep 2014 17:04:22 +0100 Subject: [PATCH 311/831] Fix IllegalArgumentException when scope is a String instead of a collection Fixs gh-266 --- .../DefaultUserAuthenticationConverter.java | 2 +- ...faultUserAuthenticationConverterTests.java | 51 +++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultUserAuthenticationConverterTests.java diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultUserAuthenticationConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultUserAuthenticationConverter.java index c7da15c17..318495365 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultUserAuthenticationConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultUserAuthenticationConverter.java @@ -68,7 +68,7 @@ private Collection getAuthorities(Map map } Object authorities = map.get(AUTHORITIES); if (authorities instanceof String) { - AuthorityUtils.commaSeparatedStringToAuthorityList((String) authorities); + return AuthorityUtils.commaSeparatedStringToAuthorityList((String) authorities); } if (authorities instanceof Collection) { return AuthorityUtils.commaSeparatedStringToAuthorityList(StringUtils diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultUserAuthenticationConverterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultUserAuthenticationConverterTests.java new file mode 100644 index 000000000..ff1fd4700 --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultUserAuthenticationConverterTests.java @@ -0,0 +1,51 @@ +package org.springframework.security.oauth2.provider.token; + +import org.junit.Test; +import org.springframework.security.core.Authentication; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +/** + * Created with IntelliJ IDEA. + * User: saket + * Date: 29/09/2014 + * Time: 16:25 + * To change this template use File | Settings | File Templates. + */ + +public class DefaultUserAuthenticationConverterTests { + private UserAuthenticationConverter converter = new DefaultUserAuthenticationConverter(); + + @Test + public void shouldExtractAuthenticationWhenAuthoritiesIsCollection() throws Exception { + Map map = new HashMap(); + map.put(UserAuthenticationConverter.USERNAME, "test_user"); + ArrayList lists = new ArrayList(); + lists.add("a1"); + lists.add("a2"); + map.put(UserAuthenticationConverter.AUTHORITIES, lists); + + Authentication authentication = converter.extractAuthentication(map); + + assertNotEquals(authentication.getAuthorities(), null); + assertEquals(authentication.getAuthorities().size(), 2); + } + + @Test + public void shouldExtractAuthenticationWhenAuthoritiesIsString() throws Exception { + Map map = new HashMap(); + map.put(UserAuthenticationConverter.USERNAME, "test_user"); + map.put(UserAuthenticationConverter.AUTHORITIES, "a1,a2"); + + Authentication authentication = converter.extractAuthentication(map); + + assertNotEquals(authentication.getAuthorities(), null); + assertEquals(authentication.getAuthorities().size(), 2); + } +} + From dabcae6ece72153af83e44f2e1539c59d50077e7 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 3 Oct 2014 13:58:31 +0100 Subject: [PATCH 312/831] Add another integration test for /authorize endpoint Checks that a client credentials exception leads to a 401 and an error page from the server (because the redirect cannot be verified). See gh-265 --- ...bstractAuthorizationCodeProviderTests.java | 34 ++++++++++++------- .../demo/AuthorizationCodeProviderTests.java | 26 ++++++++++++++ 2 files changed, 47 insertions(+), 13 deletions(-) diff --git a/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java b/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java index d1492bc8a..fcb5512bb 100755 --- a/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java @@ -200,16 +200,6 @@ public void testNoClientIdProvided() throws Exception { assertTrue("Wrong body: " + body, body.contains("Bad client credentials")); } - @Test - public void testWrongClientIdProvided() throws Exception { - ResponseEntity response = attemptToGetConfirmationPage("no-such-client", "http://anywhere/"); - // With no client id you get an InvalidClientException on the server which is forwarded to /oauth/error - assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); - String body = response.getBody(); - assertTrue("Wrong body: " + body, body.contains(" response = attemptToGetConfirmationPage("my-trusted-client", null); @@ -320,11 +310,29 @@ public void testRegisteredRedirectWithWrongOneInTokenEndpoint() throws Exception } } - private ResponseEntity attemptToGetConfirmationPage(String clientId, String redirectUri) { - HttpHeaders headers = getAuthenticatedHeaders(); - return http.getForString(getAuthorizeUrl(clientId, redirectUri, "read"), headers); + protected ResponseEntity attemptToGetConfirmationPage(String clientId, String redirectUri) { + return attemptToGetConfirmationPage(clientId, redirectUri, "code"); } + protected ResponseEntity attemptToGetConfirmationPage(String clientId, String redirectUri, String responseType) { + HttpHeaders headers = getAuthenticatedHeaders(); + return http.getForString(getAuthorizeUrl(clientId, redirectUri, responseType, "read"), headers); + } + + private String getAuthorizeUrl(String clientId, String redirectUri, String responseType, String scope) { + UriBuilder uri = http.buildUri(authorizePath()).queryParam("state", "mystateid").queryParam("scope", scope); + if (responseType != null) { + uri.queryParam("response_type", responseType); + } + if (clientId != null) { + uri.queryParam("client_id", clientId); + } + if (redirectUri != null) { + uri.queryParam("redirect_uri", redirectUri); + } + return uri.build().toString(); + } + private HttpHeaders getAuthenticatedHeaders() { HttpHeaders headers = new HttpHeaders(); headers.setAccept(Arrays.asList(MediaType.TEXT_HTML)); diff --git a/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java index 632098bf1..0655723fa 100755 --- a/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java +++ b/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -12,7 +12,13 @@ */ package demo; +import static org.junit.Assert.assertEquals; +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 sparklr.common.AbstractAuthorizationCodeProviderTests; @@ -22,4 +28,24 @@ @SpringApplicationConfiguration(classes = Application.class) public class AuthorizationCodeProviderTests extends AbstractAuthorizationCodeProviderTests { + @Test + public void testWrongClientIdProvided() throws Exception { + ResponseEntity response = attemptToGetConfirmationPage("no-such-client", "http://anywhere/"); + // With no client id you get an InvalidClientException on the server which is forwarded to /oauth/error + assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); + String body = response.getBody(); + assertTrue("Wrong body: " + body, body.contains(" response = attemptToGetConfirmationPage("no-such-client", "http://anywhere/", null); + // With bad client id you get an InvalidClientException on the server which is forwarded to /oauth/error + assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); + String body = response.getBody(); + assertTrue("Wrong body: " + body, body.contains(" Date: Thu, 28 Aug 2014 21:37:46 +0200 Subject: [PATCH 313/831] Additional fix for additionInformation bug and tests Fixes gh-251 --- .../builders/ClientDetailsServiceBuilder.java | 2 +- ...AuthorizationServerConfigurationTests.java | 31 ++++++++++--------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java index ead812ea7..6e5d72985 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java @@ -203,7 +203,7 @@ public ClientBuilder additionalInformation(String... pairs) { } int index = pair.indexOf(separator); String key = pair.substring(0, index > 0 ? index : pair.length()); - String value = index > 0 ? pair.substring(index) : null; + String value = index > 0 ? pair.substring(index+1) : null; this.additionalInformation.put(key, (Object) value); } return this; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java index d5e1701f3..98f8eb3d1 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java @@ -12,17 +12,6 @@ */ package org.springframework.security.oauth2.config.annotation; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import javax.sql.DataSource; - import org.junit.After; import org.junit.Rule; import org.junit.Test; @@ -63,6 +52,13 @@ import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; +import javax.sql.DataSource; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.*; + /** * @author Dave Syer * @@ -147,7 +143,7 @@ public void configure(ClientDetailsServiceConfigurer clients) throws Exception { .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") .scopes("read", "write", "trust") .accessTokenValiditySeconds(60) - .additionalInformation("foo:bar", "spam:bucket", "crap"); + .additionalInformation("foo:bar", "spam:bucket", "crap", "bad:"); // @formatter:on } @@ -161,8 +157,15 @@ public void run() { Map request = handler.getUserApprovalRequest(authorizationRequest, new UsernamePasswordAuthenticationToken("user", "password")); assertTrue(request.containsKey("scopes")); - assertTrue(clientDetailsService.loadClientByClientId("my-trusted-client").getAdditionalInformation() - .containsKey("foo")); + + Map information = clientDetailsService.loadClientByClientId("my-trusted-client") + .getAdditionalInformation(); + + assertTrue(information.containsKey("foo")); + assertTrue(information.get("foo").equals("bar")); + assertTrue(information.get("spam").equals("bucket")); + assertTrue(information.get("crap") == null); + assertTrue(information.get("bad").equals("")); } } From 4ab43f06317a2ac2f93877dbfe2189d479fb840c Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Sat, 11 Oct 2014 16:41:58 +0100 Subject: [PATCH 314/831] Expose client authorities in /check_token Fixed gh-274 --- .../provider/token/AccessTokenConverter.java | 2 ++ .../token/DefaultAccessTokenConverter.java | 4 ++++ .../token/UserAuthenticationConverter.java | 2 +- .../DefaultAccessTokenConverterTests.java | 22 ++++++++++++++++--- 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AccessTokenConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AccessTokenConverter.java index 409844de3..4a0b0607f 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AccessTokenConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AccessTokenConverter.java @@ -35,6 +35,8 @@ public interface AccessTokenConverter { final String SCOPE = OAuth2AccessToken.SCOPE; + final String AUTHORITIES = "authorities"; + /** * @param token an access token * @param authentication the current OAuth authentication diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java index 57d486d7d..32dc3a083 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java @@ -52,6 +52,10 @@ public void setUserTokenConverter(UserAuthenticationConverter userTokenConverter if (!authentication.isClientOnly()) { response.putAll(userTokenConverter.convertUserAuthentication(authentication.getUserAuthentication())); + } else { + if (clientToken.getAuthorities()!=null && !clientToken.getAuthorities().isEmpty()) { + response.put(UserAuthenticationConverter.AUTHORITIES, clientToken.getAuthorities()); + } } if (token.getScope()!=null) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/UserAuthenticationConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/UserAuthenticationConverter.java index 4823b0478..737bfa500 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/UserAuthenticationConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/UserAuthenticationConverter.java @@ -25,7 +25,7 @@ */ public interface UserAuthenticationConverter { - final String AUTHORITIES = "authorities"; + final String AUTHORITIES = AccessTokenConverter.AUTHORITIES; final String USERNAME = "user_name"; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverterTests.java index 3822be05f..e2f86d72a 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverterTests.java @@ -39,21 +39,37 @@ public class DefaultAccessTokenConverterTests { private UsernamePasswordAuthenticationToken userAuthentication = new UsernamePasswordAuthenticationToken("foo", "bar", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"))); - private OAuth2Authentication authentication; + private OAuth2Request request; @Before public void init() { - OAuth2Request request = RequestTokenFactory.createOAuth2Request(null, "id", + request = RequestTokenFactory.createOAuth2Request(null, "id", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_CLIENT"), true, Collections.singleton("read"), Collections.singleton("resource"), null, null, null); - authentication = new OAuth2Authentication(request, userAuthentication); } @Test public void extractAuthentication() { DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken("FOO"); + OAuth2Authentication authentication = new OAuth2Authentication(request, userAuthentication); + token.setScope(authentication.getOAuth2Request().getScope()); Map map = converter.convertAccessToken(token, authentication); assertTrue(map.containsKey(AccessTokenConverter.AUD)); + assertTrue(map.containsKey(AccessTokenConverter.SCOPE)); + assertTrue(map.containsKey(AccessTokenConverter.AUTHORITIES)); + OAuth2Authentication extracted = converter.extractAuthentication(map); + assertTrue(extracted.getOAuth2Request().getResourceIds().contains("resource")); + } + + @Test + public void extractAuthenticationFromClientToken() { + DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken("FOO"); + OAuth2Authentication authentication = new OAuth2Authentication(request, null); + token.setScope(authentication.getOAuth2Request().getScope()); + Map map = converter.convertAccessToken(token, authentication); + assertTrue(map.containsKey(AccessTokenConverter.AUD)); + assertTrue(map.containsKey(AccessTokenConverter.SCOPE)); + assertTrue(map.containsKey(AccessTokenConverter.AUTHORITIES)); OAuth2Authentication extracted = converter.extractAuthentication(map); assertTrue(extracted.getOAuth2Request().getResourceIds().contains("resource")); } From 2981cd74a76642cf13737a9d987932029ec0090c Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Sat, 11 Oct 2014 16:47:18 +0100 Subject: [PATCH 315/831] Pass resource ids through to OAuth2Request from TokenRequest Fixes gh-271 --- .../oauth2/provider/TokenRequest.java | 37 ++++++++----------- ...faultAuthorizationRequestFactoryTests.java | 3 ++ 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java index 687634219..71e1c652b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java @@ -9,14 +9,12 @@ import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint; /** - * Represents an OAuth2 token request, made at the {@link TokenEndpoint}. The - * requestParameters map should contain the original, unmodified parameters from - * the original OAuth2 request. + * Represents an OAuth2 token request, made at the {@link TokenEndpoint}. The requestParameters map should contain the + * original, unmodified parameters from the original OAuth2 request. * - * In the implicit flow, a token is requested through the - * {@link AuthorizationEndpoint} directly, and in that case the - * {@link AuthorizationRequest} is converted into a {@link TokenRequest} for - * processing through the token granting chain. + * In the implicit flow, a token is requested through the {@link AuthorizationEndpoint} directly, and in that case the + * {@link AuthorizationRequest} is converted into a {@link TokenRequest} for processing through the token granting + * chain. * * @author Amanda Anganes * @author Dave Syer @@ -34,16 +32,15 @@ protected TokenRequest() { } /** - * Full constructor. Sets this TokenRequest's requestParameters map to an - * unmodifiable version of the one provided. + * Full constructor. Sets this TokenRequest's requestParameters map to an unmodifiable version of the one provided. * * @param requestParameters * @param clientId * @param scope * @param grantType */ - public TokenRequest(Map requestParameters, String clientId, - Collection scope, String grantType) { + public TokenRequest(Map requestParameters, String clientId, Collection scope, + String grantType) { setClientId(clientId); setRequestParameters(requestParameters); setScope(scope); @@ -63,9 +60,8 @@ public void setClientId(String clientId) { } /** - * Set the scope value. If the collection contains only a single scope - * value, this method will parse that value into a collection using - * {@link OAuth2Utils.parseParameterList}. + * Set the scope value. If the collection contains only a single scope value, this method will parse that value into + * a collection using {@link OAuth2Utils.parseParameterList}. * * @see AuthorizationRequest.setScope * @@ -76,9 +72,8 @@ public void setScope(Collection scope) { } /** - * Set the Request Parameters on this authorization request, which represent - * the original request parameters and should never be changed during - * processing. The map passed in is wrapped in an unmodifiable map instance. + * Set the Request Parameters on this authorization request, which represent the original request parameters and + * should never be changed during processing. The map passed in is wrapped in an unmodifiable map instance. * * @see AuthorizationRequest.setRequestParameters * @@ -90,15 +85,13 @@ public void setRequestParameters(Map requestParameters) { public OAuth2Request createOAuth2Request(ClientDetails client) { Map requestParameters = getRequestParameters(); - HashMap modifiable = new HashMap( - requestParameters); + HashMap modifiable = new HashMap(requestParameters); // Remove password if present to prevent leaks modifiable.remove("password"); // Add grant type so it can be retrieved from OAuth2Request modifiable.put("grant_type", grantType); - return new OAuth2Request(modifiable, client.getClientId(), - client.getAuthorities(), true, this.getScope(), null, null, - null, null); + return new OAuth2Request(modifiable, client.getClientId(), client.getAuthorities(), true, this.getScope(), + client.getResourceIds(), null, null, null); } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/request/DefaultAuthorizationRequestFactoryTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/request/DefaultAuthorizationRequestFactoryTests.java index 7e943d538..dc05f8c04 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/request/DefaultAuthorizationRequestFactoryTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/request/DefaultAuthorizationRequestFactoryTests.java @@ -15,6 +15,7 @@ import static org.junit.Assert.assertEquals; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -51,6 +52,7 @@ public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exceptio public void start() { client.setClientId("foo"); client.setScope(Collections.singleton("bar")); + client.setResourceIds(Arrays.asList("bar")); } @After @@ -100,6 +102,7 @@ public void testCreateTokenThenOAuth2RequestWithGrantType() { AuthorizationRequest auth = factory.createAuthorizationRequest(Collections.singletonMap("client_id", "foo")); OAuth2Request request = factory.createTokenRequest(auth, "password").createOAuth2Request(client); assertEquals("password", request.getGrantType()); + assertEquals("[bar]", request.getResourceIds().toString()); } @Test From 76839fc3ca89b3bbcf312ad6ede0acae0a22cee6 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Sat, 11 Oct 2014 16:43:03 +0100 Subject: [PATCH 316/831] Add specific user (not default) for testing authentication in password flow --- .../common/AbstractIntegrationTests.java | 6 ++++- .../jdbc/src/main/java/demo/Application.java | 16 ++++-------- .../jdbc/src/main/resources/application.yml | 3 +++ .../demo/AuthorizationCodeProviderTests.java | 6 +++++ .../ResourceOwnerPasswordProviderTests.java | 25 ++++++++++++++++++- tests/annotation/pom.xml | 2 +- .../demo/AuthorizationCodeProviderTests.java | 14 ++++++++++- tests/xml/pom.xml | 2 +- 8 files changed, 58 insertions(+), 16 deletions(-) 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 2f90d4d21..8b91a7f1f 100644 --- a/tests/annotation/common/src/main/java/sparklr/common/AbstractIntegrationTests.java +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractIntegrationTests.java @@ -103,11 +103,15 @@ public void fixPaths() { if (resource instanceof ImplicitResourceDetails) { resource.setAccessTokenUri(http.getUrl(authorizePath())); } - if (resource instanceof ResourceOwnerPasswordResourceDetails) { + if (resource instanceof ResourceOwnerPasswordResourceDetails && !(resource instanceof DoNotOverride)) { ((ResourceOwnerPasswordResourceDetails) resource).setUsername(security.getUser().getName()); ((ResourceOwnerPasswordResourceDetails) resource).setPassword(security.getUser().getPassword()); } } + + public interface DoNotOverride { + + } @After public void close() throws Exception { diff --git a/tests/annotation/jdbc/src/main/java/demo/Application.java b/tests/annotation/jdbc/src/main/java/demo/Application.java index 0f5ab8baf..1c957cd55 100644 --- a/tests/annotation/jdbc/src/main/java/demo/Application.java +++ b/tests/annotation/jdbc/src/main/java/demo/Application.java @@ -5,8 +5,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.security.SecurityProperties; -import org.springframework.boot.autoconfigure.security.SecurityProperties.User; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; @@ -124,18 +122,14 @@ protected static class AuthenticationManagerConfiguration extends GlobalAuthenti @Autowired private DataSource dataSource; - @Autowired - private SecurityProperties security; - @Override public void init(AuthenticationManagerBuilder auth) throws Exception { - User user = security.getUser(); // @formatter:off - auth.jdbcAuthentication().dataSource(dataSource) - .withUser(user.getName()) - .password(user.getPassword()) - .roles(user.getRole().toArray(new String[0])); - // @formatter:on + auth.jdbcAuthentication().dataSource(dataSource) + .withUser("dave") + .password("secret") + .roles("USER"); + // @formatter:on } } diff --git a/tests/annotation/jdbc/src/main/resources/application.yml b/tests/annotation/jdbc/src/main/resources/application.yml index c2b03892c..df9f757f7 100644 --- a/tests/annotation/jdbc/src/main/resources/application.yml +++ b/tests/annotation/jdbc/src/main/resources/application.yml @@ -6,6 +6,9 @@ management: security: user: password: password +logging: + level: + org.springframework.security: DEBUG --- diff --git a/tests/annotation/jdbc/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/jdbc/src/test/java/demo/AuthorizationCodeProviderTests.java index 8c4082abd..984266a9e 100755 --- a/tests/annotation/jdbc/src/test/java/demo/AuthorizationCodeProviderTests.java +++ b/tests/annotation/jdbc/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -16,6 +16,7 @@ import static org.junit.Assert.assertTrue; import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.security.crypto.codec.Base64; import sparklr.common.AbstractAuthorizationCodeProviderTests; @@ -25,6 +26,11 @@ @SpringApplicationConfiguration(classes = Application.class) public class AuthorizationCodeProviderTests extends AbstractAuthorizationCodeProviderTests { + protected String getBasicAuthentication() { + // SecurityProperties is used to create a parent authentication manager + return "Basic " + new String(Base64.encode(("dave:secret").getBytes())); + } + protected void verifyAuthorizationPage(String page) { assertTrue(page.contains("action='http://github.com/oauth/authorize'")); assertTrue(page.contains(" org.springframework.boot spring-boot-starter-parent - 1.1.5.RELEASE + 1.1.7.RELEASE diff --git a/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java index 0655723fa..20c5b9ef7 100755 --- a/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java +++ b/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -39,7 +39,7 @@ public void testWrongClientIdProvided() throws Exception { } @Test - public void testWrongClientIdAndOmittedResponseTypeProvided() throws Exception { + public void testWrongClientIdAndOmittedResponseType() throws Exception { // Test wrong client id together with an omitted response_type ResponseEntity response = attemptToGetConfirmationPage("no-such-client", "http://anywhere/", null); // With bad client id you get an InvalidClientException on the server which is forwarded to /oauth/error @@ -48,4 +48,16 @@ public void testWrongClientIdAndOmittedResponseTypeProvided() throws Exception { assertTrue("Wrong body: " + body, body.contains(" response = attemptToGetConfirmationPage("no-such-client", "http://anywhere/", "unsupported"); + // With bad client id you get an InvalidClientException on the server which is forwarded to /oauth/error + assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); + String body = response.getBody(); + assertTrue("Wrong body: " + body, body.contains(" org.springframework.boot spring-boot-starter-parent - 1.1.5.RELEASE + 1.1.7.RELEASE From baf89900ab087310f7077644da03c7432ed89e18 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 15 Oct 2014 11:28:02 +0100 Subject: [PATCH 317/831] Fix JDBC sample tests so they authenticate properly --- docs/oauth2.md | 2 +- ...uthorizationServerEndpointsConfigurer.java | 36 +++++++++++++++++-- .../common/AbstractIntegrationTests.java | 16 ++++++--- .../AbstractRefreshTokenSupportTests.java | 4 +-- .../jdbc/src/main/java/demo/Application.java | 18 +++++----- .../demo/AuthorizationCodeProviderTests.java | 10 +++--- .../test/java/demo/ImplicitProviderTests.java | 8 +++++ .../java/demo/RefreshTokenSupportTests.java | 7 ++++ .../ResourceOwnerPasswordProviderTests.java | 8 +++++ tests/annotation/multi/pom.xml | 2 +- .../multi/src/main/java/demo/Application.java | 10 +++++- .../ResourceOwnerPasswordProviderTests.java | 22 ++++++++++++ 12 files changed, 117 insertions(+), 26 deletions(-) diff --git a/docs/oauth2.md b/docs/oauth2.md index 9f71c0696..335090e16 100644 --- a/docs/oauth2.md +++ b/docs/oauth2.md @@ -78,7 +78,7 @@ configured via the `AuthorizationServerEndpointsConfigurer`. By default all grant types are supported except password (see below for details of how to switch it on). The following properties affect grant types: -* `authenticationManager`: password grants are switched on by injecting an `AuthenticationManager`. +* `authenticationManager`: password grants are switched on by injecting an `AuthenticationManager`. Take care when injecting an `AuthenticationManager` into an `AuthorizationServerEndpointsConfigurer`: if you build the `AuthenticationManager` from an `AuthenticationManagerBuilder` elsewhere, then instead of injecting the manager directly, inject the builder. Then you can use the overloaded version of this method that takes the builder as an argument. * `authorizationCodeServices`: defines the authorization code services (instance of `org.springframework.security.oauth2.provider.code.AuthorizationCodeServices`) for the auth code grant * `implicitGrantService`: manages state during the imlpicit grant. * `tokenGranter`: the `TokenGranter` (taking full control of the granting and ignoring the other properties above) 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 2f8275773..03215746f 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 @@ -21,6 +21,9 @@ import java.util.Map; import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.CompositeTokenGranter; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; @@ -57,7 +60,7 @@ import org.springframework.web.servlet.HandlerInterceptor; /** - * Configure the properties and enhanced functionality of the Authorization Server endpoints. + * Configure the properties and enhanced functionality of the Authorization Server endpoints. * * @author Rob Winch * @author Dave Syer @@ -92,7 +95,7 @@ public final class AuthorizationServerEndpointsConfigurer { private AuthenticationManager authenticationManager; private ClientDetailsService clientDetailsService; - + private String prefix; private Map patternMap = new HashMap(); @@ -197,11 +200,38 @@ public AuthorizationServerEndpointsConfigurer addInterceptor(WebRequestIntercept return this; } + /** + * The AuthenticationManager for the password grant. Use this method only if you know the AuthenticationManager is + * fully initialized (because you created it yourself). If you created it elsewhere using an + * AuthenticationManagerBuilder, then do not use this method (use + * {@link #authenticationManager(AuthenticationManagerBuilder)} instead). + * + * @param builder an AuthenticationManager, fully initialized + * @return this for a fluent style + */ public AuthorizationServerEndpointsConfigurer authenticationManager(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; return this; } + /** + * The AuthenticationManager for the password grant can be lazily initialized to avoid a cascade of early + * initialization in the enclosing BeanFactory. + * + * @param builder an AuthenticationManagerBuilder + * @return this for a fluent style + */ + public AuthorizationServerEndpointsConfigurer authenticationManager(AuthenticationManagerBuilder builder) { + final AuthenticationManagerBuilder auth = builder; + this.authenticationManager = new AuthenticationManager() { + @Override + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + return auth.getOrBuild().authenticate(authentication); + } + }; + return this; + } + public AuthorizationServerEndpointsConfigurer tokenGranter(TokenGranter tokenGranter) { this.tokenGranter = tokenGranter; return this; @@ -409,7 +439,7 @@ private FrameworkEndpointHandlerMapping frameworkEndpointHandlerMapping() { frameworkEndpointHandlerMapping = new FrameworkEndpointHandlerMapping(); frameworkEndpointHandlerMapping.setMappings(patternMap); frameworkEndpointHandlerMapping.setPrefix(prefix); - frameworkEndpointHandlerMapping.setInterceptors(interceptors .toArray()); + frameworkEndpointHandlerMapping.setInterceptors(interceptors.toArray()); } return frameworkEndpointHandlerMapping; } 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 8b91a7f1f..388caa6c7 100644 --- a/tests/annotation/common/src/main/java/sparklr/common/AbstractIntegrationTests.java +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractIntegrationTests.java @@ -78,7 +78,7 @@ public abstract class AbstractIntegrationTests { private DataSource dataSource; @Autowired - protected SecurityProperties security; + private SecurityProperties security; @Autowired private ServerProperties server; @@ -104,10 +104,18 @@ public void fixPaths() { resource.setAccessTokenUri(http.getUrl(authorizePath())); } if (resource instanceof ResourceOwnerPasswordResourceDetails && !(resource instanceof DoNotOverride)) { - ((ResourceOwnerPasswordResourceDetails) resource).setUsername(security.getUser().getName()); - ((ResourceOwnerPasswordResourceDetails) resource).setPassword(security.getUser().getPassword()); + ((ResourceOwnerPasswordResourceDetails) resource).setUsername(getUsername()); + ((ResourceOwnerPasswordResourceDetails) resource).setPassword(getPassword()); } } + + protected String getPassword() { + return security.getUser().getPassword(); + } + + protected String getUsername() { + return security.getUser().getName(); + } public interface DoNotOverride { @@ -121,7 +129,7 @@ public void close() throws Exception { protected String getBasicAuthentication() { return "Basic " - + new String(Base64.encode((security.getUser().getName() + ":" + security.getUser().getPassword()) + + new String(Base64.encode((getUsername() + ":" + getPassword()) .getBytes())); } diff --git a/tests/annotation/common/src/main/java/sparklr/common/AbstractRefreshTokenSupportTests.java b/tests/annotation/common/src/main/java/sparklr/common/AbstractRefreshTokenSupportTests.java index 75223068d..726b1fc2d 100644 --- a/tests/annotation/common/src/main/java/sparklr/common/AbstractRefreshTokenSupportTests.java +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractRefreshTokenSupportTests.java @@ -101,8 +101,8 @@ private MultiValueMap getTokenFormData(String scope, String clie formData.add("client_id", clientId); } formData.add("scope", scope); - formData.add("username", security.getUser().getName()); - formData.add("password", security.getUser().getPassword()); + formData.add("username", getUsername()); + formData.add("password", getPassword()); return formData; } } diff --git a/tests/annotation/jdbc/src/main/java/demo/Application.java b/tests/annotation/jdbc/src/main/java/demo/Application.java index 1c957cd55..6de303fdb 100644 --- a/tests/annotation/jdbc/src/main/java/demo/Application.java +++ b/tests/annotation/jdbc/src/main/java/demo/Application.java @@ -7,9 +7,6 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.core.Ordered; -import org.springframework.core.annotation.Order; -import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter; import org.springframework.security.config.annotation.web.builders.HttpSecurity; @@ -65,7 +62,7 @@ public void configure(HttpSecurity http) throws Exception { protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter { @Autowired - private AuthenticationManager authenticationManager; + private AuthenticationManagerBuilder auth; @Autowired private DataSource dataSource; @@ -83,7 +80,7 @@ protected AuthorizationCodeServices authorizationCodeServices() { @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.authorizationCodeServices(authorizationCodeServices()) - .authenticationManager(authenticationManager).tokenStore(tokenStore()).approvalStoreDisabled(); + .authenticationManager(auth).tokenStore(tokenStore()).approvalStoreDisabled(); } @Override @@ -116,7 +113,6 @@ public void configure(ClientDetailsServiceConfigurer clients) throws Exception { } @Configuration - @Order(Ordered.HIGHEST_PRECEDENCE + 10) protected static class AuthenticationManagerConfiguration extends GlobalAuthenticationConfigurerAdapter { @Autowired @@ -125,12 +121,14 @@ protected static class AuthenticationManagerConfiguration extends GlobalAuthenti @Override public void init(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off - auth.jdbcAuthentication().dataSource(dataSource) - .withUser("dave") - .password("secret") - .roles("USER"); + auth + .jdbcAuthentication().dataSource(dataSource) + .withUser("dave") + .password("secret") + .roles("USER"); // @formatter:on } + } } diff --git a/tests/annotation/jdbc/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/jdbc/src/test/java/demo/AuthorizationCodeProviderTests.java index 984266a9e..40787edad 100755 --- a/tests/annotation/jdbc/src/test/java/demo/AuthorizationCodeProviderTests.java +++ b/tests/annotation/jdbc/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -16,7 +16,6 @@ import static org.junit.Assert.assertTrue; import org.springframework.boot.test.SpringApplicationConfiguration; -import org.springframework.security.crypto.codec.Base64; import sparklr.common.AbstractAuthorizationCodeProviderTests; @@ -26,9 +25,12 @@ @SpringApplicationConfiguration(classes = Application.class) public class AuthorizationCodeProviderTests extends AbstractAuthorizationCodeProviderTests { - protected String getBasicAuthentication() { - // SecurityProperties is used to create a parent authentication manager - return "Basic " + new String(Base64.encode(("dave:secret").getBytes())); + protected String getPassword() { + return "secret"; + } + + protected String getUsername() { + return "dave"; } protected void verifyAuthorizationPage(String page) { diff --git a/tests/annotation/jdbc/src/test/java/demo/ImplicitProviderTests.java b/tests/annotation/jdbc/src/test/java/demo/ImplicitProviderTests.java index 7a8958187..89b5a1ef8 100644 --- a/tests/annotation/jdbc/src/test/java/demo/ImplicitProviderTests.java +++ b/tests/annotation/jdbc/src/test/java/demo/ImplicitProviderTests.java @@ -10,4 +10,12 @@ @SpringApplicationConfiguration(classes=Application.class) public class ImplicitProviderTests extends AbstractImplicitProviderTests { + protected String getPassword() { + return "secret"; + } + + protected String getUsername() { + return "dave"; + } + } diff --git a/tests/annotation/jdbc/src/test/java/demo/RefreshTokenSupportTests.java b/tests/annotation/jdbc/src/test/java/demo/RefreshTokenSupportTests.java index 4ed370eea..299e66005 100644 --- a/tests/annotation/jdbc/src/test/java/demo/RefreshTokenSupportTests.java +++ b/tests/annotation/jdbc/src/test/java/demo/RefreshTokenSupportTests.java @@ -10,4 +10,11 @@ */ @SpringApplicationConfiguration(classes=Application.class) public class RefreshTokenSupportTests extends AbstractRefreshTokenSupportTests { + protected String getPassword() { + return "secret"; + } + + protected String getUsername() { + return "dave"; + } } diff --git a/tests/annotation/jdbc/src/test/java/demo/ResourceOwnerPasswordProviderTests.java b/tests/annotation/jdbc/src/test/java/demo/ResourceOwnerPasswordProviderTests.java index fe219b42a..65c784f57 100644 --- a/tests/annotation/jdbc/src/test/java/demo/ResourceOwnerPasswordProviderTests.java +++ b/tests/annotation/jdbc/src/test/java/demo/ResourceOwnerPasswordProviderTests.java @@ -16,6 +16,14 @@ @SpringApplicationConfiguration(classes = Application.class) public class ResourceOwnerPasswordProviderTests extends AbstractResourceOwnerPasswordProviderTests { + protected String getPassword() { + return "secret"; + } + + protected String getUsername() { + return "dave"; + } + @Test @OAuth2ContextConfiguration(JdbcResourceOwner.class) public void testTokenObtainedWithHeaderAuthenticationAndJdbcUser() throws Exception { diff --git a/tests/annotation/multi/pom.xml b/tests/annotation/multi/pom.xml index 6c96781f5..a2f91c4eb 100644 --- a/tests/annotation/multi/pom.xml +++ b/tests/annotation/multi/pom.xml @@ -2,7 +2,7 @@ 4.0.0 - sparklr-boot-multi + spring-oauth2-tests-multi sparklr-boot-multi Demo project diff --git a/tests/annotation/multi/src/main/java/demo/Application.java b/tests/annotation/multi/src/main/java/demo/Application.java index 62034d623..370460078 100644 --- a/tests/annotation/multi/src/main/java/demo/Application.java +++ b/tests/annotation/multi/src/main/java/demo/Application.java @@ -59,7 +59,8 @@ public void configure(HttpSecurity http) throws Exception { } })); - + resource.setOrder(3); + return resource; } @@ -121,6 +122,13 @@ public void configure(ClientDetailsServiceConfigurer clients) throws Exception { .authorizedGrantTypes("client_credentials", "password") .authorities("ROLE_CLIENT") .scopes("read") + .resourceIds("oauth2/admin") + .secret("secret") + .and() + .withClient("my-other-client-with-secret") + .authorizedGrantTypes("password") + .authorities("ROLE_CLIENT") + .scopes("read", "trust") .resourceIds("oauth2/other") .secret("secret"); // @formatter:on diff --git a/tests/annotation/multi/src/test/java/demo/ResourceOwnerPasswordProviderTests.java b/tests/annotation/multi/src/test/java/demo/ResourceOwnerPasswordProviderTests.java index aa5786098..886c48e28 100644 --- a/tests/annotation/multi/src/test/java/demo/ResourceOwnerPasswordProviderTests.java +++ b/tests/annotation/multi/src/test/java/demo/ResourceOwnerPasswordProviderTests.java @@ -1,6 +1,13 @@ package demo; +import static org.junit.Assert.assertEquals; + +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; import sparklr.common.AbstractResourceOwnerPasswordProviderTests; @@ -10,4 +17,19 @@ @SpringApplicationConfiguration(classes=Application.class) public class ResourceOwnerPasswordProviderTests extends AbstractResourceOwnerPasswordProviderTests { + @Test + @OAuth2ContextConfiguration(OtherResourceOwner.class) + public void testTokenObtainedWithHeaderAuthenticationAndOtherResource() throws Exception { + assertEquals(HttpStatus.OK, http.getStatusCode("/")); + } + + static class OtherResourceOwner extends ResourceOwner implements DoNotOverride { + public OtherResourceOwner(Object target) { + super(target); + setClientId("my-other-client-with-secret"); + setClientSecret("secret"); + setScope(Arrays.asList("trust")); + } + } + } From 40f8073c5e0f0d5450c5a5f53c470ddd436f3306 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 15 Oct 2014 16:52:22 +0100 Subject: [PATCH 318/831] Update README.md --- tests/annotation/resource/README.md | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/tests/annotation/resource/README.md b/tests/annotation/resource/README.md index acb89fbf6..c4f6a5ae7 100644 --- a/tests/annotation/resource/README.md +++ b/tests/annotation/resource/README.md @@ -1,18 +1,6 @@ This project shows what you can do with the minimum configuration to -set up an Authorization Server and Resource Server. +set up a Resource Server. -For the Authorization Server you need to `@EnableAuthorizationServer` -and also configure at least one client registration -(`OAuth2ClientDetails`). You can see this is the bulk of -`Application.java`. - -An `AuthenticationManager` is created by Spring Boot (it has a single -user, named "user", with password "password", per -`application.yml`). It is needed in the Authorization Server to -provide authentication for the Resource Owner Password grant type. - -For the Resource Server all that is needed is the -`@EnableResourceServer` annotation. By default it protects all -resources that are not explicitly ignored and not exposed by the -`AuthorizationEndpoint` (if there is an Authorization Server in the -same application). +All that is needed is the +`@EnableResourceServer` annotation and a `TokenStore`. By default it protects all +resources that are not explicitly ignored. From 589dd04205b23aa13f258f4330acd0e30c969220 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Sun, 19 Oct 2014 11:28:39 +0100 Subject: [PATCH 319/831] Upgrade Spring and Spring Security --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 644ce27d6..dbc290555 100644 --- a/pom.xml +++ b/pom.xml @@ -17,8 +17,8 @@ UTF-8 - 4.0.3.RELEASE - 3.2.3.RELEASE + 4.0.7.RELEASE + 3.2.5.RELEASE 1.6 From 45505c6ab815a8c282d6f566eb65a9b5da676f26 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Sun, 19 Oct 2014 16:34:17 +0100 Subject: [PATCH 320/831] Make DefaultTokenServices a @Bean It's a bit awkward to do this because it makes it harder to back off if the user provides his own @Bean, but it's worth it for the JDBC case because the AuthorizationServerTokenServices needs to be @Transactional in that case. If the user only provides a JDBC TokenStore the system now should be more resilient to duplicate tokens under load. Fixes gh-276 --- ...orizationServerEndpointsConfiguration.java | 53 ++++++++----- .../ResourceServerConfiguration.java | 42 ++++++++-- ...uthorizationServerEndpointsConfigurer.java | 29 +++++-- .../provider/token/DefaultTokenServices.java | 2 + ...AuthorizationServerConfigurationTests.java | 76 +++++++++++++------ .../ResourceServerConfigurationTests.java | 46 +++++++++++ tests/annotation/multi/pom.xml | 3 +- 7 files changed, 194 insertions(+), 57 deletions(-) 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 15d954fdb..2713290bc 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 @@ -43,9 +43,9 @@ import org.springframework.security.oauth2.provider.endpoint.TokenKeyEndpoint; import org.springframework.security.oauth2.provider.endpoint.WhitelabelApprovalEndpoint; import org.springframework.security.oauth2.provider.endpoint.WhitelabelErrorEndpoint; +import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; import org.springframework.security.oauth2.provider.token.ConsumerTokenServices; 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.JwtAccessTokenConverter; /** @@ -56,13 +56,6 @@ @Import(TokenKeyEndpointRegistrar.class) public class AuthorizationServerEndpointsConfiguration { - /** - * The static bean name for a TokenStore if any. If the use creates his own bean with the same name, or else an - * ApprovalStore named {@link #APPROVAL_STORE_BEAN_NAME}, then Spring will create an {@link InMemoryTokenStore}. - * - */ - public static final String TOKEN_STORE_BEAN_NAME = "tokenStore"; - private AuthorizationServerEndpointsConfigurer endpoints = new AuthorizationServerEndpointsConfigurer(); @Autowired @@ -87,7 +80,7 @@ public void init() { @Bean public AuthorizationEndpoint authorizationEndpoint() throws Exception { AuthorizationEndpoint authorizationEndpoint = new AuthorizationEndpoint(); - FrameworkEndpointHandlerMapping mapping = endpoints.getFrameworkEndpointHandlerMapping(); + FrameworkEndpointHandlerMapping mapping = getEndpoints().getFrameworkEndpointHandlerMapping(); authorizationEndpoint.setUserApprovalPage(extractPath(mapping, "/oauth/confirm_access")); authorizationEndpoint.setErrorPage(extractPath(mapping, "/oauth/error")); authorizationEndpoint.setTokenGranter(tokenGranter()); @@ -111,8 +104,8 @@ public TokenEndpoint tokenEndpoint() throws Exception { @Bean public CheckTokenEndpoint checkTokenEndpoint() { - CheckTokenEndpoint endpoint = new CheckTokenEndpoint(endpoints.getResourceServerTokenServices()); - endpoint.setAccessTokenConverter(endpoints.getAccessTokenConverter()); + CheckTokenEndpoint endpoint = new CheckTokenEndpoint(getEndpoints().getResourceServerTokenServices()); + endpoint.setAccessTokenConverter(getEndpoints().getAccessTokenConverter()); return endpoint; } @@ -128,37 +121,56 @@ public WhitelabelErrorEndpoint whitelabelErrorEndpoint() { @Bean public FrameworkEndpointHandlerMapping oauth2EndpointHandlerMapping() throws Exception { - return endpoints.getFrameworkEndpointHandlerMapping(); + return getEndpoints().getFrameworkEndpointHandlerMapping(); } @Bean public ConsumerTokenServices consumerTokenServices() throws Exception { - return endpoints.getConsumerTokenServices(); + return getEndpoints().getConsumerTokenServices(); + } + + /** + * This needs to be a @Bean so that it can be @Transactional (in case the token store + * supports them). If you are overriding the token services in an {@link AuthorizationServerConfigurer} consider + * making it a @Bean for the same reason (assuming you need transactions, e.g. for a JDBC token store). + * + * @return an AuthorizationServerTokenServices + */ + @Bean + public AuthorizationServerTokenServices defaultAuthorizationServerTokenServices() { + return endpoints.getDefaultAuthorizationServerTokenServices(); } @Bean public TokenStore tokenStore() throws Exception { - return endpoints.getTokenStore(); + return getEndpoints().getTokenStore(); + } + + private AuthorizationServerEndpointsConfigurer getEndpoints() { + if (!endpoints.isTokenServicesOverride()) { + endpoints.tokenServices(defaultAuthorizationServerTokenServices()); + } + return endpoints; } private OAuth2RequestFactory oauth2RequestFactory() throws Exception { - return endpoints.getOAuth2RequestFactory(); + return getEndpoints().getOAuth2RequestFactory(); } private UserApprovalHandler userApprovalHandler() throws Exception { - return endpoints.getUserApprovalHandler(); + return getEndpoints().getUserApprovalHandler(); } private OAuth2RequestValidator oauth2RequestValidator() throws Exception { - return endpoints.getOAuth2RequestValidator(); + return getEndpoints().getOAuth2RequestValidator(); } private AuthorizationCodeServices authorizationCodeServices() throws Exception { - return endpoints.getAuthorizationCodeServices(); + return getEndpoints().getAuthorizationCodeServices(); } private TokenGranter tokenGranter() throws Exception { - return endpoints.getTokenGranter(); + return getEndpoints().getTokenGranter(); } private String extractPath(FrameworkEndpointHandlerMapping mapping, String page) { @@ -176,7 +188,8 @@ protected static class TokenKeyEndpointRegistrar implements BeanDefinitionRegist @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { - String[] names = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, JwtAccessTokenConverter.class); + String[] names = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, + JwtAccessTokenConverter.class); if (names.length > 0) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(TokenKeyEndpoint.class); builder.addConstructorArgReference(names[0]); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java index a3168a6e5..8ccfaae28 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java @@ -20,7 +20,9 @@ import javax.servlet.http.HttpServletRequest; +import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import org.springframework.security.config.annotation.web.builders.HttpSecurity; @@ -41,14 +43,17 @@ */ @Configuration public class ResourceServerConfiguration extends WebSecurityConfigurerAdapter implements Ordered { - + private int order = 3; @Autowired(required = false) private TokenStore tokenStore; @Autowired(required = false) - private ResourceServerTokenServices tokenServices; + private ResourceServerTokenServices[] tokenServices; + + @Autowired + private ApplicationContext context; private List configurers = Collections.emptyList(); @@ -56,7 +61,7 @@ public class ResourceServerConfiguration extends WebSecurityConfigurerAdapter im @Autowired(required = false) private AuthorizationServerEndpointsConfiguration endpoints; - + @Override public int getOrder() { return order; @@ -132,8 +137,9 @@ protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests().expressionHandler(new OAuth2WebSecurityExpressionHandler()); ResourceServerSecurityConfigurer resources = new ResourceServerSecurityConfigurer(); http.apply(resources); - if (tokenServices != null) { - resources.tokenServices(tokenServices); + ResourceServerTokenServices services = resolveTokenServices(); + if (services != null) { + resources.tokenServices(services); } else { if (tokenStore != null) { @@ -145,4 +151,30 @@ protected void configure(HttpSecurity http) throws Exception { } } + private ResourceServerTokenServices resolveTokenServices() { + if (tokenServices == null || tokenServices.length==0) { + return null; + } + if (tokenServices.length == 1) { + return tokenServices[0]; + } + if (tokenServices.length == 2 && tokenServices[0] == tokenServices[1]) { + return tokenServices[0]; + } + try { + TokenServicesConfiguration bean = context.getAutowireCapableBeanFactory().createBean( + TokenServicesConfiguration.class); + return bean.services; + } + catch (BeanCreationException e) { + throw new IllegalStateException( + "Could not wire ResourceServerTokenServices: please create a bean definition and mark it as @Primary."); + } + } + + private static class TokenServicesConfiguration { + @Autowired + private ResourceServerTokenServices services; + } + } 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 03215746f..14e448e9d 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 @@ -106,6 +106,10 @@ public final class AuthorizationServerEndpointsConfigurer { private List interceptors = new ArrayList(); + private DefaultTokenServices defaultTokenServices; + + private boolean tokenServicesOverride = false; + public AuthorizationServerTokenServices getTokenServices() { return tokenServices; } @@ -159,8 +163,13 @@ public AuthorizationServerEndpointsConfigurer accessTokenConverter(AccessTokenCo public AuthorizationServerEndpointsConfigurer tokenServices(AuthorizationServerTokenServices tokenServices) { this.tokenServices = tokenServices; + this.tokenServicesOverride = true; return this; } + + public boolean isTokenServicesOverride() { + return tokenServicesOverride; + } public AuthorizationServerEndpointsConfigurer userApprovalHandler(UserApprovalHandler approvalHandler) { this.userApprovalHandler = approvalHandler; @@ -287,7 +296,7 @@ private ResourceServerTokenServices resourceTokenServices() { if (tokenServices instanceof ResourceServerTokenServices) { return (ResourceServerTokenServices) tokenServices; } - resourceTokenServices = createTokenServices(); + resourceTokenServices = createDefaultTokenServices(); } return resourceTokenServices; } @@ -297,7 +306,7 @@ private ConsumerTokenServices consumerTokenServices() { if (tokenServices instanceof ConsumerTokenServices) { return (ConsumerTokenServices) tokenServices; } - consumerTokenServices = createTokenServices(); + consumerTokenServices = createDefaultTokenServices(); } return consumerTokenServices; } @@ -306,20 +315,28 @@ private AuthorizationServerTokenServices tokenServices() { if (tokenServices != null) { return tokenServices; } - this.tokenServices = createTokenServices(); + this.tokenServices = createDefaultTokenServices(); return tokenServices; } + + public AuthorizationServerTokenServices getDefaultAuthorizationServerTokenServices() { + if (defaultTokenServices !=null) { + return defaultTokenServices; + } + this.defaultTokenServices = createDefaultTokenServices(); + return this.defaultTokenServices; + } - private DefaultTokenServices createTokenServices() { + private DefaultTokenServices createDefaultTokenServices() { DefaultTokenServices tokenServices = new DefaultTokenServices(); tokenServices.setTokenStore(tokenStore()); tokenServices.setSupportRefreshToken(true); tokenServices.setClientDetailsService(clientDetailsService()); - tokenServices.setTokenEnhancer(tokenEnchancer()); + tokenServices.setTokenEnhancer(tokenEnhancer()); return tokenServices; } - private TokenEnhancer tokenEnchancer() { + private TokenEnhancer tokenEnhancer() { if (this.tokenEnhancer == null && accessTokenConverter() instanceof JwtAccessTokenConverter) { tokenEnhancer = (TokenEnhancer) accessTokenConverter; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java index 50989c38e..03f4d8962 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java @@ -33,6 +33,7 @@ import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.TokenRequest; +import org.springframework.transaction.annotation.Transactional; import org.springframework.util.Assert; /** @@ -47,6 +48,7 @@ * @author Luke Taylor * @author Dave Syer */ +@Transactional public class DefaultTokenServices implements AuthorizationServerTokenServices, ResourceServerTokenServices, ConsumerTokenServices, InitializingBean { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java index 98f8eb3d1..9ee92a72e 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java @@ -12,6 +12,16 @@ */ package org.springframework.security.oauth2.config.annotation; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import javax.sql.DataSource; + import org.junit.After; import org.junit.Rule; import org.junit.Test; @@ -52,13 +62,6 @@ import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; -import javax.sql.DataSource; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import static org.junit.Assert.*; - /** * @author Dave Syer * @@ -77,12 +80,13 @@ public class AuthorizationServerConfigurationTests { public static List parameters() { return Arrays.asList( // @formatter:off new Object[] { BeanCreationException.class, new Class[] { AuthorizationServerUnconfigured.class } }, - new Object[] { BeanCreationException.class, new Class[] { AuthorizationServerCycle.class } }, + new Object[] { null, new Class[] { AuthorizationServerCycle.class } }, new Object[] { null, new Class[] { AuthorizationServerVanilla.class } }, new Object[] { null, new Class[] { AuthorizationServerDisableApproval.class } }, new Object[] { null, new Class[] { AuthorizationServerExtras.class } }, new Object[] { null, new Class[] { AuthorizationServerJdbc.class } }, new Object[] { null, new Class[] { AuthorizationServerJwt.class } }, + new Object[] { null, new Class[] { AuthorizationServerWithTokenServices.class } }, new Object[] { null, new Class[] { AuthorizationServerApproval.class } }, new Object[] { BeanCreationException.class, new Class[] { AuthorizationServerTypes.class } } // @formatter:on @@ -178,7 +182,7 @@ protected static class AuthorizationServerCycle extends AuthorizationServerConfi @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { - endpoints.tokenServices(tokenServices); // cycle leads to null here + endpoints.tokenServices(tokenServices); // cycle can lead to null here } @Override @@ -192,7 +196,7 @@ public void configure(ClientDetailsServiceConfigurer clients) throws Exception { @Override public void run() { - assertNull(tokenServices); + assertNotNull(tokenServices); } } @@ -322,34 +326,58 @@ public DataSource dataSource() { @EnableAuthorizationServer protected static class AuthorizationServerJwt extends AuthorizationServerConfigurerAdapter { - @Autowired - private ApplicationContext context; + @Override + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + endpoints.tokenStore(tokenStore()).tokenEnhancer(jwtTokenEnhancer()); + } + + @Bean + public TokenStore tokenStore() { + return new JwtTokenStore(jwtTokenEnhancer()); + } + + @Bean + protected JwtAccessTokenConverter jwtTokenEnhancer() { + return new JwtAccessTokenConverter(); + } + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + // @formatter:off + clients.inMemory() + .withClient("my-trusted-client") + .authorizedGrantTypes("password"); + // @formatter:on + } + + } + @Configuration + @EnableWebMvcSecurity + @EnableAuthorizationServer + protected static class AuthorizationServerWithTokenServices extends AuthorizationServerConfigurerAdapter { + @Autowired private ClientDetailsService clientDetailsService; @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { - endpoints.tokenServices(tokenServices()); + endpoints.tokenServices(tokenServices()).tokenStore(tokenStore()); } @Bean public DefaultTokenServices tokenServices() { - DefaultTokenServices services = new DefaultTokenServices(); - services.setClientDetailsService(clientDetailsService); - services.setTokenEnhancer(jwtTokenEnhancer()); - services.setTokenStore(tokenStore()); - return services; + DefaultTokenServices tokenServices = new DefaultTokenServices(); + tokenServices.setTokenStore(tokenStore()); + tokenServices.setAccessTokenValiditySeconds(300); + tokenServices.setRefreshTokenValiditySeconds(30000); + tokenServices.setClientDetailsService(clientDetailsService); + return tokenServices; } @Bean public TokenStore tokenStore() { - return new JwtTokenStore(jwtTokenEnhancer()); - } - - @Bean - protected JwtAccessTokenConverter jwtTokenEnhancer() { - return new JwtAccessTokenConverter(); + return new InMemoryTokenStore(); } @Override diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java index 53be0955b..7dd15689c 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java @@ -27,9 +27,12 @@ import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.client.BaseClientDetails; +import org.springframework.security.oauth2.provider.client.InMemoryClientDetailsService; +import org.springframework.security.oauth2.provider.token.DefaultTokenServices; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore; import org.springframework.test.web.servlet.MockMvc; @@ -74,6 +77,20 @@ public void testDefaults() throws Exception { context.close(); } + @Test + public void testCustomTokenServices() throws Exception { + tokenStore.storeAccessToken(token, authentication); + AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); + context.setServletContext(new MockServletContext()); + context.register(TokenServicesContext.class); + context.refresh(); + MockMvc mvc = MockMvcBuilders.webAppContextSetup(context) + .addFilters(new DelegatingFilterProxy(context.getBean("springSecurityFilterChain", Filter.class))) + .build(); + mvc.perform(MockMvcRequestBuilders.get("/")).andExpect(MockMvcResultMatchers.status().isUnauthorized()); + context.close(); + } + @Configuration @EnableResourceServer @EnableWebSecurity @@ -89,4 +106,33 @@ public TokenStore tokenStore() { } } + @Configuration + @EnableResourceServer + @EnableWebSecurity + protected static class TokenServicesContext { + + @Bean + protected ClientDetailsService clientDetailsService() { + return new InMemoryClientDetailsService(); + } + + @Autowired + protected void init(AuthenticationManagerBuilder builder) { + builder.authenticationProvider(new AnonymousAuthenticationProvider("default")); + } + + @Bean + public DefaultTokenServices tokenServices() { + DefaultTokenServices tokenServices = new DefaultTokenServices(); + tokenServices.setTokenStore(tokenStore()); + tokenServices.setClientDetailsService(clientDetailsService()); + return tokenServices; + } + + @Bean + public TokenStore tokenStore() { + return tokenStore; + } + } + } \ No newline at end of file diff --git a/tests/annotation/multi/pom.xml b/tests/annotation/multi/pom.xml index a2f91c4eb..280903680 100644 --- a/tests/annotation/multi/pom.xml +++ b/tests/annotation/multi/pom.xml @@ -3,8 +3,7 @@ 4.0.0 spring-oauth2-tests-multi - - sparklr-boot-multi + spring-oauth2-tests-multi Demo project From 177305ddcdc26fe82646e0f010c956860ffe0388 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Sun, 19 Oct 2014 16:40:59 +0100 Subject: [PATCH 321/831] Update context path for tonr2 (fixes gh-250, fixes gh-280) --- samples/oauth2/tonr/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index da80d2cf2..358ca561d 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -51,6 +51,7 @@ run + /tonr2 true From 9d21b2aa3d8f3f1a4d0da4551355520dc7d7b72d Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 3 Nov 2014 15:18:06 +0000 Subject: [PATCH 322/831] Revert change to work around issue in Spring Boot --- ...uthorizationServerEndpointsConfigurer.java | 26 +------------------ .../jdbc/src/main/java/demo/Application.java | 12 ++++++++- 2 files changed, 12 insertions(+), 26 deletions(-) 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 14e448e9d..92e44d755 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 @@ -21,9 +21,6 @@ import java.util.Map; import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.AuthenticationException; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.CompositeTokenGranter; import org.springframework.security.oauth2.provider.OAuth2RequestFactory; @@ -210,10 +207,7 @@ public AuthorizationServerEndpointsConfigurer addInterceptor(WebRequestIntercept } /** - * The AuthenticationManager for the password grant. Use this method only if you know the AuthenticationManager is - * fully initialized (because you created it yourself). If you created it elsewhere using an - * AuthenticationManagerBuilder, then do not use this method (use - * {@link #authenticationManager(AuthenticationManagerBuilder)} instead). + * The AuthenticationManager for the password grant. * * @param builder an AuthenticationManager, fully initialized * @return this for a fluent style @@ -223,24 +217,6 @@ public AuthorizationServerEndpointsConfigurer authenticationManager(Authenticati return this; } - /** - * The AuthenticationManager for the password grant can be lazily initialized to avoid a cascade of early - * initialization in the enclosing BeanFactory. - * - * @param builder an AuthenticationManagerBuilder - * @return this for a fluent style - */ - public AuthorizationServerEndpointsConfigurer authenticationManager(AuthenticationManagerBuilder builder) { - final AuthenticationManagerBuilder auth = builder; - this.authenticationManager = new AuthenticationManager() { - @Override - public Authentication authenticate(Authentication authentication) throws AuthenticationException { - return auth.getOrBuild().authenticate(authentication); - } - }; - return this; - } - public AuthorizationServerEndpointsConfigurer tokenGranter(TokenGranter tokenGranter) { this.tokenGranter = tokenGranter; return this; diff --git a/tests/annotation/jdbc/src/main/java/demo/Application.java b/tests/annotation/jdbc/src/main/java/demo/Application.java index 6de303fdb..aa76bbf2c 100644 --- a/tests/annotation/jdbc/src/main/java/demo/Application.java +++ b/tests/annotation/jdbc/src/main/java/demo/Application.java @@ -7,9 +7,12 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter; import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; @@ -80,7 +83,14 @@ protected AuthorizationCodeServices authorizationCodeServices() { @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.authorizationCodeServices(authorizationCodeServices()) - .authenticationManager(auth).tokenStore(tokenStore()).approvalStoreDisabled(); + .authenticationManager(new AuthenticationManager() { + // TODO: unwind this workaround for Spring Boot issue (when 1.1.9 is out) + @Override + public Authentication authenticate(Authentication authentication) + throws AuthenticationException { + return auth.getOrBuild().authenticate(authentication); + } + }).tokenStore(tokenStore()).approvalStoreDisabled(); } @Override From 178f3c5d7f2b570c05c524fcc322e00364cf012b Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 4 Nov 2014 11:09:41 +0000 Subject: [PATCH 323/831] Enhance OAuth2AuthenticationToken details with upstream details Adds a new property to OAuth2AuthenticationDetails (decodedDetails) to hold the AuthenticationDetails (if any) loaded by the ResourceServerTokenServices. In this way we can preserve the existing OAuth2AuthenticationDetails behaviour (in particular the access token value which people rely on) but retain all the data from the ResourceServerTokenServices. Fixes gh-285 --- .../OAuth2AuthenticationDetails.java | 22 +++++++++++++++++ .../OAuth2AuthenticationManager.java | 5 ++++ .../OAuth2AuthenticationManagerTests.java | 24 +++++++++++++++---- 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationDetails.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationDetails.java index f90695fa9..ac398d9a2 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationDetails.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationDetails.java @@ -38,6 +38,8 @@ public class OAuth2AuthenticationDetails implements Serializable { private final String tokenValue; private final String display; + + private Object decodedDetails; /** * Records the access token value and remote address and will also set the session Id if a session already exists @@ -97,6 +99,26 @@ public String getSessionId() { return sessionId; } + /** + * The authentication details obtained by decoding the access token + * if available. + * + * @return the decodedDetails if available (default null) + */ + public Object getDecodedDetails() { + return decodedDetails; + } + + /** + * The authentication details obtained by decoding the access token + * if available. + * + * @param decodedDetails the decodedDetails to set + */ + public void setDecodedDetails(Object decodedDetails) { + this.decodedDetails = decodedDetails; + } + @Override public String toString() { return display; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java index 3d3730b0d..4e586aa5b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java @@ -89,6 +89,11 @@ public Authentication authenticate(Authentication authentication) throws Authent checkClientDetails(auth); + if (authentication.getDetails() instanceof OAuth2AuthenticationDetails) { + OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) authentication.getDetails(); + // Preserve the authentication details if any from the one loaded by token services + details.setDecodedDetails(auth.getDetails()); + } auth.setDetails(authentication.getDetails()); auth.setAuthenticated(true); return auth; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManagerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManagerTests.java index 9cafecbd8..839eb4b0f 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManagerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManagerTests.java @@ -11,13 +11,13 @@ * specific language governing permissions and limitations under the License. */ - package org.springframework.security.oauth2.provider.authentication; import static org.junit.Assert.assertEquals; import org.junit.Test; import org.mockito.Mockito; +import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.provider.OAuth2Authentication; @@ -32,13 +32,14 @@ public class OAuth2AuthenticationManagerTests { private OAuth2AuthenticationManager manager = new OAuth2AuthenticationManager(); - + private ResourceServerTokenServices tokenServices = Mockito.mock(ResourceServerTokenServices.class); private Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala"); - private OAuth2Authentication authentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request("foo", false), userAuthentication); - + private OAuth2Authentication authentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request( + "foo", false), userAuthentication); + { manager.setTokenServices(tokenServices); } @@ -53,4 +54,19 @@ public void testDetailsAdded() throws Exception { assertEquals("BAR", result.getDetails()); } + @Test + public void testDetailsEnhanced() throws Exception { + authentication.setDetails("DETAILS"); + Mockito.when(tokenServices.loadAuthentication("FOO")).thenReturn(authentication); + PreAuthenticatedAuthenticationToken request = new PreAuthenticatedAuthenticationToken("FOO", ""); + MockHttpServletRequest servletRequest = new MockHttpServletRequest(); + servletRequest.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_VALUE, "BAR"); + OAuth2AuthenticationDetails details = new OAuth2AuthenticationDetails(servletRequest); + request.setDetails(details); + Authentication result = manager.authenticate(request); + assertEquals(authentication, result); + assertEquals("BAR", ((OAuth2AuthenticationDetails) result.getDetails()).getTokenValue()); + assertEquals("DETAILS", ((OAuth2AuthenticationDetails) result.getDetails()).getDecodedDetails()); + } + } From b31ab531dae34e174a7311c23d89958fc7d11778 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 4 Nov 2014 11:31:04 +0000 Subject: [PATCH 324/831] Add request parameters as "details" in password grant The AuthenticationManager in the password grant now has access to the request parameters (via Authentication.getDetails()). It still has to support UsernamePasswordAuthenticationToken, so no existing code requires changes. Note that the request parameters are available in the OAuth2AuthenticationToken anyway, so the AuthenticationManager does *not* need to copy the details to a successfully authenticated result (although a ProviderManager will already do that by default). Fixes gh-284 --- .../ResourceOwnerPasswordTokenGranter.java | 2 + ...esourceOwnerPasswordTokenGranterTests.java | 101 +++++++++++------- 2 files changed, 62 insertions(+), 41 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java index d9a96a59d..c38f2e88e 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java @@ -18,6 +18,7 @@ import java.util.Map; +import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.authentication.AccountStatusException; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; @@ -57,6 +58,7 @@ protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, Tok String password = parameters.get("password"); Authentication userAuth = new UsernamePasswordAuthenticationToken(username, password); + ((AbstractAuthenticationToken) userAuth).setDetails(parameters); try { userAuth = authenticationManager.authenticate(userAuth); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranterTests.java index 8cccf3299..6f7ac86c0 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranterTests.java @@ -12,6 +12,8 @@ */ package org.springframework.security.oauth2.provider.password; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.util.Arrays; @@ -26,6 +28,7 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.exceptions.InvalidClientException; @@ -47,16 +50,13 @@ */ public class ResourceOwnerPasswordTokenGranterTests { - private Authentication validUser = new UsernamePasswordAuthenticationToken( - "foo", "bar", + private Authentication validUser = new UsernamePasswordAuthenticationToken("foo", "bar", Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"))); - private BaseClientDetails client = new BaseClientDetails("foo", "resource", - "scope", "password", "ROLE_USER"); + private BaseClientDetails client = new BaseClientDetails("foo", "resource", "scope", "password", "ROLE_USER"); private AuthenticationManager authenticationManager = new AuthenticationManager() { - public Authentication authenticate(Authentication authentication) - throws AuthenticationException { + public Authentication authenticate(Authentication authentication) throws AuthenticationException { return validUser; } }; @@ -64,14 +64,12 @@ public Authentication authenticate(Authentication authentication) private DefaultTokenServices providerTokenServices = new DefaultTokenServices(); private ClientDetailsService clientDetailsService = new ClientDetailsService() { - public ClientDetails loadClientByClientId(String clientId) - throws OAuth2Exception { + public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exception { return client; } }; - private OAuth2RequestFactory requestFactory = new DefaultOAuth2RequestFactory( - clientDetailsService); + private OAuth2RequestFactory requestFactory = new DefaultOAuth2RequestFactory(clientDetailsService); private TokenRequest tokenRequest; @@ -86,63 +84,84 @@ public ResourceOwnerPasswordTokenGranterTests() { parameters.put("password", "bar"); parameters.put("client_id", clientId); - tokenRequest = requestFactory.createTokenRequest(parameters, - clientDetails); + tokenRequest = requestFactory.createTokenRequest(parameters, clientDetails); } @Test public void testSunnyDay() { - ResourceOwnerPasswordTokenGranter granter = new ResourceOwnerPasswordTokenGranter( - authenticationManager, providerTokenServices, - clientDetailsService, requestFactory); + ResourceOwnerPasswordTokenGranter granter = new ResourceOwnerPasswordTokenGranter(authenticationManager, + providerTokenServices, clientDetailsService, requestFactory); OAuth2AccessToken token = granter.grant("password", tokenRequest); - OAuth2Authentication authentication = providerTokenServices - .loadAuthentication(token.getValue()); + OAuth2Authentication authentication = providerTokenServices.loadAuthentication(token.getValue()); assertTrue(authentication.isAuthenticated()); } + @Test + public void testPasswordRemoved() { + ResourceOwnerPasswordTokenGranter granter = new ResourceOwnerPasswordTokenGranter(authenticationManager, + providerTokenServices, clientDetailsService, requestFactory); + OAuth2AccessToken token = granter.grant("password", tokenRequest); + OAuth2Authentication authentication = providerTokenServices.loadAuthentication(token.getValue()); + assertNotNull(authentication.getOAuth2Request().getRequestParameters().get("username")); + assertNull(authentication.getOAuth2Request().getRequestParameters().get("password")); + } + + @Test + public void testExtraParameters() { + authenticationManager = new AuthenticationManager() { + @Override + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + if (authentication instanceof UsernamePasswordAuthenticationToken) { + UsernamePasswordAuthenticationToken user = (UsernamePasswordAuthenticationToken) authentication; + user = new UsernamePasswordAuthenticationToken(user.getPrincipal(), "N/A", + AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); + assertNotNull(authentication.getDetails()); + return user; + } + return authentication; + } + }; + ResourceOwnerPasswordTokenGranter granter = new ResourceOwnerPasswordTokenGranter(authenticationManager, + providerTokenServices, clientDetailsService, requestFactory); + OAuth2AccessToken token = granter.grant("password", tokenRequest); + OAuth2Authentication authentication = providerTokenServices.loadAuthentication(token.getValue()); + assertTrue(authentication.isAuthenticated()); + assertNull(authentication.getUserAuthentication().getDetails()); + } + @Test(expected = InvalidGrantException.class) public void testBadCredentials() { - ResourceOwnerPasswordTokenGranter granter = new ResourceOwnerPasswordTokenGranter( - new AuthenticationManager() { - public Authentication authenticate( - Authentication authentication) - throws AuthenticationException { - throw new BadCredentialsException("test"); - } - }, providerTokenServices, clientDetailsService, requestFactory); + ResourceOwnerPasswordTokenGranter granter = new ResourceOwnerPasswordTokenGranter(new AuthenticationManager() { + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + throw new BadCredentialsException("test"); + } + }, providerTokenServices, clientDetailsService, requestFactory); granter.grant("password", tokenRequest); } @Test(expected = InvalidClientException.class) public void testGrantTypeNotSupported() { - ResourceOwnerPasswordTokenGranter granter = new ResourceOwnerPasswordTokenGranter( - authenticationManager, providerTokenServices, - clientDetailsService, requestFactory); - client.setAuthorizedGrantTypes(Collections - .singleton("client_credentials")); + ResourceOwnerPasswordTokenGranter granter = new ResourceOwnerPasswordTokenGranter(authenticationManager, + providerTokenServices, clientDetailsService, requestFactory); + client.setAuthorizedGrantTypes(Collections.singleton("client_credentials")); granter.grant("password", tokenRequest); } @Test(expected = InvalidGrantException.class) public void testAccountLocked() { - ResourceOwnerPasswordTokenGranter granter = new ResourceOwnerPasswordTokenGranter( - new AuthenticationManager() { - public Authentication authenticate( - Authentication authentication) - throws AuthenticationException { - throw new LockedException("test"); - } - }, providerTokenServices, clientDetailsService, requestFactory); + ResourceOwnerPasswordTokenGranter granter = new ResourceOwnerPasswordTokenGranter(new AuthenticationManager() { + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + throw new LockedException("test"); + } + }, providerTokenServices, clientDetailsService, requestFactory); granter.grant("password", tokenRequest); } @Test(expected = InvalidGrantException.class) public void testUnauthenticated() { validUser = new UsernamePasswordAuthenticationToken("foo", "bar"); - ResourceOwnerPasswordTokenGranter granter = new ResourceOwnerPasswordTokenGranter( - authenticationManager, providerTokenServices, - clientDetailsService, requestFactory); + ResourceOwnerPasswordTokenGranter granter = new ResourceOwnerPasswordTokenGranter(authenticationManager, + providerTokenServices, clientDetailsService, requestFactory); granter.grant("password", tokenRequest); } From e526ddb9a6abf6e1ba5d66d06dc5a95e5c61d465 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 4 Nov 2014 22:00:33 +0000 Subject: [PATCH 325/831] Protect password from leaking downstream To prevent the password leaking downstream in a password grant it can be removed from the authentcation details. Affects only the last commit (not released). --- .../provider/password/ResourceOwnerPasswordTokenGranter.java | 5 ++++- .../password/ResourceOwnerPasswordTokenGranterTests.java | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java index c38f2e88e..b556179fc 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java @@ -16,6 +16,7 @@ package org.springframework.security.oauth2.provider.password; +import java.util.LinkedHashMap; import java.util.Map; import org.springframework.security.authentication.AbstractAuthenticationToken; @@ -53,9 +54,11 @@ public ResourceOwnerPasswordTokenGranter(AuthenticationManager authenticationMan @Override protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) { - Map parameters = tokenRequest.getRequestParameters(); + Map parameters = new LinkedHashMap(tokenRequest.getRequestParameters()); String username = parameters.get("username"); String password = parameters.get("password"); + // Protect from downstream leaks of password + parameters.remove("password"); Authentication userAuth = new UsernamePasswordAuthenticationToken(username, password); ((AbstractAuthenticationToken) userAuth).setDetails(parameters); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranterTests.java index 6f7ac86c0..160669744 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranterTests.java @@ -115,7 +115,9 @@ public Authentication authenticate(Authentication authentication) throws Authent UsernamePasswordAuthenticationToken user = (UsernamePasswordAuthenticationToken) authentication; user = new UsernamePasswordAuthenticationToken(user.getPrincipal(), "N/A", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); - assertNotNull(authentication.getDetails()); + @SuppressWarnings("unchecked") + Map details = (Map) authentication.getDetails(); + assertNull(details.get("password")); return user; } return authentication; From 21d59959f8ba131f32c8a8dcea20bde30a2b6e57 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 5 Nov 2014 13:14:36 +0000 Subject: [PATCH 326/831] Save Authentication in case of changes after checking existing token When the DefaultTokenServices are used to create an AccessToken from a Authentication (e.g. in a token grant) and the AccessToken already exists, it is looked up based on (typically) a subset of its full properties (e.g. userid and client id and scopes). Since the other properties might have changed since the token was created, it makes sense to ask the TokenStore to store the new Authentication. Fixes gh-283 --- .../provider/token/DefaultTokenServices.java | 2 + ...ltTokenServicesAuthoritiesChangeTests.java | 118 ++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesAuthoritiesChangeTests.java diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java index 03f4d8962..277c8d760 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java @@ -89,6 +89,8 @@ public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication) tokenStore.removeAccessToken(existingAccessToken); } else { + // Re-store the access token in case the authentication has changed + tokenStore.storeAccessToken(existingAccessToken, authentication); return existingAccessToken; } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesAuthoritiesChangeTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesAuthoritiesChangeTests.java new file mode 100644 index 000000000..48edeb1c2 --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesAuthoritiesChangeTests.java @@ -0,0 +1,118 @@ +/* + * Copyright 20013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.springframework.security.oauth2.provider.token; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; +import java.util.Collections; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.RequestTokenFactory; +import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore; + +/** + * @author Ismael Gomes + * + */ +public class DefaultTokenServicesAuthoritiesChangeTests { + + private DefaultTokenServices services; + + private InMemoryTokenStore tokenStore = new InMemoryTokenStore(); + + @Rule + public ExpectedException expected = ExpectedException.none(); + + @Before + public void setUp() throws Exception { + services = new DefaultTokenServices(); + services.setTokenStore(tokenStore); + services.setSupportRefreshToken(true); + services.afterPropertiesSet(); + } + + // This test will fail + @Test + public void testChangeAuthoritiesAuthenticationTokenFail() throws Exception { + + TestChangeAuthentication testAuthentication = new TestChangeAuthentication("test2", false, + new SimpleGrantedAuthority("USER")); + OAuth2Authentication oauth2Authentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request( + "id", false, Collections.singleton("read")), testAuthentication); + + OAuth2AccessToken createAccessToken = getTokenServices().createAccessToken(oauth2Authentication); + // First time. The Authentication has 2 roles; + assertEquals(testAuthentication.getAuthorities(), + getTokenServices().loadAuthentication(createAccessToken.getValue()).getAuthorities()); + // Now I change the authorities from testAuthentication + testAuthentication = new TestChangeAuthentication("test2", false, new SimpleGrantedAuthority("NONE")); + // I recreate the request + oauth2Authentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request("id", false, + Collections.singleton("read")), testAuthentication); + // I create the authentication again + createAccessToken = getTokenServices().createAccessToken(oauth2Authentication); + assertEquals(testAuthentication.getAuthorities(), + getTokenServices().loadAuthentication(createAccessToken.getValue()).getAuthorities()); + + } + + protected TokenStore createTokenStore() { + tokenStore = new InMemoryTokenStore(); + return tokenStore; + } + + protected int getAccessTokenCount() { + return tokenStore.getAccessTokenCount(); + } + + protected int getRefreshTokenCount() { + return tokenStore.getRefreshTokenCount(); + } + + protected DefaultTokenServices getTokenServices() { + return services; + } + + protected static class TestChangeAuthentication extends AbstractAuthenticationToken { + + private static final long serialVersionUID = 1L; + + private String principal; + + public TestChangeAuthentication(String name, boolean authenticated, GrantedAuthority... authorities) { + super(Arrays.asList(authorities)); + setAuthenticated(authenticated); + this.principal = name; + } + + public Object getCredentials() { + return null; + } + + public Object getPrincipal() { + return this.principal; + } + + } + +} \ No newline at end of file From e31781dcc4db99f2f3f3b27180b68e6c7465ae5b Mon Sep 17 00:00:00 2001 From: golonzovsky Date: Wed, 5 Nov 2014 17:11:14 +0100 Subject: [PATCH 327/831] Added findTokensByUserName method to JdbcTokenStore This restores a feature from 1.0.x but only in the concrete type (since the TokenStore no longer can have that method). Fixes gh-300 --- .../provider/token/store/JdbcTokenStore.java | 38 +++++++++++++++---- .../token/store/JdbcTokenStoreTests.java | 20 +++++++++- .../token/store/TokenStoreBaseTests.java | 2 +- 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JdbcTokenStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JdbcTokenStore.java index 65bf03d27..4c67843d0 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JdbcTokenStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JdbcTokenStore.java @@ -49,6 +49,8 @@ public class JdbcTokenStore implements TokenStore { private static final String DEFAULT_ACCESS_TOKENS_FROM_USERNAME_AND_CLIENT_SELECT_STATEMENT = "select token_id, token from oauth_access_token where user_name = ? and client_id = ?"; + private static final String DEFAULT_ACCESS_TOKENS_FROM_USERNAME_SELECT_STATEMENT = "select token_id, token from oauth_access_token where user_name = ?"; + private static final String DEFAULT_ACCESS_TOKENS_FROM_CLIENTID_SELECT_STATEMENT = "select token_id, token from oauth_access_token where client_id = ?"; private static final String DEFAULT_ACCESS_TOKEN_DELETE_STATEMENT = "delete from oauth_access_token where token_id = ?"; @@ -73,6 +75,8 @@ public class JdbcTokenStore implements TokenStore { private String selectAccessTokensFromUserNameAndClientIdSql = DEFAULT_ACCESS_TOKENS_FROM_USERNAME_AND_CLIENT_SELECT_STATEMENT; + private String selectAccessTokensFromUserNameSql = DEFAULT_ACCESS_TOKENS_FROM_USERNAME_SELECT_STATEMENT; + private String selectAccessTokensFromClientIdSql = DEFAULT_ACCESS_TOKENS_FROM_CLIENTID_SELECT_STATEMENT; private String deleteAccessTokenSql = DEFAULT_ACCESS_TOKEN_DELETE_STATEMENT; @@ -300,6 +304,22 @@ public Collection findTokensByClientId(String clientId) { return accessTokens; } + public Collection findTokensByUserName(String userName) { + List accessTokens = new ArrayList(); + + try { + accessTokens = jdbcTemplate.query(selectAccessTokensFromUserNameSql, new SafeAccessTokenRowMapper(), + userName); + } + catch (EmptyResultDataAccessException e) { + if (LOG.isInfoEnabled()) + LOG.info("Failed to find access token for userName " + userName); + } + accessTokens = removeNulls(accessTokens); + + return accessTokens; + } + public Collection findTokensByClientIdAndUserName(String clientId, String userName) { List accessTokens = new ArrayList(); @@ -309,7 +329,7 @@ public Collection findTokensByClientIdAndUserName(String clie } catch (EmptyResultDataAccessException e) { if (LOG.isInfoEnabled()) { - LOG.info("Failed to find access token for userName " + userName); + LOG.info("Failed to find access token for clientId " + clientId + " and userName " + userName); } } accessTokens = removeNulls(accessTokens); @@ -425,12 +445,16 @@ public void setDeleteAccessTokenFromRefreshTokenSql(String deleteAccessTokenFrom this.deleteAccessTokenFromRefreshTokenSql = deleteAccessTokenFromRefreshTokenSql; } - public void setSelectAccessTokensFromUserNameAndClientIdSql(String selectAccessTokensFromUserNameAndClientIdSql) { - this.selectAccessTokensFromUserNameAndClientIdSql = selectAccessTokensFromUserNameAndClientIdSql; - } + public void setSelectAccessTokensFromUserNameSql(String selectAccessTokensFromUserNameSql) { + this.selectAccessTokensFromUserNameSql = selectAccessTokensFromUserNameSql; + } + + public void setSelectAccessTokensFromUserNameAndClientIdSql(String selectAccessTokensFromUserNameAndClientIdSql) { + this.selectAccessTokensFromUserNameAndClientIdSql = selectAccessTokensFromUserNameAndClientIdSql; + } - public void setSelectAccessTokensFromClientIdSql(String selectAccessTokensFromClientIdSql) { - this.selectAccessTokensFromClientIdSql = selectAccessTokensFromClientIdSql; - } + public void setSelectAccessTokensFromClientIdSql(String selectAccessTokensFromClientIdSql) { + this.selectAccessTokensFromClientIdSql = selectAccessTokensFromClientIdSql; + } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JdbcTokenStoreTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JdbcTokenStoreTests.java index 108ac61db..ffd13fb83 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JdbcTokenStoreTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JdbcTokenStoreTests.java @@ -1,10 +1,18 @@ package org.springframework.security.oauth2.provider.token.store; +import static org.junit.Assert.assertEquals; + +import java.util.Collection; + import org.junit.After; import org.junit.Before; +import org.junit.Test; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; -import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore; +import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.RequestTokenFactory; /** * @author Dave Syer @@ -28,6 +36,16 @@ public void setUp() throws Exception { tokenStore = new JdbcTokenStore(db); } + @Test + public void testFindAccessTokensByUserName() { + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request("id", false), new TestAuthentication("test2", false)); + OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); + getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); + + Collection actualOAuth2AccessTokens = getTokenStore().findTokensByUserName("test2"); + assertEquals(1, actualOAuth2AccessTokens.size()); + } + @After public void tearDown() throws Exception { db.shutdown(); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/TokenStoreBaseTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/TokenStoreBaseTests.java index adb1db0f2..a81e20ada 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/TokenStoreBaseTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/TokenStoreBaseTests.java @@ -100,7 +100,7 @@ public void testRetrieveAccessToken() { } @Test - public void testFindAccessTokensByUserName() { + public void testFindAccessTokensByClientIdAndUserName() { OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request("id", false), new TestAuthentication("test2", false)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); From a3e32bf1238f955acf5ff384277146f34dbfc984 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 10 Nov 2014 06:07:08 +0000 Subject: [PATCH 328/831] Add support for dynamic credentials in password grant clients User can now add credentials (of any kind) to the AccessTokenRequest. Fixes gh-306 --- docs/oauth2.md | 63 +++++++++++--- ...ourceOwnerPasswordAccessTokenProvider.java | 5 +- ...OwnerPasswordAccessTokenProviderTests.java | 85 +++++++++++++++++++ 3 files changed, 137 insertions(+), 16 deletions(-) create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/password/ResourceOwnerPasswordAccessTokenProviderTests.java diff --git a/docs/oauth2.md b/docs/oauth2.md index 335090e16..e6aafd1ee 100644 --- a/docs/oauth2.md +++ b/docs/oauth2.md @@ -11,11 +11,11 @@ home: ../ This is the user guide for the support for [`OAuth 2.0`](http://tools.ietf.org/html/draft-ietf-oauth-v2). For OAuth 1.0, everything is different, so [see its user guide](oauth1.html). -This user guide is divided into two parts, the first for the OAuth 2.0 provider, the second for the OAuth 2.0 client. +This user guide is divided into two parts, the first for the OAuth 2.0 provider, the second for the OAuth 2.0 client. For both the provider and the client, the best source of sample code is the [integration tests](https://github.com/spring-projects/spring-security-oauth/tree/master/tests) and [sample apps](https://github.com/spring-projects/spring-security-oauth/tree/master/samples/oauth2). ## OAuth 2.0 Provider -The OAuth 2.0 provider mechanism is responsible for exposing OAuth 2.0 protected resources. The configuration involves establishing the OAuth 2.0 clients that can access its protected resources on behalf of a user. The provider does this by managing and verifying the OAuth 2.0 tokens that can be used to access the protected resources. Where applicable, the provider must also supply an interface for the user to confirm that a client can be granted access to the protected resources (i.e. a confirmation page). +The OAuth 2.0 provider mechanism is responsible for exposing OAuth 2.0 protected resources. The configuration involves establishing the OAuth 2.0 clients that can access its protected resources independently or on behalf of a user. The provider does this by managing and verifying the OAuth 2.0 tokens used to access the protected resources. Where applicable, the provider must also supply an interface for the user to confirm that a client can be granted access to the protected resources (i.e. a confirmation page). ## OAuth 2.0 Provider Implementation @@ -28,13 +28,13 @@ The following filter is required to implement an OAuth 2.0 Resource Server: * The [`OAuth2AuthenticationProcessingFilter`][OAuth2AuthenticationProcessingFilter] is used to load the Authentication for the request given an authenticated access token. -For all the OAuth 2.0 provider features, configuration is simplified using special Spring OAuth `@Configuration` adapters. There is also XML namespace for OAuth configuration and the schema resides at [http://www.springframework.org/schema/security/spring-security-oauth2.xsd][oauth2.xsd]. The namespace is `http://www.springframework.org/schema/security/oauth2`. +For all the OAuth 2.0 provider features, configuration is simplified using special Spring OAuth `@Configuration` adapters. There is also an XML namespace for OAuth configuration, and the schema resides at [http://www.springframework.org/schema/security/spring-security-oauth2.xsd][oauth2.xsd]. The namespace is `http://www.springframework.org/schema/security/oauth2`. ## Authorization Server Configuration As you configure the Authorization Server, you have to consider the grant type that the client is to use to obtain an access token from the end-user (e.g. authorization code, user credentials, refresh token). The configuration of the server is used to provide implementations of the client details service and token services and to enable or disable certain aspects of the mechanism globally. Note, however, that each client can be configured specifically with permissions to be able to use certain authorization mechanisms and access grants. I.e. just because your provider is configured to support the "client credentials" grant type, doesn't mean that a specific client is authorized to use that grant type. -The `@EnableAuthorizationServer` annotation is used to configure the OAuth 2.0 Authorization Server mechanism, together with any `@Beans` that implement `AuthorizationServerConfigurer` (there is a hander adapter implementation with empty methods). The following features are delegated to separate configurers that are created by Spring and passed into the `AuthorizationServerConfigurer`: +The `@EnableAuthorizationServer` annotation is used to configure the OAuth 2.0 Authorization Server mechanism, together with any `@Beans` that implement `AuthorizationServerConfigurer` (there is a handy adapter implementation with empty methods). The following features are delegated to separate configurers that are created by Spring and passed into the `AuthorizationServerConfigurer`: * `ClientDetailsServiceConfigurer`: a configurer that defines the client details service. Client details can be initialized, or you can just refer to an existing store. * `AuthorizationServerSecurityConfigurer`: defines the security constraints on the token endpoint. @@ -54,22 +54,28 @@ The `ClientDetailsServiceConfigurer` (a callback from your `AuthorizationServerC * `authorizedGrantTypes`: Grasnt types that are authorized for the client to use. Default value is empty. * `authorities`: Authorities that are granted to the client (regular Spring Security authorities). -Client details can be updated in a running application by access the underlying store directly (e.g. database tables in the case of `JdbcClientDetailsService`) or through the `ClientDetailsManager` interface (which both implementations or `ClientDetailsService` also implement). +Client details can be updated in a running application by access the underlying store directly (e.g. database tables in the case of `JdbcClientDetailsService`) or through the `ClientDetailsManager` interface (which both implementations of `ClientDetailsService` also implement). ### Managing Tokens The [`AuthorizationServerTokenServices`][AuthorizationServerTokenServices] interface defines the operations that are necessary to manage OAuth 2.0 tokens. Note the following: -* When an access token is created, the authentication must be stored so that the subsequent access token can reference it. +* When an access token is created, the authentication must be stored so that resources accepting the access token can reference it later. * The access token is used to load the authentication that was used to authorize its creation. -When creating your `AuthorizationServerTokenServices` implementation, you may want to consider using the [`DefaultTokenServices`][DefaultTokenServices] which creates tokens via random value and handles everything except for the persistence of the tokens which it delegates to a `TokenStore`. The default store is an [in-memory implementation][InMemoryTokenStore], but there are some other implementations available. Here's a description with some discussion of each of them +When creating your `AuthorizationServerTokenServices` implementation, you may want to consider using the [`DefaultTokenServices`][DefaultTokenServices] which has many strategies that can be plugged in to change the format ans storage of access tokens. By default it creates tokens via random value and handles everything except for the persistence of the tokens which it delegates to a `TokenStore`. The default store is an [in-memory implementation][InMemoryTokenStore], but there are some other implementations available. Here's a description with some discussion of each of them * The default `InMemoryTokenStore` is perfectly fine for a single server (i.e. low traffic and no hot swap to a backup server in the case of failure). Most projects can start here, and maybe operate this way in development mode, to make it easy to start a server with no dependencies. * The `JdbcTokenStore` is the [JDBC version](JdbcTokenStore) of the same thing, which stores token data in a relational database. Use the JDBC version if you can share a database between servers, either scaled up instances of the same server if there is only one, or the Authorization and Resources Servers if there are multiple components. To use the `JdbcTokenStore` you need "spring-jdbc" on the classpath. -* The [JSON Web Token (JWT) version](`JwtTokenStore`) of the store encodes all the data about the grant into the token itself (so no back end store at all which is a significant advantage). One disadvantage is that you can't easily revoke an access token (so they normally are granted with short expiry and the revocation is handled at the refresh token). Another disadvantage is that the tokens can get quite large if you are storing a lot of user credential information in them. The `JwtTokenStore` is not really a "store" in the sense that it doesn't persist any datam but it plays the same role of translating betweeen token values and authentication information in the `DefaultTokenServices`. Note that the `JwtTokenStore` has a dependency on a `JwtAccessTokenConverter`, and the same implementation is needed by both the Authorization Server and the Resource Server (so they can agree on the contents and decode them safely). The tokens are signed by default, and the Resource Server has to be able to verify the signature, so it either needs the same symmetric (signing) key as the Authorization Server (shared secret, or symmetric key), or it needs the public key (verifier key) that matches the private key (signing key) in the Authorization (public-private or asymmetric key). To use the `JwtTokenStore` you need "spring-security-jwt" on your classpath (you can find it in the same github repository as Spring OAuth but with a different release cycle). +* The [JSON Web Token (JWT) version](`JwtTokenStore`) of the store encodes all the data about the grant into the token itself (so no back end store at all which is a significant advantage). One disadvantage is that you can't easily revoke an access token, so they normally are granted with short expiry and the revocation is handled at the refresh token. Another disadvantage is that the tokens can get quite large if you are storing a lot of user credential information in them. The `JwtTokenStore` is not really a "store" in the sense that it doesn't persist any data, but it plays the same role of translating betweeen token values and authentication information in the `DefaultTokenServices`. + +### JWT Tokens + +To use JWT tokens you need a `JwtTokenStore` in your Authorization Server. The Resource Server also needs to be able to decode the tokens so the `JwtTokenStore` has a dependency on a `JwtAccessTokenConverter`, and the same implementation is needed by both the Authorization Server and the Resource Server. The tokens are signed by default, and the Resource Server also has to be able to verify the signature, so it either needs the same symmetric (signing) key as the Authorization Server (shared secret, or symmetric key), or it needs the public key (verifier key) that matches the private key (signing key) in the Authorization Server (public-private or asymmetric key). The public key (if available) is exposed by the Authorization Server on the `/oauth/token_key` endpoint, which is secure by default with access rule "denyAll()". You can open it up by injecting a standard SpEL expression into the `AuthorizationServerSecurityConfigurer` (e.g. "permitAll()" is probably adequate since it is a public key). + +To use the `JwtTokenStore` you need "spring-security-jwt" on your classpath (you can find it in the same github repository as Spring OAuth but with a different release cycle). ### Grant Types @@ -78,8 +84,8 @@ configured via the `AuthorizationServerEndpointsConfigurer`. By default all grant types are supported except password (see below for details of how to switch it on). The following properties affect grant types: -* `authenticationManager`: password grants are switched on by injecting an `AuthenticationManager`. Take care when injecting an `AuthenticationManager` into an `AuthorizationServerEndpointsConfigurer`: if you build the `AuthenticationManager` from an `AuthenticationManagerBuilder` elsewhere, then instead of injecting the manager directly, inject the builder. Then you can use the overloaded version of this method that takes the builder as an argument. -* `authorizationCodeServices`: defines the authorization code services (instance of `org.springframework.security.oauth2.provider.code.AuthorizationCodeServices`) for the auth code grant +* `authenticationManager`: password grants are switched on by injecting an `AuthenticationManager`. +* `authorizationCodeServices`: defines the authorization code services (instance of `AuthorizationCodeServices`) for the auth code grant. * `implicitGrantService`: manages state during the imlpicit grant. * `tokenGranter`: the `TokenGranter` (taking full control of the granting and ignoring the other properties above) @@ -92,9 +98,23 @@ The `AuthorizationServerEndpointsConfigurer` has a `pathMapping()` method. It ta * The default (framework implementation) URL path for the endpoint * The custom path required (starting with a "/") -The URL paths provided by the framework are `/oauth/authorize` (the authorization endpoint), `/oauth/token` (the token endpoint), `/oauth/confirm_access` (user posts approval for grants here) and `/oauth/error` (used to render errors in the authorization server). +The URL paths provided by the framework are `/oauth/authorize` (the authorization endpoint), `/oauth/token` (the token endpoint), `/oauth/confirm_access` (user posts approval for grants here), `/oauth/error` (used to render errors in the authorization server), `/oauth/check_token` (used by Resource Servers to decode access tokens), and `/oauth/token_key` (exposes public key for token verification if using JWT tokens). + +N.B. the Authorization endpoint `/oauth/authorize` (or its mapped alternative) should be protected using Spring Security so that it is only accessible to authenticated users. For instance using a standard Spring Security `WebSecurityConfigurer`: + +``` + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .authorizeRequests().antMatchers("/login").permitAll().and() + // default protection for all resources (including /oauth/authorize) + .authorizeRequests() + .anyRequest().hasRole("USER") + // ... more configuration, e.g. for form login + } +``` -N.B. the Authorization endpoint `/oauth/authorize` (or its mapped alternative) should be protected using Spring Security so that it is only accessible to authenticated users. The token endpoint is protected by default by Spring OAuth in the `@Configuration` support using HTTP Basic authentication of the client secret, but not in XML (so in that case it should be protected explicitly). +The token endpoint is protected for you by default by Spring OAuth in the `@Configuration` support using HTTP Basic authentication of the client secret. This is not the case in XML (so it should be protected explicitly). In XML the `` element has some attributes that can be used to change the default endpoint URLs in a similar way. @@ -109,9 +129,22 @@ A Resource Server (can be the same as the Authorization Server or a separate app * `tokenServices`: the bean that defines the token services (instance of `ResourceServerTokenServices`). * `resourceId`: the id for the resource (optional, but recommended and will be validated by the auth server if present). -The `@EnableResourceServer` annotation adds a filter of type `OAuth2AuthenticationProcessingFilter` to the Spring Security filter chain. +The `@EnableResourceServer` annotation adds a filter of type `OAuth2AuthenticationProcessingFilter` automatically to the Spring Security filter chain. -In XML there is a `` element with an `id` attribute - this is the bean id for a servlet `Filter` that can be added to the standard Spring Security chain. +In XML there is a `` element with an `id` attribute - this is the bean id for a servlet `Filter` that can then be added manually to the standard Spring Security chain. + +Your `ResourceServerTokenServices` is the other half of a contract with the Authorization Server. If the Resource Server and Authorization Server are in the same application and you use `DefaultTokenServices` then you don't have to think too hard about this because it implements all the necessary interfaces so it is automatically consistent. If your Resource Server is a separate application then you have to make sure you match the capabilities of the Authorization Server and provide a `ResourceServerTokenServices` that knows how to decode the tokens correctly. As with the Authorization Server, you can often use the `DefaultTokenServices` and the choices are mostly expressed through the `TokenStore` (backend storage or local encoding). An alternative is the `RemoteTokenServices` which is a Spring OAuth features (not part of the spec) allowing Resource Servers to decode tokens through an HTTP resource on the Authorization Server (`/oauth/check_token`). `RemoteTokenServices` are convenient if there is not a huge volume of traffic in the Resource Servers (every request has to be verified with the Authorization Server), or if you can afford to cache the results. To use the `/oauth/check_token` endpoint you need to expose it by changing its access rule (default is "denyAll()") in the `AuthorizationServerSecurityConfigurer`, e.g. + +``` + @Override + public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { + oauthServer.tokenKeyAccess("isAnonymous() || hasAuthority('ROLE_TRUSTED_CLIENT')").checkTokenAccess( + "hasAuthority('ROLE_TRUSTED_CLIENT')"); + } + +``` + +In this example we are configuring both the `/oauth/check_token` endpoint and the `/oauth/token_key` endpoint (so trusted resources can obtain the public key for JWT verification). These two endpoints are protected by HTTP Basic authentication using client credentials. ### Configuring An OAuth-Aware Expression Handler @@ -182,6 +215,8 @@ In XML there is a `` element with an `id` attribute - this is the bean Once you've supplied all the configuration for the resources, you can now access those resources. The suggested method for accessing those resources is by using [the `RestTemplate` introduced in Spring 3][restTemplate]. OAuth for Spring Security has provided [an extension of RestTemplate][OAuth2RestTemplate] that only needs to be supplied an instance of [`OAuth2ProtectedResourceDetails`][OAuth2ProtectedResourceDetails]. To use it with user-tokens (authorization code grants) you should consider using the `@EnableOAuth2Client` configuration (or the XML equivalent ``) which creates some request and session scoped context objects so that requests for different users do not collide at runtime. +As a general rule, a web application should not use password grants, so avoid using `ResourceOwnerPasswordResourceDetails` if you can in favour of `AuthorizationCodeResourceDetails`. If you desparately need password grants to work from a Java client, then use the same mechanism to configure your `OAuth2RestTemplate` and add the credentials to the `AccessTokenRequest` (which is a `Map` and is ephemeral) not the `ResourceOwnerPasswordResourceDetails` (which is shared between all access tokens). + ### Persisting Tokens in a Client A client does not *need* to persist tokens, but it can be nice for users to not be required to approve a new token grant every time the client app is restarted. The [`ClientTokenServices`](/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/ClientTokenServices.java) interface defines the operations that are necessary to persist OAuth 2.0 tokens for specific users. There is a JDBC implementation provided, but you can if you prefer implement your own service for storing the access tokens and associated authentication instances in a persistent database. diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/password/ResourceOwnerPasswordAccessTokenProvider.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/password/ResourceOwnerPasswordAccessTokenProvider.java index f505afc8f..3fa397bcb 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/password/ResourceOwnerPasswordAccessTokenProvider.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/password/ResourceOwnerPasswordAccessTokenProvider.java @@ -44,17 +44,18 @@ public OAuth2AccessToken obtainAccessToken(OAuth2ProtectedResourceDetails detail throws UserRedirectRequiredException, AccessDeniedException, OAuth2AccessDeniedException { ResourceOwnerPasswordResourceDetails resource = (ResourceOwnerPasswordResourceDetails) details; - return retrieveToken(request, resource, getParametersForTokenRequest(resource), new HttpHeaders()); + return retrieveToken(request, resource, getParametersForTokenRequest(resource, request), new HttpHeaders()); } - private MultiValueMap getParametersForTokenRequest(ResourceOwnerPasswordResourceDetails resource) { + private MultiValueMap getParametersForTokenRequest(ResourceOwnerPasswordResourceDetails resource, AccessTokenRequest request) { MultiValueMap form = new LinkedMultiValueMap(); form.set("grant_type", "password"); form.set("username", resource.getUsername()); form.set("password", resource.getPassword()); + form.putAll(request); if (resource.isScoped()) { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/password/ResourceOwnerPasswordAccessTokenProviderTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/password/ResourceOwnerPasswordAccessTokenProviderTests.java new file mode 100644 index 000000000..e6499ef6e --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/password/ResourceOwnerPasswordAccessTokenProviderTests.java @@ -0,0 +1,85 @@ +/* + * Copyright 2006-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.client.token.grant.password; + +import static org.junit.Assert.assertEquals; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.springframework.http.HttpHeaders; +import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails; +import org.springframework.security.oauth2.client.token.AccessTokenRequest; +import org.springframework.security.oauth2.client.token.DefaultAccessTokenRequest; +import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; + +/** + * @author Dave Syer + * + */ +public class ResourceOwnerPasswordAccessTokenProviderTests { + + @Rule + public ExpectedException expected = ExpectedException.none(); + + private MultiValueMap params = new LinkedMultiValueMap(); + + private ResourceOwnerPasswordAccessTokenProvider provider = new ResourceOwnerPasswordAccessTokenProvider() { + @Override + protected OAuth2AccessToken retrieveToken(AccessTokenRequest request, OAuth2ProtectedResourceDetails resource, + MultiValueMap form, HttpHeaders headers) { + params.putAll(form); + if (!form.containsKey("username") || form.getFirst("username")==null) { + throw new IllegalArgumentException(); + } + // Only the map parts of the AccessTokenRequest are sent as form values + if (form.containsKey("current_uri") || form.containsKey("currentUri")) { + throw new IllegalArgumentException(); + } + return new DefaultOAuth2AccessToken("FOO"); + } + }; + + private ResourceOwnerPasswordResourceDetails resource = new ResourceOwnerPasswordResourceDetails(); + + @Test + public void testGetAccessToken() throws Exception { + AccessTokenRequest request = new DefaultAccessTokenRequest(); + resource.setAccessTokenUri("http://localhost/oauth/token"); + resource.setUsername("foo"); + resource.setPassword("bar"); + assertEquals("FOO", provider.obtainAccessToken(resource, request).getValue()); + } + + @Test + public void testGetAccessTokenWithDynamicCredentials() throws Exception { + AccessTokenRequest request = new DefaultAccessTokenRequest(); + request.set("username", "foo"); + request.set("password", "bar"); + resource.setAccessTokenUri("http://localhost/oauth/token"); + assertEquals("FOO", provider.obtainAccessToken(resource, request).getValue()); + } + + @Test + public void testCurrentUriNotUsed() throws Exception { + AccessTokenRequest request = new DefaultAccessTokenRequest(); + request.set("username", "foo"); + request.setCurrentUri("urn:foo:bar"); + resource.setAccessTokenUri("http://localhost/oauth/token"); + assertEquals("FOO", provider.obtainAccessToken(resource, request).getValue()); + } + +} From 081830f2acd39d07c79609c13120cfce91c93cd2 Mon Sep 17 00:00:00 2001 From: judeplat Date: Sun, 9 Nov 2014 14:59:42 +0100 Subject: [PATCH 329/831] Error on json callback and ResourceServerConfiguration in sparklr2 Fixes gh-304, fixes gh-307 --- .../sparklr/config/OAuth2ServerConfig.java | 14 +++++++------- .../examples/sparklr/mvc/PhotoController.java | 10 ++++++---- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java index 987b6936e..f37cc3ca7 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java @@ -89,11 +89,11 @@ public void configure(HttpSecurity http) throws Exception { .requestMatchers().antMatchers("/photos/**", "/oauth/users/**", "/oauth/clients/**","/me") .and() .authorizeRequests() - .antMatchers("/me").access("#oauth2.hasScope('read')") - .antMatchers("/photos").access("#oauth2.hasScope('read')") + .antMatchers("/me").access("#oauth2.hasScope('read')") + .antMatchers("/photos").access("#oauth2.hasScope('read') or hasRole('ROLE_USER')") .antMatchers("/photos/trusted/**").access("#oauth2.hasScope('trust')") - .antMatchers("/photos/user/**").access("#oauth2.hasScope('trust')") - .antMatchers("/photos/**").access("#oauth2.hasScope('read')") + .antMatchers("/photos/user/**").access("#oauth2.hasScope('trust')") + .antMatchers("/photos/**").access("#oauth2.hasScope('read') or hasRole('ROLE_USER')") .regexMatchers(HttpMethod.DELETE, "/oauth/users/([^/].*?)/tokens/.*") .access("#oauth2.clientHasRole('ROLE_CLIENT') and (hasRole('ROLE_USER') or #oauth2.isClient()) and #oauth2.hasScope('write')") .regexMatchers(HttpMethod.GET, "/oauth/clients/([^/].*?)/users/.*") @@ -190,9 +190,9 @@ public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws } } - + protected static class Stuff { - + @Autowired private ClientDetailsService clientDetailsService; @@ -208,7 +208,7 @@ public ApprovalStore approvalStore() throws Exception { @Bean @Lazy - @Scope(proxyMode=ScopedProxyMode.TARGET_CLASS) + @Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) public SparklrUserApprovalHandler userApprovalHandler() throws Exception { SparklrUserApprovalHandler handler = new SparklrUserApprovalHandler(); handler.setApprovalStore(approvalStore()); diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/PhotoController.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/PhotoController.java index 023e498fc..dbf46e35f 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/PhotoController.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/mvc/PhotoController.java @@ -33,7 +33,8 @@ public ResponseEntity getPhoto(@PathVariable("photoId") String id) throw InputStream photo = getPhotoService().loadPhoto(id); if (photo == null) { return new ResponseEntity(HttpStatus.NOT_FOUND); - } else { + } + else { ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len = photo.read(buffer); @@ -48,7 +49,8 @@ public ResponseEntity getPhoto(@PathVariable("photoId") String id) throw } @RequestMapping(value = "/photos", params = "format=json") - public ResponseEntity getJsonPhotos(@RequestParam(value = "callback", required = false) String callback, Principal principal) { + public ResponseEntity getJsonPhotos(@RequestParam(value = "callback", required = false) String callback, + Principal principal) { Collection photos = getPhotoService().getPhotosForCurrentUser(principal.getName()); StringBuilder out = new StringBuilder(); if (callback != null) { @@ -69,7 +71,7 @@ public ResponseEntity getJsonPhotos(@RequestParam(value = "callback", re } HttpHeaders headers = new HttpHeaders(); - headers.set("Content-Type", "application/json"); + headers.set("Content-Type", "application/javascript"); return new ResponseEntity(out.toString(), headers, HttpStatus.OK); } @@ -98,7 +100,7 @@ public String getTrustedClientMessage() { @RequestMapping("/photos/user/message") @ResponseBody public String getTrustedUserMessage(Principal principal) { - return "Hello, Trusted User" + (principal!=null ? " " + principal.getName() : ""); + return "Hello, Trusted User" + (principal != null ? " " + principal.getName() : ""); } public PhotoService getPhotoService() { From f6e0acf94bb90a525598d6e7edb24c923b0f9723 Mon Sep 17 00:00:00 2001 From: sgyyz Date: Fri, 7 Nov 2014 23:06:59 +0800 Subject: [PATCH 330/831] Add @Qualifier for ConsumerTokenServices. This shouldn't be necessary and it works for me, but users have reported that it is needed. When someone has time we might be able to figure out why. Fixes gh-298, fixes gh-303 --- .../examples/sparklr/config/WebMvcConfig.java | 141 +++++++++--------- 1 file changed, 71 insertions(+), 70 deletions(-) diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/WebMvcConfig.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/WebMvcConfig.java index 4089ce918..43d96e9a0 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/WebMvcConfig.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/WebMvcConfig.java @@ -4,6 +4,7 @@ import java.util.Arrays; import java.util.List; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; @@ -39,65 +40,66 @@ public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderCon return new PropertySourcesPlaceholderConfigurer(); } - @Bean - public ContentNegotiatingViewResolver contentViewResolver() throws Exception { - ContentNegotiationManagerFactoryBean contentNegotiationManager = new ContentNegotiationManagerFactoryBean(); - contentNegotiationManager.addMediaType("json", MediaType.APPLICATION_JSON); - - InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); - viewResolver.setPrefix("/WEB-INF/jsp/"); - viewResolver.setSuffix(".jsp"); - - MappingJackson2JsonView defaultView = new MappingJackson2JsonView(); - defaultView.setExtractValueFromSingleKeyModel(true); - - ContentNegotiatingViewResolver contentViewResolver = new ContentNegotiatingViewResolver(); - contentViewResolver.setContentNegotiationManager(contentNegotiationManager.getObject()); - contentViewResolver.setViewResolvers(Arrays.asList(viewResolver)); - contentViewResolver.setDefaultViews(Arrays.asList(defaultView)); - return contentViewResolver; - } - - - @Bean - public PhotoServiceUserController photoServiceUserController(PhotoService photoService) { - PhotoServiceUserController photoServiceUserController = new PhotoServiceUserController(); - return photoServiceUserController; - } - - @Bean - public PhotoController photoController(PhotoService photoService) { - PhotoController photoController = new PhotoController(); - photoController.setPhotoService(photoService); - return photoController; - } - - @Bean - public AccessConfirmationController accessConfirmationController(ClientDetailsService clientDetailsService, ApprovalStore approvalStore) { - AccessConfirmationController accessConfirmationController = new AccessConfirmationController(); - accessConfirmationController.setClientDetailsService(clientDetailsService); - accessConfirmationController.setApprovalStore(approvalStore); - return accessConfirmationController; - } - - @Bean - public PhotoServiceImpl photoServices() { - List photos = new ArrayList(); - photos.add(createPhoto("1", "marissa")); - photos.add(createPhoto("2", "paul")); - photos.add(createPhoto("3", "marissa")); - photos.add(createPhoto("4", "paul")); - photos.add(createPhoto("5", "marissa")); - photos.add(createPhoto("6", "paul")); - - PhotoServiceImpl photoServices = new PhotoServiceImpl(); - photoServices.setPhotos(photos); - return photoServices; - } + @Bean + public ContentNegotiatingViewResolver contentViewResolver() throws Exception { + ContentNegotiationManagerFactoryBean contentNegotiationManager = new ContentNegotiationManagerFactoryBean(); + contentNegotiationManager.addMediaType("json", MediaType.APPLICATION_JSON); + + InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); + viewResolver.setPrefix("/WEB-INF/jsp/"); + viewResolver.setSuffix(".jsp"); + + MappingJackson2JsonView defaultView = new MappingJackson2JsonView(); + defaultView.setExtractValueFromSingleKeyModel(true); + + ContentNegotiatingViewResolver contentViewResolver = new ContentNegotiatingViewResolver(); + contentViewResolver.setContentNegotiationManager(contentNegotiationManager.getObject()); + contentViewResolver.setViewResolvers(Arrays. asList(viewResolver)); + contentViewResolver.setDefaultViews(Arrays. asList(defaultView)); + return contentViewResolver; + } + + @Bean + public PhotoServiceUserController photoServiceUserController(PhotoService photoService) { + PhotoServiceUserController photoServiceUserController = new PhotoServiceUserController(); + return photoServiceUserController; + } + + @Bean + public PhotoController photoController(PhotoService photoService) { + PhotoController photoController = new PhotoController(); + photoController.setPhotoService(photoService); + return photoController; + } + @Bean + public AccessConfirmationController accessConfirmationController(ClientDetailsService clientDetailsService, + ApprovalStore approvalStore) { + AccessConfirmationController accessConfirmationController = new AccessConfirmationController(); + accessConfirmationController.setClientDetailsService(clientDetailsService); + accessConfirmationController.setApprovalStore(approvalStore); + return accessConfirmationController; + } + + @Bean + public PhotoServiceImpl photoServices() { + List photos = new ArrayList(); + photos.add(createPhoto("1", "marissa")); + photos.add(createPhoto("2", "paul")); + photos.add(createPhoto("3", "marissa")); + photos.add(createPhoto("4", "paul")); + photos.add(createPhoto("5", "marissa")); + photos.add(createPhoto("6", "paul")); + + PhotoServiceImpl photoServices = new PhotoServiceImpl(); + photoServices.setPhotos(photos); + return photoServices; + } + // N.B. the @Qualifier here should not be necessary (gh-298) but lots of users report needing it. @Bean - public AdminController adminController(TokenStore tokenStore, ConsumerTokenServices tokenServices, + public AdminController adminController(TokenStore tokenStore, + @Qualifier("consumerTokenServices") ConsumerTokenServices tokenServices, SparklrUserApprovalHandler userApprovalHandler) { AdminController adminController = new AdminController(); adminController.setTokenStore(tokenStore); @@ -106,18 +108,17 @@ public AdminController adminController(TokenStore tokenStore, ConsumerTokenServi return adminController; } - private PhotoInfo createPhoto(String id, String userId) { - PhotoInfo photo = new PhotoInfo(); - photo.setId(id); - photo.setName("photo" + id + ".jpg"); - photo.setUserId(userId); - photo.setResourceURL("/org/springframework/security/oauth/examples/sparklr/impl/resources/" + photo.getName()); - return photo; - } - - @Override - public void configureDefaultServletHandling( - DefaultServletHandlerConfigurer configurer) { - configurer.enable(); - } + private PhotoInfo createPhoto(String id, String userId) { + PhotoInfo photo = new PhotoInfo(); + photo.setId(id); + photo.setName("photo" + id + ".jpg"); + photo.setUserId(userId); + photo.setResourceURL("/org/springframework/security/oauth/examples/sparklr/impl/resources/" + photo.getName()); + return photo; + } + + @Override + public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { + configurer.enable(); + } } From 79dd8cb18953b039ac91fe43ee9fac906cd24d4b Mon Sep 17 00:00:00 2001 From: presidentio Date: Sun, 2 Nov 2014 11:59:44 +0200 Subject: [PATCH 331/831] Custom token name in RemoteTokenServices --- .../provider/token/RemoteTokenServices.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/RemoteTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/RemoteTokenServices.java index 8ae7c9e62..4c1439e9d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/RemoteTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/RemoteTokenServices.java @@ -12,10 +12,6 @@ *******************************************************************************/ package org.springframework.security.oauth2.provider.token; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.util.Map; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.http.HttpEntity; @@ -35,6 +31,10 @@ import org.springframework.web.client.RestOperations; import org.springframework.web.client.RestTemplate; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.Map; + /** * Queries the /check_token endpoint to obtain the contents of an access token. * @@ -56,6 +56,8 @@ public class RemoteTokenServices implements ResourceServerTokenServices { private String clientSecret; + private String tokenName; + private AccessTokenConverter tokenConverter = new DefaultAccessTokenConverter(); public RemoteTokenServices() { @@ -91,11 +93,15 @@ public void setAccessTokenConverter(AccessTokenConverter accessTokenConverter) { this.tokenConverter = accessTokenConverter; } - @Override + public void setTokenName(String tokenName) { + this.tokenName = tokenName; + } + + @Override public OAuth2Authentication loadAuthentication(String accessToken) throws AuthenticationException, InvalidTokenException { MultiValueMap formData = new LinkedMultiValueMap(); - formData.add("token", accessToken); + formData.add(tokenName, accessToken); HttpHeaders headers = new HttpHeaders(); headers.set("Authorization", getAuthorizationHeader(clientId, clientSecret)); Map map = postForMap(checkTokenEndpointUrl, formData, headers); From 17babbe2e1b1520a42770473ec7da1e888f38a18 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 10 Nov 2014 06:24:20 +0000 Subject: [PATCH 332/831] Provide default token name to restore default behaviour Fixes gh-297, fixes gh-296 --- .../security/oauth2/provider/token/RemoteTokenServices.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/RemoteTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/RemoteTokenServices.java index 4c1439e9d..b2b059fdf 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/RemoteTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/RemoteTokenServices.java @@ -56,7 +56,7 @@ public class RemoteTokenServices implements ResourceServerTokenServices { private String clientSecret; - private String tokenName; + private String tokenName = "token"; private AccessTokenConverter tokenConverter = new DefaultAccessTokenConverter(); From a8f6679398defa091ee9e92d1c2122723e12d005 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 11 Nov 2014 10:37:01 +0000 Subject: [PATCH 333/831] Add KeyStoreKeyFactory for loading RSA keys from a file User provides a Resource and a password and can then lift the keys out of the store by name. As long as they are RSA keys they can be injected into a JwtAccessTokenConverter (using a new setter). Fixes gh-308 --- .../token/store/JwtAccessTokenConverter.java | 14 ++++ .../token/store/KeyStoreKeyFactory.java | 71 ++++++++++++++++++ .../token/store/JwtTokenEnhancerTests.java | 15 +++- .../src/test/resources/keystore.jks | Bin 0 -> 2243 bytes 4 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/KeyStoreKeyFactory.java create mode 100644 spring-security-oauth2/src/test/resources/keystore.jks diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java index 3a07e1d73..25828e878 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java @@ -12,6 +12,10 @@ */ package org.springframework.security.oauth2.provider.token.store; +import java.security.KeyPair; +import java.security.PrivateKey; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; import java.util.Date; import java.util.LinkedHashMap; import java.util.Map; @@ -20,6 +24,7 @@ import org.apache.commons.logging.LogFactory; import org.codehaus.jackson.map.ObjectMapper; import org.springframework.beans.factory.InitializingBean; +import org.springframework.security.crypto.codec.Base64; import org.springframework.security.jwt.Jwt; import org.springframework.security.jwt.JwtHelper; import org.springframework.security.jwt.crypto.sign.InvalidSignatureException; @@ -113,6 +118,15 @@ public Map getKey() { result.put("value", verifierKey); return result; } + + public void setKeyPair(KeyPair keyPair) { + PrivateKey privateKey = keyPair.getPrivate(); + Assert.state(privateKey instanceof RSAPrivateKey, "KeyPair must be an RSA "); + signer = new RsaSigner((RSAPrivateKey) privateKey); + RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); + verifier = new RsaVerifier(publicKey); + verifierKey = "-----BEGIN PUBLIC KEY-----\n" + new String(Base64.encode(publicKey.getEncoded())) + "\n-----END PUBLIC KEY-----"; + } /** * Sets the JWT signing key. It can be either a simple MAC key or an RSA key. RSA keys should be in OpenSSH format, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/KeyStoreKeyFactory.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/KeyStoreKeyFactory.java new file mode 100644 index 000000000..8eda6ef2a --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/KeyStoreKeyFactory.java @@ -0,0 +1,71 @@ +/* + * Copyright 20013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.springframework.security.oauth2.provider.token.store; + +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyStore; +import java.security.PublicKey; +import java.security.interfaces.RSAPrivateCrtKey; +import java.security.spec.RSAPublicKeySpec; + +import org.springframework.core.io.Resource; + +/** + * Factory for RSA key pairs from a JKS keystore file. User provides a {@link Resource} location of a keystore file and + * the password to unlock it, and the factory grabs the keypairs from the store by name (and optionally password). + * + * @author Dave Syer + * + */ +public class KeyStoreKeyFactory { + + private Resource resource; + + private char[] password; + + private KeyStore store; + + private Object lock = new Object(); + + public KeyStoreKeyFactory(Resource resource, char[] password) { + this.resource = resource; + this.password = password; + } + + public KeyPair getKeyPair(String alias) { + return getKeyPair(alias, password); + } + + public KeyPair getKeyPair(String alias, char[] password) { + try { + synchronized (lock) { + if (store == null) { + synchronized (lock) { + store = KeyStore.getInstance("jks"); + store.load(resource.getInputStream(), this.password); + } + } + } + RSAPrivateCrtKey key = (RSAPrivateCrtKey) store.getKey(alias, password); + RSAPublicKeySpec spec = new RSAPublicKeySpec(key.getModulus(), key.getPublicExponent()); + PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(spec); + return new KeyPair(publicKey, key); + } + catch (Exception e) { + throw new IllegalStateException("Cannot load keys from store: " + resource, e); + } + } + +} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtTokenEnhancerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtTokenEnhancerTests.java index 15f3cec28..8d99840f2 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtTokenEnhancerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtTokenEnhancerTests.java @@ -9,16 +9,16 @@ */ package org.springframework.security.oauth2.provider.token.store; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; +import java.security.KeyPair; import java.util.Collections; import java.util.Map; import java.util.Set; import org.junit.Before; import org.junit.Test; +import org.springframework.core.io.ClassPathResource; import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.jwt.JwtHelper; @@ -138,6 +138,15 @@ public void keysNotMatchingWithMacSigner() throws Exception { tokenEnhancer.setVerifierKey("someKey"); tokenEnhancer.afterPropertiesSet(); } + + @Test + public void rsaKeyPair() throws Exception { + KeyStoreKeyFactory factory = new KeyStoreKeyFactory(new ClassPathResource("keystore.jks"), "foobar".toCharArray()); + KeyPair keys = factory.getKeyPair("test"); + tokenEnhancer.setKeyPair(keys); + tokenEnhancer.afterPropertiesSet(); + assertTrue(tokenEnhancer.getKey().get("value").contains("BEGIN PUBLIC")); + } private OAuth2Request createOAuth2Request(String clientId, Set scope) { return new OAuth2Request(Collections. emptyMap(), clientId, null, true, scope, null, null, diff --git a/spring-security-oauth2/src/test/resources/keystore.jks b/spring-security-oauth2/src/test/resources/keystore.jks new file mode 100644 index 0000000000000000000000000000000000000000..0ad98eade454db2617fd1b1dc54052c264710f81 GIT binary patch literal 2243 zcmchYX*3iHAI4|THjG^%nuLhPjIwWKh7lrUtkq37Tf6p@|APS=`!9oKu$`@ZL%)A#qo^Wph@`k&`K=lOFNxC;OP0CXte-+~0)3Jf|l zW;9SZ0sw%5QB=qQN)X1U3IjrbDj;DX5DI`$A#?Lv-Gx2z_bZ!mz1flQ8{Mm-doyg$ zobv>&~Ak)(@aAA@h1;9fq^L#gr8% zHF3q7)#a53Hxz-+_Aj@Bf~z(}OHiqt`+R$H3#y4q(UvY)M0^QW!q^tCoH;x>)F+V4yZ)cd&U*LYqVsT9Lt(`%4(kknd z&W2^JU+8$}Xl4bQr^DJc_p4S~iN0A9+=>q|)hT#pGHsLjvedBeQ5UIVM&am_r)m>M zrd%RDZ7}9Um5E8ERn$CYhi$lSF)&8?F#P8IZi*|J-7`{ulbFHJ+fojclLaj)2iq1h z_Cq`9Lz#|j&P=87@~AdTKv_Vc2Kd^f`x9Q^*7+f;(*_q)?O9!Lod{HEh;|gi<`#j3!%pdJE6d~KIZVKB| z%Dko-jEK^*NG~RRC$D>%`wlqldOM*VTEmNfdG|GYVW*D zzFX%;i@MTW3bcmj_P1a&O#BQvHLq|a=UcORa}_=DQX&pbkbPxBw7&22_zu0U$v-;M zAKMrmsy-A&1IoFhFEMh6fNy%dYf5Z!nUU&vrCk9BO$n2%1lxPnP|DQAcjQT|iT$ef z5)|FL)hO;O)YY;1D_fdkx9(szFnN%|(rbddafc?9t%O;S%72yWXmFScgE#C%>)dl#ydlnY`%FWTuDzc$g6 z)7|(|yS4M0@G4fW+dyWTE|i;sboyaN5W9jip9i#D-fA~0DHtzuW^QZSqNB>VZuXYV zCmYi4=@1sW)@}9uU=Ws`uhG+*Jy39GyiFOeZ^2F?DVOHoI^Kg)7{0|LOBKg7kTWiO z9+ULIkSb=k#6HZx(xd&g22v;B+n{>Z;GEE)P@{}laKJ@P$D15R{x{jm1vdz!oJ~{itTVz%M(`a9J%*ygi z@XG!Y$X@#03ZXMs-7>`nJE)G){gBWW+Ag1gU#n*C&FpIsquc9jB*^4Gw0ceY8_^=r z@5zO!e;VrvX&5Q_Jb669Im<`TTzCRs6sdolMtu zovfMh`Bdl1KTt+yQb?)yGQRY5j&IAaOQq1Uo=rqDLHvK19C|;(rOxPvpo? zgzqQ9{}TcKkD!iA!ZkEeS{M`>rHMvkod0b#P-yM{*#Gl2R3P%7aU8x2Fcl~SKv98w zASw_Dc;!vL_~J(Afs%d=E2B}h+{5Rok+IA3(VHL+9^c~7f%|hZgcM{ep!_lamX1># zvZf(;)mWF;n;cu7AZBBg%_B4QFG|Few>pKHZHhDw_e84a2DVj=$skA47K++Z zq&+grK0qtJQp5(N<}3Nrm&TfyZwE@u&6^|f?_{O#Q03cV!bE!fc_RtfN0TOUS*4@f zATSUB%szpVL&+XCL{<30(Z6+(+;lYKrIEJW8%+$ z{cTTLv(&o&niDE{tl#W+=h8HV_d(>}U@KtDXvzy!mX5R2M7_#ECjO3b?Lg%5y;X4s z7dzc#ATy}WDK5UNXioMdOqsnw@|fE!$+pWRT5Ni`x7 Date: Tue, 11 Nov 2014 10:50:44 +0000 Subject: [PATCH 334/831] Allow TokenExtractor to be injected in ResourceServerSecurityConfigurer Fixes gh-309 --- .../ResourceServerSecurityConfigurer.java | 23 ++++++-- .../ResourceServerConfigurationTests.java | 53 +++++++++++++++++++ 2 files changed, 72 insertions(+), 4 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java index 5516ff1d0..93c1960d5 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java @@ -26,6 +26,7 @@ import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationManager; import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter; +import org.springframework.security.oauth2.provider.authentication.TokenExtractor; import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint; import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler; @@ -46,7 +47,9 @@ /** * * @author Rob Winch - * @since 3.2 + * @Author Dave Syer + * + * @since 2.0.0 */ public final class ResourceServerSecurityConfigurer extends SecurityConfigurerAdapter { @@ -66,7 +69,9 @@ public final class ResourceServerSecurityConfigurer extends private String resourceId = "oauth2-resource"; private SecurityExpressionHandler expressionHandler = new OAuth2WebSecurityExpressionHandler(); - + + private TokenExtractor tokenExtractor; + public ResourceServerSecurityConfigurer() { resourceId(resourceId); } @@ -85,6 +90,12 @@ public ResourceServerSecurityConfigurer tokenStore(TokenStore tokenStore) { return this; } + public ResourceServerSecurityConfigurer tokenExtractor(TokenExtractor tokenExtractor) { + Assert.state(tokenExtractor != null, "TokenExtractor cannot be null"); + this.tokenExtractor = tokenExtractor; + return this; + } + public ResourceServerSecurityConfigurer authenticationManager(AuthenticationManager authenticationManager) { Assert.state(authenticationManager != null, "AuthenticationManager cannot be null"); this.authenticationManager = authenticationManager; @@ -136,6 +147,9 @@ public void configure(HttpSecurity http) throws Exception { AuthenticationManager oauthAuthenticationManager = oauthAuthenticationManager(http); resourcesServerFilter = new OAuth2AuthenticationProcessingFilter(); resourcesServerFilter.setAuthenticationManager(oauthAuthenticationManager); + if (tokenExtractor != null) { + resourcesServerFilter.setTokenExtractor(tokenExtractor); + } resourcesServerFilter = postProcess(resourcesServerFilter); // @formatter:off @@ -149,10 +163,11 @@ public void configure(HttpSecurity http) throws Exception { private AuthenticationManager oauthAuthenticationManager(HttpSecurity http) { OAuth2AuthenticationManager oauthAuthenticationManager = new OAuth2AuthenticationManager(); - if (authenticationManager!=null) { + if (authenticationManager != null) { if (authenticationManager instanceof OAuth2AuthenticationManager) { oauthAuthenticationManager = (OAuth2AuthenticationManager) authenticationManager; - } else { + } + else { return authenticationManager; } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java index 7dd15689c..d57225fad 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java @@ -13,6 +13,7 @@ package org.springframework.security.oauth2.config.annotation; import javax.servlet.Filter; +import javax.servlet.http.HttpServletRequest; import org.junit.Before; import org.junit.Test; @@ -22,19 +23,25 @@ import org.springframework.mock.web.MockServletContext; import org.springframework.security.authentication.AnonymousAuthenticationProvider; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; +import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.TokenRequest; +import org.springframework.security.oauth2.provider.authentication.TokenExtractor; import org.springframework.security.oauth2.provider.client.BaseClientDetails; import org.springframework.security.oauth2.provider.client.InMemoryClientDetailsService; import org.springframework.security.oauth2.provider.token.DefaultTokenServices; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore; +import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.result.MockMvcResultMatchers; @@ -91,6 +98,21 @@ public void testCustomTokenServices() throws Exception { context.close(); } + @Test + public void testCustomTokenExtractor() throws Exception { + tokenStore.storeAccessToken(token, authentication); + AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); + context.setServletContext(new MockServletContext()); + context.register(TokenExtractorContext.class); + context.refresh(); + MockMvc mvc = MockMvcBuilders.webAppContextSetup(context) + .addFilters(new DelegatingFilterProxy(context.getBean("springSecurityFilterChain", Filter.class))) + .build(); + mvc.perform(MockMvcRequestBuilders.get("/").header("Authorization", "Bearer BAR")).andExpect( + MockMvcResultMatchers.status().isNotFound()); + context.close(); + } + @Configuration @EnableResourceServer @EnableWebSecurity @@ -106,6 +128,37 @@ public TokenStore tokenStore() { } } + @Configuration + @EnableResourceServer + @EnableWebSecurity + protected static class TokenExtractorContext extends ResourceServerConfigurerAdapter { + @Autowired + protected void init(AuthenticationManagerBuilder builder) { + builder.authenticationProvider(new AnonymousAuthenticationProvider("default")); + } + + @Override + public void configure(ResourceServerSecurityConfigurer resources) throws Exception { + resources.tokenExtractor(new TokenExtractor() { + + @Override + public Authentication extract(HttpServletRequest request) { + return new PreAuthenticatedAuthenticationToken("FOO", "N/A"); + } + }); + } + + @Override + public void configure(HttpSecurity http) throws Exception { + http.authorizeRequests().anyRequest().authenticated(); + } + + @Bean + public TokenStore tokenStore() { + return tokenStore; + } + } + @Configuration @EnableResourceServer @EnableWebSecurity From 369973e513d603eaa8f28529f0bd12fe7776a3fc Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 11 Nov 2014 11:12:50 +0000 Subject: [PATCH 335/831] [maven-release-plugin] prepare release 2.0.4.RELEASE --- pom.xml | 4 ++-- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- tests/annotation/approval/pom.xml | 2 +- tests/annotation/client/pom.xml | 2 +- tests/annotation/common/pom.xml | 2 +- tests/annotation/form/pom.xml | 2 +- tests/annotation/jdbc/pom.xml | 2 +- tests/annotation/jwt/pom.xml | 2 +- tests/annotation/mappings/pom.xml | 2 +- tests/annotation/multi/pom.xml | 2 +- tests/annotation/pom.xml | 8 ++++++-- tests/annotation/resource/pom.xml | 2 +- tests/annotation/vanilla/pom.xml | 2 +- tests/pom.xml | 2 +- tests/xml/approval/pom.xml | 2 +- tests/xml/client/pom.xml | 2 +- tests/xml/common/pom.xml | 2 +- tests/xml/form/pom.xml | 2 +- tests/xml/jdbc/pom.xml | 2 +- tests/xml/jwt/pom.xml | 2 +- tests/xml/mappings/pom.xml | 2 +- tests/xml/pom.xml | 8 ++++++-- tests/xml/vanilla/pom.xml | 2 +- 29 files changed, 40 insertions(+), 32 deletions(-) diff --git a/pom.xml b/pom.xml index dbc290555..7cd33bb1c 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.4.BUILD-SNAPSHOT + 2.0.4.RELEASE http://static.springframework.org/spring-security/oauth @@ -26,7 +26,7 @@ http://github.com/SpringSource/spring-security-oauth scm:git:git://github.com/SpringSource/spring-security-oauth.git scm:git:ssh://git@github.com/SpringSource/spring-security-oauth.git - HEAD + 2.0.4.RELEASE JIRA diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index 950ab16c6..365c89e63 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.4.BUILD-SNAPSHOT + 2.0.4.RELEASE ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index ea1795ca3..156751d7c 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.4.BUILD-SNAPSHOT + 2.0.4.RELEASE ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 958cd950e..add7cbf35 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.4.BUILD-SNAPSHOT + 2.0.4.RELEASE ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 358ca561d..9bb84fa8d 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.4.BUILD-SNAPSHOT + 2.0.4.RELEASE ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index f7166f7ed..eccbb5c20 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.4.BUILD-SNAPSHOT + 2.0.4.RELEASE spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index b2e692135..9ba063440 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.4.BUILD-SNAPSHOT + 2.0.4.RELEASE spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 2ae42f58b..b3139267a 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.4.BUILD-SNAPSHOT + 2.0.4.RELEASE spring-security-oauth2 diff --git a/tests/annotation/approval/pom.xml b/tests/annotation/approval/pom.xml index 547f6c88a..15187286c 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.4.BUILD-SNAPSHOT + 2.0.4.RELEASE diff --git a/tests/annotation/client/pom.xml b/tests/annotation/client/pom.xml index ef7722f7a..e86474039 100644 --- a/tests/annotation/client/pom.xml +++ b/tests/annotation/client/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.0.4.BUILD-SNAPSHOT + 2.0.4.RELEASE diff --git a/tests/annotation/common/pom.xml b/tests/annotation/common/pom.xml index 8d8fc6c0a..8834aa5a0 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.4.BUILD-SNAPSHOT + 2.0.4.RELEASE diff --git a/tests/annotation/form/pom.xml b/tests/annotation/form/pom.xml index 8769172e2..1ecd4d597 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.4.BUILD-SNAPSHOT + 2.0.4.RELEASE diff --git a/tests/annotation/jdbc/pom.xml b/tests/annotation/jdbc/pom.xml index c633107f6..0289c1c0f 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.4.BUILD-SNAPSHOT + 2.0.4.RELEASE diff --git a/tests/annotation/jwt/pom.xml b/tests/annotation/jwt/pom.xml index 8c37bc711..e10c54138 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.4.BUILD-SNAPSHOT + 2.0.4.RELEASE diff --git a/tests/annotation/mappings/pom.xml b/tests/annotation/mappings/pom.xml index 809cf006d..1f2556447 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.4.BUILD-SNAPSHOT + 2.0.4.RELEASE diff --git a/tests/annotation/multi/pom.xml b/tests/annotation/multi/pom.xml index 280903680..65427ff85 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.4.BUILD-SNAPSHOT + 2.0.4.RELEASE diff --git a/tests/annotation/pom.xml b/tests/annotation/pom.xml index 8f90d3c7e..2499d7f74 100644 --- a/tests/annotation/pom.xml +++ b/tests/annotation/pom.xml @@ -4,7 +4,7 @@ org.demo spring-oauth2-tests-parent - 2.0.4.BUILD-SNAPSHOT + 2.0.4.RELEASE pom @@ -34,7 +34,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.0.4.BUILD-SNAPSHOT + 2.0.4.RELEASE jackson-mapper-asl @@ -129,4 +129,8 @@ + + + 2.0.4.RELEASE + diff --git a/tests/annotation/resource/pom.xml b/tests/annotation/resource/pom.xml index b1ab11c0c..7255bd377 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.4.BUILD-SNAPSHOT + 2.0.4.RELEASE diff --git a/tests/annotation/vanilla/pom.xml b/tests/annotation/vanilla/pom.xml index 2c2491364..38693573a 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.4.BUILD-SNAPSHOT + 2.0.4.RELEASE diff --git a/tests/pom.xml b/tests/pom.xml index 6dbb6a4e9..a3b0cdc4a 100644 --- a/tests/pom.xml +++ b/tests/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.4.BUILD-SNAPSHOT + 2.0.4.RELEASE spring-security-oauth-tests diff --git a/tests/xml/approval/pom.xml b/tests/xml/approval/pom.xml index 00e1bbab4..81450bfe3 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.4.BUILD-SNAPSHOT + 2.0.4.RELEASE diff --git a/tests/xml/client/pom.xml b/tests/xml/client/pom.xml index c4d507e9a..2371dde5b 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.4.BUILD-SNAPSHOT + 2.0.4.RELEASE diff --git a/tests/xml/common/pom.xml b/tests/xml/common/pom.xml index ab3a1ea4e..8d1ae7d09 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.4.BUILD-SNAPSHOT + 2.0.4.RELEASE diff --git a/tests/xml/form/pom.xml b/tests/xml/form/pom.xml index eb8496b0c..0c572d195 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.4.BUILD-SNAPSHOT + 2.0.4.RELEASE diff --git a/tests/xml/jdbc/pom.xml b/tests/xml/jdbc/pom.xml index 5419a64ff..d256925d3 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.4.BUILD-SNAPSHOT + 2.0.4.RELEASE diff --git a/tests/xml/jwt/pom.xml b/tests/xml/jwt/pom.xml index 19423d0be..c97f79db6 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.4.BUILD-SNAPSHOT + 2.0.4.RELEASE diff --git a/tests/xml/mappings/pom.xml b/tests/xml/mappings/pom.xml index 27bd0a26e..b1124e399 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.4.BUILD-SNAPSHOT + 2.0.4.RELEASE diff --git a/tests/xml/pom.xml b/tests/xml/pom.xml index c0015b6cf..694d0f100 100644 --- a/tests/xml/pom.xml +++ b/tests/xml/pom.xml @@ -4,7 +4,7 @@ org.demo spring-oauth2-tests-xml-parent - 2.0.4.BUILD-SNAPSHOT + 2.0.4.RELEASE pom @@ -32,7 +32,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.0.4.BUILD-SNAPSHOT + 2.0.4.RELEASE jackson-mapper-asl @@ -127,4 +127,8 @@ + + + 2.0.4.RELEASE + diff --git a/tests/xml/vanilla/pom.xml b/tests/xml/vanilla/pom.xml index bbd3336ff..c1c5752f3 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.4.BUILD-SNAPSHOT + 2.0.4.RELEASE From f58d804d3c1e5d2a396734054b015ea5f5bc79c1 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 11 Nov 2014 11:13:00 +0000 Subject: [PATCH 336/831] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- tests/annotation/approval/pom.xml | 2 +- tests/annotation/client/pom.xml | 2 +- tests/annotation/common/pom.xml | 2 +- tests/annotation/form/pom.xml | 2 +- tests/annotation/jdbc/pom.xml | 2 +- tests/annotation/jwt/pom.xml | 2 +- tests/annotation/mappings/pom.xml | 2 +- tests/annotation/multi/pom.xml | 2 +- tests/annotation/pom.xml | 8 ++------ tests/annotation/resource/pom.xml | 2 +- tests/annotation/vanilla/pom.xml | 2 +- tests/pom.xml | 2 +- tests/xml/approval/pom.xml | 2 +- tests/xml/client/pom.xml | 2 +- tests/xml/common/pom.xml | 2 +- tests/xml/form/pom.xml | 2 +- tests/xml/jdbc/pom.xml | 2 +- tests/xml/jwt/pom.xml | 2 +- tests/xml/mappings/pom.xml | 2 +- tests/xml/pom.xml | 8 ++------ tests/xml/vanilla/pom.xml | 2 +- 29 files changed, 32 insertions(+), 40 deletions(-) diff --git a/pom.xml b/pom.xml index 7cd33bb1c..992050d96 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.4.RELEASE + 2.0.5.BUILD-SNAPSHOT http://static.springframework.org/spring-security/oauth @@ -26,7 +26,7 @@ http://github.com/SpringSource/spring-security-oauth scm:git:git://github.com/SpringSource/spring-security-oauth.git scm:git:ssh://git@github.com/SpringSource/spring-security-oauth.git - 2.0.4.RELEASE + HEAD JIRA diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index 365c89e63..c0ccea250 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.4.RELEASE + 2.0.5.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index 156751d7c..cc2ad4890 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.4.RELEASE + 2.0.5.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index add7cbf35..ec0567326 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.4.RELEASE + 2.0.5.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 9bb84fa8d..ce1940a68 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.4.RELEASE + 2.0.5.BUILD-SNAPSHOT ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index eccbb5c20..627277d36 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.4.RELEASE + 2.0.5.BUILD-SNAPSHOT spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index 9ba063440..399915cdd 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.4.RELEASE + 2.0.5.BUILD-SNAPSHOT spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index b3139267a..0fecc679c 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.4.RELEASE + 2.0.5.BUILD-SNAPSHOT spring-security-oauth2 diff --git a/tests/annotation/approval/pom.xml b/tests/annotation/approval/pom.xml index 15187286c..004538521 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.4.RELEASE + 2.0.5.BUILD-SNAPSHOT diff --git a/tests/annotation/client/pom.xml b/tests/annotation/client/pom.xml index e86474039..be3b8551b 100644 --- a/tests/annotation/client/pom.xml +++ b/tests/annotation/client/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.0.4.RELEASE + 2.0.5.BUILD-SNAPSHOT diff --git a/tests/annotation/common/pom.xml b/tests/annotation/common/pom.xml index 8834aa5a0..4f92cbf2b 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.4.RELEASE + 2.0.5.BUILD-SNAPSHOT diff --git a/tests/annotation/form/pom.xml b/tests/annotation/form/pom.xml index 1ecd4d597..cd5dbca48 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.4.RELEASE + 2.0.5.BUILD-SNAPSHOT diff --git a/tests/annotation/jdbc/pom.xml b/tests/annotation/jdbc/pom.xml index 0289c1c0f..f3ab5f014 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.4.RELEASE + 2.0.5.BUILD-SNAPSHOT diff --git a/tests/annotation/jwt/pom.xml b/tests/annotation/jwt/pom.xml index e10c54138..d86a8d34c 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.4.RELEASE + 2.0.5.BUILD-SNAPSHOT diff --git a/tests/annotation/mappings/pom.xml b/tests/annotation/mappings/pom.xml index 1f2556447..0d0ab5fd9 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.4.RELEASE + 2.0.5.BUILD-SNAPSHOT diff --git a/tests/annotation/multi/pom.xml b/tests/annotation/multi/pom.xml index 65427ff85..3104cf559 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.4.RELEASE + 2.0.5.BUILD-SNAPSHOT diff --git a/tests/annotation/pom.xml b/tests/annotation/pom.xml index 2499d7f74..0d3081043 100644 --- a/tests/annotation/pom.xml +++ b/tests/annotation/pom.xml @@ -4,7 +4,7 @@ org.demo spring-oauth2-tests-parent - 2.0.4.RELEASE + 2.0.5.BUILD-SNAPSHOT pom @@ -34,7 +34,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.0.4.RELEASE + 2.0.5.BUILD-SNAPSHOT jackson-mapper-asl @@ -129,8 +129,4 @@ - - - 2.0.4.RELEASE - diff --git a/tests/annotation/resource/pom.xml b/tests/annotation/resource/pom.xml index 7255bd377..a934a1bb0 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.4.RELEASE + 2.0.5.BUILD-SNAPSHOT diff --git a/tests/annotation/vanilla/pom.xml b/tests/annotation/vanilla/pom.xml index 38693573a..8861db26f 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.4.RELEASE + 2.0.5.BUILD-SNAPSHOT diff --git a/tests/pom.xml b/tests/pom.xml index a3b0cdc4a..eda061dfa 100644 --- a/tests/pom.xml +++ b/tests/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.4.RELEASE + 2.0.5.BUILD-SNAPSHOT spring-security-oauth-tests diff --git a/tests/xml/approval/pom.xml b/tests/xml/approval/pom.xml index 81450bfe3..9e55b0515 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.4.RELEASE + 2.0.5.BUILD-SNAPSHOT diff --git a/tests/xml/client/pom.xml b/tests/xml/client/pom.xml index 2371dde5b..00e62fa4b 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.4.RELEASE + 2.0.5.BUILD-SNAPSHOT diff --git a/tests/xml/common/pom.xml b/tests/xml/common/pom.xml index 8d1ae7d09..fba2f5bb4 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.4.RELEASE + 2.0.5.BUILD-SNAPSHOT diff --git a/tests/xml/form/pom.xml b/tests/xml/form/pom.xml index 0c572d195..bde4b3683 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.4.RELEASE + 2.0.5.BUILD-SNAPSHOT diff --git a/tests/xml/jdbc/pom.xml b/tests/xml/jdbc/pom.xml index d256925d3..e44cc6ef3 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.4.RELEASE + 2.0.5.BUILD-SNAPSHOT diff --git a/tests/xml/jwt/pom.xml b/tests/xml/jwt/pom.xml index c97f79db6..bd3dff86f 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.4.RELEASE + 2.0.5.BUILD-SNAPSHOT diff --git a/tests/xml/mappings/pom.xml b/tests/xml/mappings/pom.xml index b1124e399..b8359fbc8 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.4.RELEASE + 2.0.5.BUILD-SNAPSHOT diff --git a/tests/xml/pom.xml b/tests/xml/pom.xml index 694d0f100..811d39e5d 100644 --- a/tests/xml/pom.xml +++ b/tests/xml/pom.xml @@ -4,7 +4,7 @@ org.demo spring-oauth2-tests-xml-parent - 2.0.4.RELEASE + 2.0.5.BUILD-SNAPSHOT pom @@ -32,7 +32,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.0.4.RELEASE + 2.0.5.BUILD-SNAPSHOT jackson-mapper-asl @@ -127,8 +127,4 @@ - - - 2.0.4.RELEASE - diff --git a/tests/xml/vanilla/pom.xml b/tests/xml/vanilla/pom.xml index c1c5752f3..cc5842816 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.4.RELEASE + 2.0.5.BUILD-SNAPSHOT From 2ed8311913bac9a49c0d6d73574079e58b50def2 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 12 Nov 2014 07:19:59 +0000 Subject: [PATCH 337/831] Remove snapshot repos from tests --- tests/annotation/pom.xml | 44 ---------------------------------------- tests/xml/pom.xml | 44 ---------------------------------------- 2 files changed, 88 deletions(-) diff --git a/tests/annotation/pom.xml b/tests/annotation/pom.xml index 0d3081043..337313ea2 100644 --- a/tests/annotation/pom.xml +++ b/tests/annotation/pom.xml @@ -85,48 +85,4 @@ 1.7 - - - spring-snapshots - Spring Snapshots - http://repo.spring.io/libs-snapshot-local - - true - - - - spring-milestones - Spring Milestones - http://repo.spring.io/libs-milestone-local - - false - - - - spring-staging - Spring Milestones - http://repo.spring.io/libs-staging-local - - false - - - - - - spring-snapshots - Spring Snapshots - http://repo.spring.io/libs-snapshot-local - - true - - - - spring-staging - Spring Milestones - http://repo.spring.io/libs-staging-local - - false - - - diff --git a/tests/xml/pom.xml b/tests/xml/pom.xml index 811d39e5d..1f2d6c9d7 100644 --- a/tests/xml/pom.xml +++ b/tests/xml/pom.xml @@ -83,48 +83,4 @@ 1.7 - - - spring-snapshots - Spring Snapshots - http://repo.spring.io/snapshot - - true - - - - spring-milestones - Spring Milestones - http://repo.spring.io/milestone - - false - - - - spring-staging - Spring Milestones - http://repo.spring.io/libs-staging-local - - false - - - - - - spring-snapshots - Spring Snapshots - http://repo.spring.io/snapshot - - true - - - - spring-staging - Spring Milestones - http://repo.spring.io/libs-staging-local - - false - - - From 54632798f2d37195e0343926bcf64cf3181ffe5a Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 11 Nov 2014 11:18:04 +0000 Subject: [PATCH 338/831] Upgrade to Spring 4.0.8 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 992050d96..14e5aae76 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ UTF-8 - 4.0.7.RELEASE + 4.0.8.RELEASE 3.2.5.RELEASE 1.6 From 59c13e40cef31dbc03e2de1d9b402a9e8a4af2c8 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Sat, 15 Nov 2014 11:31:10 +0000 Subject: [PATCH 339/831] Use full constructor for PatternsRequestCondition Makes the FrameworkEndpointHandlerMapping more customizable in line with other handler mapping implementations. Fixes gh-312 --- .../FrameworkEndpointHandlerMapping.java | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java index a3b133af2..6f8166b9e 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java @@ -50,16 +50,18 @@ public class FrameworkEndpointHandlerMapping extends RequestMappingHandlerMappin private Set paths = new HashSet(); private String prefix; - + /** * @param prefix the prefix to set */ public void setPrefix(String prefix) { if (!StringUtils.hasText(prefix)) { prefix = ""; - } else while (prefix.endsWith("/")) { - prefix = prefix.substring(0, prefix.lastIndexOf("/")); } + else + while (prefix.endsWith("/")) { + prefix = prefix.substring(0, prefix.lastIndexOf("/")); + } this.prefix = prefix; } @@ -78,7 +80,7 @@ public void setMappings(Map patternMap) { } if (result.startsWith(REDIRECT)) { result = result.substring(REDIRECT.length()); - } + } mappings.put(key, result); } } @@ -87,9 +89,9 @@ public void setMappings(Map patternMap) { * @return the mapping from default endpoint paths to custom ones (or the default if no customization is known) */ public String getServletPath(String defaultPath) { - return (prefix == null ? "" : prefix ) + getPath(defaultPath); + return (prefix == null ? "" : prefix) + getPath(defaultPath); } - + /** * @return the mapping from default endpoint paths to custom ones (or the default if no customization is known) */ @@ -100,9 +102,9 @@ public String getPath(String defaultPath) { } return result; } - + public Set getPaths() { - return paths ; + return paths; } /** @@ -147,7 +149,8 @@ protected RequestMappingInfo getMappingForMethod(Method method, Class handler paths.add(pattern); i++; } - PatternsRequestCondition patternsInfo = new PatternsRequestCondition(patterns); + PatternsRequestCondition patternsInfo = new PatternsRequestCondition(patterns, getUrlPathHelper(), + getPathMatcher(), useSuffixPatternMatch(), useTrailingSlashMatch(), getFileExtensions()); ParamsRequestCondition paramsInfo = defaultMapping.getParamsCondition(); if (!approvalParameter.equals(OAuth2Utils.USER_OAUTH_APPROVAL) && defaultPatterns.contains("/oauth/authorize")) { From fbb13cdb04cf6f05d95bfa06cebadb0c7685b20c Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Sat, 15 Nov 2014 11:35:27 +0000 Subject: [PATCH 340/831] Add expressionHandler() to ResourceServerSecurityConfigurer Fixes gh-315 --- .../web/configurers/ResourceServerSecurityConfigurer.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java index 93c1960d5..cede35f38 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java @@ -90,6 +90,12 @@ public ResourceServerSecurityConfigurer tokenStore(TokenStore tokenStore) { return this; } + public ResourceServerSecurityConfigurer expressionHandler(SecurityExpressionHandler expressionHandler) { + Assert.state(expressionHandler != null, "SecurityExpressionHandler cannot be null"); + this.expressionHandler = expressionHandler; + return this; + } + public ResourceServerSecurityConfigurer tokenExtractor(TokenExtractor tokenExtractor) { Assert.state(tokenExtractor != null, "TokenExtractor cannot be null"); this.tokenExtractor = tokenExtractor; From ce2bc8999c008225638c4f5a2e0a1c66904f0937 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 19 Nov 2014 10:27:30 +0000 Subject: [PATCH 341/831] Add sample app for JAXB configuration (XML tokens) --- .../common/AbstractIntegrationTests.java | 33 +++-- tests/annotation/jaxb/README.md | 9 ++ tests/annotation/jaxb/pom.xml | 50 ++++++++ .../jaxb/src/main/java/demo/Application.java | 119 ++++++++++++++++++ .../jaxb/src/main/resources/application.yml | 8 ++ .../src/test/java/demo/ApplicationTests.java | 20 +++ .../demo/AuthorizationCodeProviderTests.java | 71 +++++++++++ .../demo/ClientCredentialsProviderTests.java | 28 +++++ .../jaxb/src/test/java/demo/Converters.java | 64 ++++++++++ .../test/java/demo/ImplicitProviderTests.java | 80 ++++++++++++ .../java/demo/ProtectedResourceTests.java | 35 ++++++ .../java/demo/RefreshTokenSupportTests.java | 22 ++++ .../ResourceOwnerPasswordProviderTests.java | 21 ++++ 13 files changed, 552 insertions(+), 8 deletions(-) create mode 100644 tests/annotation/jaxb/README.md create mode 100644 tests/annotation/jaxb/pom.xml create mode 100644 tests/annotation/jaxb/src/main/java/demo/Application.java create mode 100644 tests/annotation/jaxb/src/main/resources/application.yml create mode 100644 tests/annotation/jaxb/src/test/java/demo/ApplicationTests.java create mode 100755 tests/annotation/jaxb/src/test/java/demo/AuthorizationCodeProviderTests.java create mode 100644 tests/annotation/jaxb/src/test/java/demo/ClientCredentialsProviderTests.java create mode 100644 tests/annotation/jaxb/src/test/java/demo/Converters.java create mode 100644 tests/annotation/jaxb/src/test/java/demo/ImplicitProviderTests.java create mode 100644 tests/annotation/jaxb/src/test/java/demo/ProtectedResourceTests.java create mode 100644 tests/annotation/jaxb/src/test/java/demo/RefreshTokenSupportTests.java create mode 100644 tests/annotation/jaxb/src/test/java/demo/ResourceOwnerPasswordProviderTests.java 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 388caa6c7..5fb4878a5 100644 --- a/tests/annotation/common/src/main/java/sparklr/common/AbstractIntegrationTests.java +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractIntegrationTests.java @@ -13,6 +13,11 @@ package sparklr.common; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + import javax.sql.DataSource; import org.junit.After; @@ -26,6 +31,8 @@ import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.context.embedded.EmbeddedWebApplicationContext; import org.springframework.boot.test.IntegrationTest; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.http.converter.HttpMessageConverter; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.security.crypto.codec.Base64; import org.springframework.security.oauth2.client.resource.BaseOAuth2ProtectedResourceDetails; @@ -55,7 +62,7 @@ public abstract class AbstractIntegrationTests { private static String globalCheckTokenPath; private static String globalAuthorizePath; - + @Value("${local.server.port}") private int port; @@ -82,9 +89,9 @@ public abstract class AbstractIntegrationTests { @Autowired private ServerProperties server; - + @Before - public void init() { + public void init() { String prefix = server.getServletPrefix(); http.setPort(port); http.setPrefix(prefix); @@ -96,6 +103,10 @@ public void fixPaths() { http.setPort(port); http.setPrefix(prefix); BaseOAuth2ProtectedResourceDetails resource = (BaseOAuth2ProtectedResourceDetails) context.getResource(); + List> converters = new ArrayList<>(context.getRestTemplate().getMessageConverters()); + converters.addAll(getAdditionalConverters()); + context.getRestTemplate().setMessageConverters(converters); + context.getRestTemplate().setInterceptors(getInterceptors()); resource.setAccessTokenUri(http.getUrl(tokenPath())); if (resource instanceof AbstractRedirectResourceDetails) { ((AbstractRedirectResourceDetails) resource).setUserAuthorizationUri(http.getUrl(authorizePath())); @@ -109,6 +120,14 @@ public void fixPaths() { } } + protected List getInterceptors() { + return Collections.emptyList(); + } + + protected Collection> getAdditionalConverters() { + return Collections.emptySet(); + } + protected String getPassword() { return security.getUser().getPassword(); } @@ -116,9 +135,9 @@ protected String getPassword() { protected String getUsername() { return security.getUser().getName(); } - + public interface DoNotOverride { - + } @After @@ -128,9 +147,7 @@ public void close() throws Exception { } protected String getBasicAuthentication() { - return "Basic " - + new String(Base64.encode((getUsername() + ":" + getPassword()) - .getBytes())); + return "Basic " + new String(Base64.encode((getUsername() + ":" + getPassword()).getBytes())); } private void clear(ApprovalStore approvalStore) throws Exception { diff --git a/tests/annotation/jaxb/README.md b/tests/annotation/jaxb/README.md new file mode 100644 index 000000000..41216db76 --- /dev/null +++ b/tests/annotation/jaxb/README.md @@ -0,0 +1,9 @@ +This project shows what you can do with the minimum configuration to +set up an Authorization Server and Resource Server with XML serialization +of access tokens and error responses. + +You need to teach Spring how to serialize `OAuth2AccessTokens` and +`OAuth2Exceptions` using the converters provided in Spring OAuth. The +steps to do this can be seen in the server (`Application` configuration) +and also in the client (where we inject `HttpMessageConverters` into the +`RestTemplate` used to access resources in the integration tests). \ No newline at end of file diff --git a/tests/annotation/jaxb/pom.xml b/tests/annotation/jaxb/pom.xml new file mode 100644 index 000000000..8b0906805 --- /dev/null +++ b/tests/annotation/jaxb/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + + jaxb + + jaxb + Demo project + + + org.demo + spring-oauth2-tests-parent + 2.0.5.BUILD-SNAPSHOT + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.security.oauth + spring-security-oauth2 + + + org.demo + spring-oauth2-tests-common + ${project.version} + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/tests/annotation/jaxb/src/main/java/demo/Application.java b/tests/annotation/jaxb/src/main/java/demo/Application.java new file mode 100644 index 000000000..956c80ffd --- /dev/null +++ b/tests/annotation/jaxb/src/main/java/demo/Application.java @@ -0,0 +1,119 @@ +package demo; + +import java.util.ArrayList; +import java.util.List; + +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.context.annotation.Configuration; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; +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.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; +import org.springframework.security.oauth2.http.converter.jaxb.JaxbOAuth2AccessTokenMessageConverter; +import org.springframework.security.oauth2.http.converter.jaxb.JaxbOAuth2ExceptionMessageConverter; +import org.springframework.security.oauth2.provider.error.DefaultOAuth2ExceptionRenderer; +import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; +import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint; +import org.springframework.security.oauth2.provider.error.OAuth2ExceptionRenderer; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.access.AccessDeniedHandler; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +@Configuration +@ComponentScan +@EnableAutoConfiguration +@EnableResourceServer +@RestController +public class Application extends WebMvcConfigurerAdapter { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + @RequestMapping("/") + public String home() { + return "Hello World"; + } + + @Override + public void configureMessageConverters(List> converters) { + converters.add(new JaxbOAuth2AccessTokenMessageConverter()); + converters.add(new JaxbOAuth2ExceptionMessageConverter()); + } + + @Configuration + @EnableAuthorizationServer + protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter { + + @Autowired + private AuthenticationManager authenticationManager; + + @Override + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + endpoints.authenticationManager(authenticationManager); + } + + @Override + public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { + oauthServer.authenticationEntryPoint(authenticationEntryPoint()).accessDeniedHandler(accessDeniedHandler()); + } + + private AccessDeniedHandler accessDeniedHandler() { + OAuth2AccessDeniedHandler accessDeniedHandler = new OAuth2AccessDeniedHandler(); + accessDeniedHandler.setExceptionRenderer(exceptionRenderer()); + return accessDeniedHandler; + } + + private AuthenticationEntryPoint authenticationEntryPoint() { + OAuth2AuthenticationEntryPoint authenticationEntryPoint = new OAuth2AuthenticationEntryPoint(); + authenticationEntryPoint.setExceptionRenderer(exceptionRenderer()); + return authenticationEntryPoint; + } + + private OAuth2ExceptionRenderer exceptionRenderer() { + DefaultOAuth2ExceptionRenderer exceptionRenderer = new DefaultOAuth2ExceptionRenderer(); + List> converters = new ArrayList<>(); + converters.add(new JaxbOAuth2ExceptionMessageConverter()); + exceptionRenderer.setMessageConverters(converters); + return exceptionRenderer; + } + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + // @formatter:off + clients.inMemory() + .withClient("my-trusted-client") + .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit") + .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") + .scopes("read", "write", "trust") + .resourceIds("oauth2-resource") + .accessTokenValiditySeconds(60) + .and() + .withClient("my-client-with-registered-redirect") + .authorizedGrantTypes("authorization_code") + .authorities("ROLE_CLIENT") + .scopes("read", "trust") + .resourceIds("oauth2-resource") + .redirectUris("http://anywhere/?key=value") + .and() + .withClient("my-client-with-secret") + .authorizedGrantTypes("client_credentials", "password") + .authorities("ROLE_CLIENT") + .scopes("read") + .resourceIds("oauth2-resource") + .secret("secret"); + // @formatter:on + } + + } + +} diff --git a/tests/annotation/jaxb/src/main/resources/application.yml b/tests/annotation/jaxb/src/main/resources/application.yml new file mode 100644 index 000000000..a9c0149f0 --- /dev/null +++ b/tests/annotation/jaxb/src/main/resources/application.yml @@ -0,0 +1,8 @@ +spring: + application: + name: vanilla +management: + context_path: /admin +security: + user: + password: password diff --git a/tests/annotation/jaxb/src/test/java/demo/ApplicationTests.java b/tests/annotation/jaxb/src/test/java/demo/ApplicationTests.java new file mode 100644 index 000000000..15eca8da6 --- /dev/null +++ b/tests/annotation/jaxb/src/test/java/demo/ApplicationTests.java @@ -0,0 +1,20 @@ +package demo; + +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; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = Application.class) +@WebAppConfiguration +@IntegrationTest("server.port=0") +public class ApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/tests/annotation/jaxb/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/jaxb/src/test/java/demo/AuthorizationCodeProviderTests.java new file mode 100755 index 000000000..7d8889a6c --- /dev/null +++ b/tests/annotation/jaxb/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -0,0 +1,71 @@ +/* + * Copyright 2006-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 demo; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +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; + +import sparklr.common.AbstractAuthorizationCodeProviderTests; + +/** + * @author Dave Syer + */ +@SpringApplicationConfiguration(classes = Application.class) +public class AuthorizationCodeProviderTests extends AbstractAuthorizationCodeProviderTests { + + @Test + public void testWrongClientIdProvided() throws Exception { + ResponseEntity response = attemptToGetConfirmationPage("no-such-client", "http://anywhere/"); + // With no client id you get an InvalidClientException on the server which is forwarded to /oauth/error + assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); + String body = response.getBody(); + assertTrue("Wrong body: " + body, body.contains(" response = attemptToGetConfirmationPage("no-such-client", "http://anywhere/", null); + // With bad client id you get an InvalidClientException on the server which is forwarded to /oauth/error + assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); + String body = response.getBody(); + assertTrue("Wrong body: " + body, body.contains(" response = attemptToGetConfirmationPage("no-such-client", "http://anywhere/", "unsupported"); + // With bad client id you get an InvalidClientException on the server which is forwarded to /oauth/error + assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); + String body = response.getBody(); + assertTrue("Wrong body: " + body, body.contains("> getAdditionalConverters() { + return Converters.getJaxbConverters(); + } + +} diff --git a/tests/annotation/jaxb/src/test/java/demo/ClientCredentialsProviderTests.java b/tests/annotation/jaxb/src/test/java/demo/ClientCredentialsProviderTests.java new file mode 100644 index 000000000..ef9ade0cd --- /dev/null +++ b/tests/annotation/jaxb/src/test/java/demo/ClientCredentialsProviderTests.java @@ -0,0 +1,28 @@ +package demo; + +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; + +import sparklr.common.AbstractClientCredentialsProviderTests; + +/** + * @author Dave Syer + */ +@SpringApplicationConfiguration(classes=Application.class) +public class ClientCredentialsProviderTests extends AbstractClientCredentialsProviderTests { + + @Override + protected Collection> getAdditionalConverters() { + return Converters.getJaxbConverters(); + } + + @Override + protected List getInterceptors() { + return Converters.getInterceptors(); + } + +} diff --git a/tests/annotation/jaxb/src/test/java/demo/Converters.java b/tests/annotation/jaxb/src/test/java/demo/Converters.java new file mode 100644 index 000000000..e3d61a8f2 --- /dev/null +++ b/tests/annotation/jaxb/src/test/java/demo/Converters.java @@ -0,0 +1,64 @@ +/* + * Copyright 20013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package demo; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import org.springframework.http.HttpRequest; +import org.springframework.http.MediaType; +import org.springframework.http.client.ClientHttpRequestExecution; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.security.oauth2.http.converter.jaxb.JaxbOAuth2AccessTokenMessageConverter; +import org.springframework.security.oauth2.http.converter.jaxb.JaxbOAuth2ExceptionMessageConverter; + +/** + * @author Dave Syer + * + */ +public class Converters { + + public static Collection> getJaxbConverters() { + Collection> converters = new ArrayList<>(); + converters.add(new JaxbOAuth2AccessTokenMessageConverter()); + converters.add(new JaxbOAuth2ExceptionMessageConverter()); + return converters; + } + + public static List getInterceptors() { + return Arrays. asList(new AcceptHeaderInterceptor(MediaType.APPLICATION_XML)); + } + + private static class AcceptHeaderInterceptor implements ClientHttpRequestInterceptor { + + private MediaType type; + + public AcceptHeaderInterceptor(MediaType type) { + this.type = type; + } + + @Override + public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) + throws IOException { + request.getHeaders().add("Accept", type.toString()); + return execution.execute(request, body); + } + + } +} diff --git a/tests/annotation/jaxb/src/test/java/demo/ImplicitProviderTests.java b/tests/annotation/jaxb/src/test/java/demo/ImplicitProviderTests.java new file mode 100644 index 000000000..874e9ca09 --- /dev/null +++ b/tests/annotation/jaxb/src/test/java/demo/ImplicitProviderTests.java @@ -0,0 +1,80 @@ +package demo; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +import org.junit.Test; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.boot.test.TestRestTemplate; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration; +import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordResourceDetails; + +import sparklr.common.AbstractImplicitProviderTests; + +/** + * @author Dave Syer + */ +@SpringApplicationConfiguration(classes = Application.class) +public class ImplicitProviderTests extends AbstractImplicitProviderTests { + + @Test + @OAuth2ContextConfiguration(ResourceOwner.class) + public void parallelGrants() throws Exception { + getToken(); + Collection> futures = new HashSet>(); + ExecutorService pool = Executors.newFixedThreadPool(10); + for (int i = 0; i < 100; i++) { + futures.add(pool.submit(new Runnable() { + @Override + public void run() { + getToken(); + } + })); + } + for (Future future : futures) { + future.get(); + } + } + + @Override + protected Collection> getAdditionalConverters() { + return Converters.getJaxbConverters(); + } + + private void getToken() { + Map form = new LinkedHashMap(); + form.put("client_id", "my-trusted-client"); + form.put("redirect_uri", "http://foo.com/"); + form.put("response_type", "token"); + form.put("scope", "read"); + ResponseEntity response = new TestRestTemplate("user", "password") + .getForEntity( + http.getUrl("/oauth/authorize?client_id={client_id}&redirect_uri={redirect_uri}&response_type={response_type}&scope={scope}"), + Void.class, form); + assertEquals(HttpStatus.FOUND, response.getStatusCode()); + assertTrue(response.getHeaders().getLocation().toString().contains("access_token")); + } + + protected static class ResourceOwner extends ResourceOwnerPasswordResourceDetails { + public ResourceOwner(Object target) { + setClientId("my-trusted-client"); + setScope(Arrays.asList("read")); + setId(getClientId()); + setUsername("user"); + setPassword("password"); + } + } + +} diff --git a/tests/annotation/jaxb/src/test/java/demo/ProtectedResourceTests.java b/tests/annotation/jaxb/src/test/java/demo/ProtectedResourceTests.java new file mode 100644 index 000000000..d47fb4893 --- /dev/null +++ b/tests/annotation/jaxb/src/test/java/demo/ProtectedResourceTests.java @@ -0,0 +1,35 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package demo; + +import java.util.Collection; + +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.http.converter.HttpMessageConverter; + +import sparklr.common.AbstractProtectedResourceTests; + +/** + * @author Dave Syer + * + */ +@SpringApplicationConfiguration(classes = Application.class) +public class ProtectedResourceTests extends AbstractProtectedResourceTests { + + @Override + protected Collection> getAdditionalConverters() { + return Converters.getJaxbConverters(); + } + +} diff --git a/tests/annotation/jaxb/src/test/java/demo/RefreshTokenSupportTests.java b/tests/annotation/jaxb/src/test/java/demo/RefreshTokenSupportTests.java new file mode 100644 index 000000000..adcaa1326 --- /dev/null +++ b/tests/annotation/jaxb/src/test/java/demo/RefreshTokenSupportTests.java @@ -0,0 +1,22 @@ +package demo; + +import java.util.Collection; + +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.http.converter.HttpMessageConverter; + +import sparklr.common.AbstractRefreshTokenSupportTests; + +/** + * @author Ryan Heaton + * @author Dave Syer + */ +@SpringApplicationConfiguration(classes=Application.class) +public class RefreshTokenSupportTests extends AbstractRefreshTokenSupportTests { + + @Override + protected Collection> getAdditionalConverters() { + return Converters.getJaxbConverters(); + } + +} diff --git a/tests/annotation/jaxb/src/test/java/demo/ResourceOwnerPasswordProviderTests.java b/tests/annotation/jaxb/src/test/java/demo/ResourceOwnerPasswordProviderTests.java new file mode 100644 index 000000000..c41de197c --- /dev/null +++ b/tests/annotation/jaxb/src/test/java/demo/ResourceOwnerPasswordProviderTests.java @@ -0,0 +1,21 @@ +package demo; + +import java.util.Collection; + +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.http.converter.HttpMessageConverter; + +import sparklr.common.AbstractResourceOwnerPasswordProviderTests; + +/** + * @author Dave Syer + */ +@SpringApplicationConfiguration(classes=Application.class) +public class ResourceOwnerPasswordProviderTests extends AbstractResourceOwnerPasswordProviderTests { + + @Override + protected Collection> getAdditionalConverters() { + return Converters.getJaxbConverters(); + } + +} From 21d82ff0df2e149c2448daa35904ce69fae0d9fc Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 19 Nov 2014 10:43:50 +0000 Subject: [PATCH 342/831] Add support for custom exception handling in ResourceServerSecurityConfigurer ResourceServerSecurityConfigurer now has optional methods for AuthenticationEntryPoint and AccessDeniedHandler (also in the AuthorizationServerSecurityConfigurer). Fixes gh-317 --- .../ResourceServerConfiguration.java | 12 ++++- ...AuthorizationServerSecurityConfigurer.java | 6 +++ .../ResourceServerSecurityConfigurer.java | 14 ++++- .../ResourceServerConfigurationTests.java | 54 +++++++++++++------ 4 files changed, 67 insertions(+), 19 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java index 8ccfaae28..219ff2aa1 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java @@ -25,7 +25,10 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; +import org.springframework.security.authentication.AnonymousAuthenticationProvider; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity.RequestMatcherConfigurer; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; @@ -110,6 +113,13 @@ private String getRequestPath(HttpServletRequest request) { } + @Autowired + protected void init(AuthenticationManagerBuilder builder) { + if (!builder.isConfigured()) { + builder.authenticationProvider(new AnonymousAuthenticationProvider("default")); + } + } + @Override protected void configure(HttpSecurity http) throws Exception { RequestMatcherConfigurer requests = http.requestMatchers(); @@ -152,7 +162,7 @@ protected void configure(HttpSecurity http) throws Exception { } private ResourceServerTokenServices resolveTokenServices() { - if (tokenServices == null || tokenServices.length==0) { + if (tokenServices == null || tokenServices.length == 0) { return null; } if (tokenServices.length == 1) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java index 9da067e87..4be32de14 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java @@ -74,6 +74,12 @@ public AuthorizationServerSecurityConfigurer authenticationEntryPoint( return this; } + public AuthorizationServerSecurityConfigurer accessDeniedHandler( + AccessDeniedHandler accessDeniedHandler) { + this.accessDeniedHandler = accessDeniedHandler; + return this; + } + public AuthorizationServerSecurityConfigurer tokenKeyAccess(String tokenKeyAccess) { this.tokenKeyAccess = tokenKeyAccess; return this; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java index cede35f38..2c1c43363 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java @@ -84,13 +84,24 @@ public TokenStore getTokenStore() { return tokenStore; } + public ResourceServerSecurityConfigurer authenticationEntryPoint(AuthenticationEntryPoint authenticationEntryPoint) { + this.authenticationEntryPoint = authenticationEntryPoint; + return this; + } + + public ResourceServerSecurityConfigurer accessDeniedHandler(AccessDeniedHandler accessDeniedHandler) { + this.accessDeniedHandler = accessDeniedHandler; + return this; + } + public ResourceServerSecurityConfigurer tokenStore(TokenStore tokenStore) { Assert.state(tokenStore != null, "TokenStore cannot be null"); this.tokenStore = tokenStore; return this; } - public ResourceServerSecurityConfigurer expressionHandler(SecurityExpressionHandler expressionHandler) { + public ResourceServerSecurityConfigurer expressionHandler( + SecurityExpressionHandler expressionHandler) { Assert.state(expressionHandler != null, "SecurityExpressionHandler cannot be null"); this.expressionHandler = expressionHandler; return this; @@ -152,6 +163,7 @@ public void configure(HttpSecurity http) throws Exception { AuthenticationManager oauthAuthenticationManager = oauthAuthenticationManager(http); resourcesServerFilter = new OAuth2AuthenticationProcessingFilter(); + resourcesServerFilter.setAuthenticationEntryPoint(authenticationEntryPoint); resourcesServerFilter.setAuthenticationManager(oauthAuthenticationManager); if (tokenExtractor != null) { resourcesServerFilter.setTokenExtractor(tokenExtractor); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java index d57225fad..acbc7d6e5 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java @@ -17,12 +17,9 @@ import org.junit.Before; import org.junit.Test; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.mock.web.MockServletContext; -import org.springframework.security.authentication.AnonymousAuthenticationProvider; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.core.Authentication; @@ -41,6 +38,8 @@ import org.springframework.security.oauth2.provider.token.DefaultTokenServices; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; @@ -113,15 +112,25 @@ public void testCustomTokenExtractor() throws Exception { context.close(); } + @Test + public void testCustomAuthenticationEntryPoint() throws Exception { + tokenStore.storeAccessToken(token, authentication); + AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); + context.setServletContext(new MockServletContext()); + context.register(AuthenticationEntryPointContext.class); + context.refresh(); + MockMvc mvc = MockMvcBuilders.webAppContextSetup(context) + .addFilters(new DelegatingFilterProxy(context.getBean("springSecurityFilterChain", Filter.class))) + .build(); + mvc.perform(MockMvcRequestBuilders.get("/").header("Authorization", "Bearer FOO")).andExpect( + MockMvcResultMatchers.status().isFound()); + context.close(); + } + @Configuration @EnableResourceServer @EnableWebSecurity protected static class ResourceServerContext { - @Autowired - protected void init(AuthenticationManagerBuilder builder) { - builder.authenticationProvider(new AnonymousAuthenticationProvider("default")); - } - @Bean public TokenStore tokenStore() { return tokenStore; @@ -131,12 +140,28 @@ public TokenStore tokenStore() { @Configuration @EnableResourceServer @EnableWebSecurity - protected static class TokenExtractorContext extends ResourceServerConfigurerAdapter { - @Autowired - protected void init(AuthenticationManagerBuilder builder) { - builder.authenticationProvider(new AnonymousAuthenticationProvider("default")); + protected static class AuthenticationEntryPointContext extends ResourceServerConfigurerAdapter { + + @Override + public void configure(HttpSecurity http) throws Exception { + http.authorizeRequests().anyRequest().authenticated(); + } + + @Override + public void configure(ResourceServerSecurityConfigurer resources) throws Exception { + resources.authenticationEntryPoint(authenticationEntryPoint()); + } + + private AuthenticationEntryPoint authenticationEntryPoint() { + return new LoginUrlAuthenticationEntryPoint("/login"); } + } + + @Configuration + @EnableResourceServer + @EnableWebSecurity + protected static class TokenExtractorContext extends ResourceServerConfigurerAdapter { @Override public void configure(ResourceServerSecurityConfigurer resources) throws Exception { resources.tokenExtractor(new TokenExtractor() { @@ -169,11 +194,6 @@ protected ClientDetailsService clientDetailsService() { return new InMemoryClientDetailsService(); } - @Autowired - protected void init(AuthenticationManagerBuilder builder) { - builder.authenticationProvider(new AnonymousAuthenticationProvider("default")); - } - @Bean public DefaultTokenServices tokenServices() { DefaultTokenServices tokenServices = new DefaultTokenServices(); From 7c3eafb50f525c5a01745e4d9275fcc4144c4af2 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 19 Nov 2014 12:12:45 +0000 Subject: [PATCH 343/831] Add support for PasswordEncoder explicitly in AuthorizationServerSecurityConfigurer The client secrets can then be encoded at rest (e.g. in JDBC). The JdbcClientDetailsServiceBuilder also has a new convenience method to add an encoder (for encoding passwords as they go into the store). Previously users had to extend AuthorizationServerSecurityConfiguration to get the same functionality. Fixes gh-320 --- .../JdbcClientDetailsServiceBuilder.java | 21 +++++++-- .../AuthorizationServerConfigurerAdapter.java | 2 +- .../ResourceServerConfiguration.java | 1 - ...AuthorizationServerSecurityConfigurer.java | 44 ++++++++++++++++--- ...AuthorizationServerConfigurationTests.java | 28 +++++++++++- .../jdbc/src/main/java/demo/Application.java | 10 +++++ 6 files changed, 92 insertions(+), 14 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/JdbcClientDetailsServiceBuilder.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/JdbcClientDetailsServiceBuilder.java index 6458b0a58..a0e90f0fd 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/JdbcClientDetailsServiceBuilder.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/JdbcClientDetailsServiceBuilder.java @@ -20,6 +20,7 @@ import javax.sql.DataSource; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService; @@ -29,17 +30,24 @@ * @author Dave Syer * */ -public class JdbcClientDetailsServiceBuilder extends - ClientDetailsServiceBuilder { +public class JdbcClientDetailsServiceBuilder extends ClientDetailsServiceBuilder { private Set clientDetails = new HashSet(); + private DataSource dataSource; - + + private PasswordEncoder passwordEncoder; // for writing client secrets + public JdbcClientDetailsServiceBuilder dataSource(DataSource dataSource) { this.dataSource = dataSource; return this; } + public JdbcClientDetailsServiceBuilder passwordEncoder(PasswordEncoder passwordEncoder) { + this.passwordEncoder = passwordEncoder; + return this; + } + @Override protected void addClient(String clientId, ClientDetails value) { clientDetails.add(value); @@ -47,8 +55,13 @@ protected void addClient(String clientId, ClientDetails value) { @Override protected ClientDetailsService performBuild() { - Assert.state(dataSource!=null, "You need to provide a DataSource"); + Assert.state(dataSource != null, "You need to provide a DataSource"); JdbcClientDetailsService clientDetailsService = new JdbcClientDetailsService(dataSource); + if (passwordEncoder != null) { + // This is used to encode secrets as they are added to the database (if it isn't set then the user has top + // pass in pre-encoded secrets) + clientDetailsService.setPasswordEncoder(passwordEncoder); + } for (ClientDetails client : clientDetails) { clientDetailsService.addClientDetails(client); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurerAdapter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurerAdapter.java index 0b8d6de6b..147573b3e 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurerAdapter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurerAdapter.java @@ -24,7 +24,7 @@ public class AuthorizationServerConfigurerAdapter implements AuthorizationServerConfigurer { @Override - public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { + public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { } @Override diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java index 219ff2aa1..8eb8c110c 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java @@ -28,7 +28,6 @@ import org.springframework.security.authentication.AnonymousAuthenticationProvider; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity.RequestMatcherConfigurer; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java index 4be32de14..89eb9e268 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java @@ -20,8 +20,10 @@ import org.springframework.http.MediaType; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.SecurityConfigurerAdapter; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configurers.ExceptionHandlingConfigurer; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter; import org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService; @@ -34,6 +36,7 @@ import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; import org.springframework.security.web.context.NullSecurityContextRepository; import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher; +import org.springframework.util.StringUtils; import org.springframework.web.accept.ContentNegotiationStrategy; import org.springframework.web.accept.HeaderContentNegotiationStrategy; @@ -50,6 +53,8 @@ public final class AuthorizationServerSecurityConfigurer extends private AccessDeniedHandler accessDeniedHandler = new OAuth2AccessDeniedHandler(); + private PasswordEncoder passwordEncoder; // for client secrets + private String realm = "oauth2/client"; private boolean allowFormAuthenticationForClients = false; @@ -68,14 +73,18 @@ public AuthorizationServerSecurityConfigurer realm(String realm) { return this; } + public AuthorizationServerSecurityConfigurer passwordEncoder(PasswordEncoder passwordEncoder) { + this.passwordEncoder = passwordEncoder; + return this; + } + public AuthorizationServerSecurityConfigurer authenticationEntryPoint( AuthenticationEntryPoint authenticationEntryPoint) { this.authenticationEntryPoint = authenticationEntryPoint; return this; } - public AuthorizationServerSecurityConfigurer accessDeniedHandler( - AccessDeniedHandler accessDeniedHandler) { + public AuthorizationServerSecurityConfigurer accessDeniedHandler(AccessDeniedHandler accessDeniedHandler) { this.accessDeniedHandler = accessDeniedHandler; return this; } @@ -86,7 +95,7 @@ public AuthorizationServerSecurityConfigurer tokenKeyAccess(String tokenKeyAcces } public AuthorizationServerSecurityConfigurer checkTokenAccess(String checkTokenAccess) { - this.checkTokenAccess = checkTokenAccess; + this.checkTokenAccess = checkTokenAccess; return this; } @@ -101,9 +110,32 @@ public String getCheckTokenAccess() { @Override public void init(HttpSecurity http) throws Exception { registerDefaultAuthenticationEntryPoint(http); - http.userDetailsService(new ClientDetailsUserDetailsService(clientDetailsService())).securityContext() - .securityContextRepository(new NullSecurityContextRepository()).and().csrf().disable().httpBasic() - .realmName(realm); + if (passwordEncoder != null) { + http.getSharedObject(AuthenticationManagerBuilder.class) + .userDetailsService(new ClientDetailsUserDetailsService(clientDetailsService())) + .passwordEncoder(passwordEncoder()); + } + else { + http.userDetailsService(new ClientDetailsUserDetailsService(clientDetailsService())); + } + http.securityContext().securityContextRepository(new NullSecurityContextRepository()).and().csrf().disable() + .httpBasic().realmName(realm); + } + + private PasswordEncoder passwordEncoder() { + return new PasswordEncoder() { + + @Override + public boolean matches(CharSequence rawPassword, String encodedPassword) { + return StringUtils.hasText(encodedPassword) ? passwordEncoder.matches(rawPassword, encodedPassword) + : true; + } + + @Override + public String encode(CharSequence rawPassword) { + return passwordEncoder.encode(rawPassword); + } + }; } @SuppressWarnings("unchecked") diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java index 9ee92a72e..13deea468 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java @@ -38,6 +38,7 @@ import org.springframework.mock.web.MockServletContext; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; @@ -85,6 +86,7 @@ public static List parameters() { new Object[] { null, new Class[] { AuthorizationServerDisableApproval.class } }, new Object[] { null, new Class[] { AuthorizationServerExtras.class } }, new Object[] { null, new Class[] { AuthorizationServerJdbc.class } }, + new Object[] { null, new Class[] { AuthorizationServerEncoder.class } }, new Object[] { null, new Class[] { AuthorizationServerJwt.class } }, new Object[] { null, new Class[] { AuthorizationServerWithTokenServices.class } }, new Object[] { null, new Class[] { AuthorizationServerApproval.class } }, @@ -162,7 +164,7 @@ public void run() { new UsernamePasswordAuthenticationToken("user", "password")); assertTrue(request.containsKey("scopes")); - Map information = clientDetailsService.loadClientByClientId("my-trusted-client") + Map information = clientDetailsService.loadClientByClientId("my-trusted-client") .getAdditionalInformation(); assertTrue(information.containsKey("foo")); @@ -321,6 +323,28 @@ public DataSource dataSource() { } + @Configuration + @EnableWebMvcSecurity + @EnableAuthorizationServer + protected static class AuthorizationServerEncoder extends AuthorizationServerConfigurerAdapter { + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + // @formatter:off + clients.inMemory() + .withClient("my-trusted-client") + .secret(new BCryptPasswordEncoder().encode("secret")) + .authorizedGrantTypes("client_credentials"); + // @formatter:on + } + + @Override + public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { + oauthServer.passwordEncoder(new BCryptPasswordEncoder()); + } + + } + @Configuration @EnableWebMvcSecurity @EnableAuthorizationServer @@ -356,7 +380,7 @@ public void configure(ClientDetailsServiceConfigurer clients) throws Exception { @EnableWebMvcSecurity @EnableAuthorizationServer protected static class AuthorizationServerWithTokenServices extends AuthorizationServerConfigurerAdapter { - + @Autowired private ClientDetailsService clientDetailsService; diff --git a/tests/annotation/jdbc/src/main/java/demo/Application.java b/tests/annotation/jdbc/src/main/java/demo/Application.java index aa76bbf2c..603aae242 100644 --- a/tests/annotation/jdbc/src/main/java/demo/Application.java +++ b/tests/annotation/jdbc/src/main/java/demo/Application.java @@ -13,12 +13,14 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; 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.config.annotation.web.configuration.ResourceServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; import org.springframework.security.oauth2.provider.code.JdbcAuthorizationCodeServices; @@ -70,6 +72,8 @@ protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter @Autowired private DataSource dataSource; + private BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + @Bean public JdbcTokenStore tokenStore() { return new JdbcTokenStore(dataSource); @@ -79,6 +83,11 @@ public JdbcTokenStore tokenStore() { protected AuthorizationCodeServices authorizationCodeServices() { return new JdbcAuthorizationCodeServices(dataSource); } + + @Override + public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { + security.passwordEncoder(passwordEncoder); + } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { @@ -97,6 +106,7 @@ public Authentication authenticate(Authentication authentication) public void configure(ClientDetailsServiceConfigurer clients) throws Exception { // @formatter:off clients.jdbc(dataSource) + .passwordEncoder(passwordEncoder) .withClient("my-trusted-client") .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit") .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") From 1396bfc43eb42936a05992bdf75aaa6633655de0 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 19 Nov 2014 13:49:21 +0000 Subject: [PATCH 344/831] Fix documentation in XSD --- .../security/oauth2/spring-security-oauth2-2.0.xsd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-2.0.xsd b/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-2.0.xsd index 31281626b..03505a920 100644 --- a/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-2.0.xsd +++ b/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-2.0.xsd @@ -269,13 +269,13 @@ - The reference to the bean that defines the manager for + The reference to the bean that defines the factory for authorization requests from the input parameters (e.g. request parameters). Default value is an instance of - "org.springframework.security.oauth2.provider.token.DefaultAuthorizationRequestManager". + "org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory". From c6153a20a7176712d9874b2321ea9dfc3c5483a4 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 21 Nov 2014 12:04:44 +0000 Subject: [PATCH 345/831] Ensure client secret is erased from OAuth2Authentication Fixes gh-321 --- .../oauth2/provider/TokenRequest.java | 1 + ...faultAuthorizationRequestFactoryTests.java | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java index 71e1c652b..e9277ef45 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java @@ -88,6 +88,7 @@ public OAuth2Request createOAuth2Request(ClientDetails client) { HashMap modifiable = new HashMap(requestParameters); // Remove password if present to prevent leaks modifiable.remove("password"); + modifiable.remove("client_secret"); // Add grant type so it can be retrieved from OAuth2Request modifiable.put("grant_type", grantType); return new OAuth2Request(modifiable, client.getClientId(), client.getAuthorities(), true, this.getScope(), diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/request/DefaultAuthorizationRequestFactoryTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/request/DefaultAuthorizationRequestFactoryTests.java index dc05f8c04..61daf0520 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/request/DefaultAuthorizationRequestFactoryTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/request/DefaultAuthorizationRequestFactoryTests.java @@ -14,6 +14,7 @@ package org.springframework.security.oauth2.provider.request; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import java.util.Arrays; import java.util.Collections; @@ -105,6 +106,26 @@ public void testCreateTokenThenOAuth2RequestWithGrantType() { assertEquals("[bar]", request.getResourceIds().toString()); } + @Test + public void testPasswordErased() { + factory.setCheckUserScopes(true); + Map params = new HashMap(Collections.singletonMap("client_id", "foo")); + params.put("password", "shhh"); + AuthorizationRequest auth = factory.createAuthorizationRequest(params); + OAuth2Request request = factory.createTokenRequest(auth, "password").createOAuth2Request(client); + assertNull(request.getRequestParameters().get("password")); + } + + @Test + public void testSecretErased() { + factory.setCheckUserScopes(true); + Map params = new HashMap(Collections.singletonMap("client_id", "foo")); + params.put("client_secret", "shhh"); + AuthorizationRequest auth = factory.createAuthorizationRequest(params); + OAuth2Request request = factory.createTokenRequest(auth, "client_credentials").createOAuth2Request(client); + assertNull(request.getRequestParameters().get("client_secret")); + } + @Test public void testCreateAuthorizationRequestWhenUserNotPermitted() { SecurityContextHolder.getContext().setAuthentication( From 2f69d29d52fb94a23832b11fb73da2d95265273f Mon Sep 17 00:00:00 2001 From: Josh Long Date: Sat, 15 Nov 2014 18:16:59 -0800 Subject: [PATCH 346/831] first commit --- .../security/oauth/common/OAuthCodec.java | 1 + .../security/oauth/common/StringSplitUtils.java | 11 +++++++---- .../common/signature/RSA_SHA1SignatureMethod.java | 6 +++--- .../oauth/common/signature/SharedConsumerSecret.java | 2 +- .../security/oauth/consumer/OAuthConsumerSupport.java | 8 ++++---- .../consumer/filter/OAuthConsumerContextFilter.java | 6 +++++- .../filter/OAuthConsumerProcessingFilter.java | 6 +++--- .../oauth/provider/ExtraTrustConsumerDetails.java | 5 ++--- .../filter/OAuthProviderProcessingFilter.java | 8 +++++--- .../filter/UserAuthorizationProcessingFilter.java | 10 +++++----- .../nonce/ExpiringTimestampNonceServices.java | 2 +- .../oauth/provider/nonce/InMemoryNonceServices.java | 5 ++--- .../token/RandomValueProviderTokenServices.java | 8 +++----- 13 files changed, 42 insertions(+), 36 deletions(-) diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/OAuthCodec.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/OAuthCodec.java index 9390ab54a..44ee7fc3b 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/OAuthCodec.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/OAuthCodec.java @@ -67,6 +67,7 @@ public static String oauthEncode(String value) { * * @param value The value to decode. * @return The decoded value. + * @throws DecoderException when URLCodec fails */ public static String oauthDecode(String value) throws DecoderException { if (value == null) { diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/StringSplitUtils.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/StringSplitUtils.java index 125389211..87ed8e914 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/StringSplitUtils.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/StringSplitUtils.java @@ -16,8 +16,8 @@ public class StringSplitUtils { private static final String[] EMPTY_STRING_ARRAY = new String[0]; /** - * Splits a String at the first instance of the delimiter.

    Does not include the delimiter in - * the response.

    + * Splits a String at the first instance of the delimiter. Does not include the delimiter in + * the response. * * @param toSplit the string to split * @param delimiter to split the string up with @@ -49,7 +49,7 @@ public static String[] split(String toSplit, String delimiter) { * Takes an array of Strings, and for each element removes any instances of * removeCharacter, and splits the element based on the delimiter. A Map is * then generated, with the left of the delimiter providing the key, and the right of the delimiter providing the - * value.

    Will trim both the key and value before adding to the Map.

    + * value. Will trim both the key and value before adding to the Map. * * @param array the array to process * @param delimiter to split each element using (typically the equals symbol) @@ -90,8 +90,11 @@ public static Map splitEachArrayElementAndCreateMap(String[] arr * Splits a given string on the given separator character, skips the contents of quoted substrings * when looking for separators. * Introduced for use in DigestProcessingFilter (see SEC-506). - *

    + * * This was copied and modified from commons-lang StringUtils + * @param str the string to split + * @param separatorChar the character by which to split the string + * @return String array containing split string */ public static String[] splitIgnoringQuotes(String str, char separatorChar) { if (str == null) { diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/RSA_SHA1SignatureMethod.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/RSA_SHA1SignatureMethod.java index 8de859e3f..27a63419f 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/RSA_SHA1SignatureMethod.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/RSA_SHA1SignatureMethod.java @@ -79,9 +79,9 @@ public String getName() { /** * The Signature Base String is signed using the Consumer’s RSA private key per RFC3447 section 8.2.1, where K is the Consumer’s RSA private key, - * M the Signature Base String, and S is the result signature octet string:

    + * M the Signature Base String, and S is the result signature octet string: * - * S = RSASSA-PKCS1-V1_5-SIGN (K, M)

    + * {@code S = RSASSA-PKCS1-V1_5-SIGN (K, M) } * * oauth_signature is set to S, first base64-encoded per RFC2045 section 6.8, then URL-encoded per Parameter Encoding. * @@ -172,4 +172,4 @@ public PrivateKey getPrivateKey() { public PublicKey getPublicKey() { return publicKey; } -} \ No newline at end of file +} diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/SharedConsumerSecret.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/SharedConsumerSecret.java index c2ac4f6c1..62423232e 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/SharedConsumerSecret.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/SharedConsumerSecret.java @@ -20,7 +20,7 @@ * A signature secret that consists of a consumer secret and a token secret. * * @author Ryan Heaton - * @author + * @author Aliaksandr Autayeu */ public interface SharedConsumerSecret extends SignatureSecret { diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/OAuthConsumerSupport.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/OAuthConsumerSupport.java index 701a1b9e7..38c3dd851 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/OAuthConsumerSupport.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/OAuthConsumerSupport.java @@ -45,7 +45,7 @@ public interface OAuthConsumerSupport { * @return The unauthorized request token. */ OAuthConsumerToken getUnauthorizedRequestToken(ProtectedResourceDetails resource, String callback) throws OAuthRequestFailedException; - + /** * Get an access token for a protected resource. * @@ -64,7 +64,7 @@ public interface OAuthConsumerSupport { * @return The access token. */ OAuthConsumerToken getAccessToken(ProtectedResourceDetails resource, OAuthConsumerToken requestToken, String verifier); - + /** * Read a protected resource from the given URL using the specified access token and HTTP method. * @@ -104,9 +104,9 @@ public interface OAuthConsumerSupport { * Get the query string that is to be used in the given request. The query string will * include any custom query parameters in the URL and any necessary OAuth parameters. Note, * however, that an OAuth parameter is not considered "necessary" if the provider of the resource - * supports the authorization header.

    + * supports the authorization header. * - * Any OAuth parameters will be URL-encoded, but not oauth-encoded, per the OAuth spec.

    + * Any OAuth parameters will be URL-encoded, but not oauth-encoded, per the OAuth spec. * * The query string is to be used by either applying it to the URL (for HTTP GET) or putting it * in the body of the request (for HTTP POST). diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/filter/OAuthConsumerContextFilter.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/filter/OAuthConsumerContextFilter.java index c8fd4566a..8fb413a1a 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/filter/OAuthConsumerContextFilter.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/filter/OAuthConsumerContextFilter.java @@ -250,6 +250,8 @@ else if (ex instanceof RuntimeException) { * * @param ex The exception. * @return The resource that needed authorization (never null). + * @throws ServletException in the case of an underlying Servlet API exception + * @throws IOException in the case of general IO exceptions */ protected ProtectedResourceDetails checkForResourceThatNeedsAuthorization(Exception ex) throws ServletException, IOException { Throwable[] causeChain = getThrowableAnalyzer().determineCauseChain(ex); @@ -322,6 +324,8 @@ protected String getUserAuthorizationRedirectURL(ProtectedResourceDetails detail * @param request The request. * @param response The response. * @param failure The failure. + * @throws ServletException in the case of an underlying Servlet API exception + * @throws IOException in the case of general IO exceptions */ protected void fail(HttpServletRequest request, HttpServletResponse response, OAuthRequestFailedException failure) throws IOException, ServletException { try { @@ -516,4 +520,4 @@ public Throwable extractCause(Throwable throwable) { }); } } -} \ No newline at end of file +} diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/filter/OAuthConsumerProcessingFilter.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/filter/OAuthConsumerProcessingFilter.java index a23e9731e..d8aa8d900 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/filter/OAuthConsumerProcessingFilter.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/filter/OAuthConsumerProcessingFilter.java @@ -48,8 +48,8 @@ import java.util.TreeSet; /** - * OAuth consumer processing filter. This filter should be applied to requests for OAuth protected resources (see OAuth Core 1.0).

    - *

    + * OAuth consumer processing filter. This filter should be applied to requests for OAuth protected resources (see OAuth Core 1.0). + * * When servicing a request that requires protected resources, this filter sets a request attribute (default "OAUTH_ACCESS_TOKENS") that contains * the list of {@link org.springframework.security.oauth.consumer.OAuthConsumerToken}s. * @@ -200,4 +200,4 @@ public void setRequireAuthenticated(boolean requireAuthenticated) { this.requireAuthenticated = requireAuthenticated; } -} \ No newline at end of file +} diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ExtraTrustConsumerDetails.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ExtraTrustConsumerDetails.java index d67d3e0f8..8c82ae5d3 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ExtraTrustConsumerDetails.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ExtraTrustConsumerDetails.java @@ -27,11 +27,10 @@ public interface ExtraTrustConsumerDetails extends ConsumerDetails { * Whether this consumer is required to obtain an authenticated oauth token. If true, it means that the OAuth consumer won't be granted access * to the protected resource unless the user is directed to the token authorization page. If false, it means that the provider has an additional * level of trust with the consumer. - *
    - *
    + * * Not requiring an authenticated access token is also known as "2-legged" OAuth or "signed fetch". * * @return Whether this consumer is required to obtain an authenticated oauth token. */ boolean isRequiredToObtainAuthenticatedToken(); -} \ No newline at end of file +} diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/OAuthProviderProcessingFilter.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/OAuthProviderProcessingFilter.java index 46f69e13b..8b6055584 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/OAuthProviderProcessingFilter.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/OAuthProviderProcessingFilter.java @@ -55,7 +55,7 @@ import java.util.Map; /** - * OAuth processing filter. This filter should be applied to requests for OAuth protected resources (see OAuth Core 1.0).

    + * OAuth processing filter. This filter should be applied to requests for OAuth protected resources (see OAuth Core 1.0). * * @author Ryan Heaton */ @@ -117,7 +117,7 @@ public void doFilter(ServletRequest servletRequest, ServletResponse servletRespo } log.debug(builder.toString()); } - + String consumerKey = oauthParams.get(OAuthConsumerParameter.oauth_consumer_key.toString()); if (consumerKey == null) { throw new InvalidOAuthParametersException(messages.getMessage("OAuthProcessingFilter.missingConsumerKey", "Missing consumer key.")); @@ -278,7 +278,7 @@ protected void validateSignature(ConsumerAuthentication authentication) throws A /** * Logic executed on valid signature. The security context can be assumed to hold a verified, authenticated - * {@link org.springframework.security.oauth.provider.ConsumerAuthentication}.

    + * {@link org.springframework.security.oauth.provider.ConsumerAuthentication} * * Default implementation continues the chain. * @@ -365,6 +365,8 @@ protected void onNewTimestamp() throws AuthenticationException { * @param request The request. * @param response The response. * @param failure The failure. + * @throws IOException thrown when there's an underlying IO exception + * @throws ServletException thrown in the case of an underlying Servlet exception */ protected void fail(HttpServletRequest request, HttpServletResponse response, AuthenticationException failure) throws IOException, ServletException { SecurityContextHolder.getContext().setAuthentication(null); diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/UserAuthorizationProcessingFilter.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/UserAuthorizationProcessingFilter.java index 7e42ab718..3e8b81e48 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/UserAuthorizationProcessingFilter.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/UserAuthorizationProcessingFilter.java @@ -34,11 +34,11 @@ /** * Processing filter for handling a request to authenticate an OAuth request token. The default {@link #setFilterProcessesUrl(String) processes URL} - * is "/oauth_authenticate_token"

    - *

    + * is "/oauth_authenticate_token". + * * This filter looks for one request parameter for the token id that is being authorized. The - * default name of the paramaters is "requestToken", but this can be configured.

    - *

    + * default name of the paramaters is "requestToken", but this can be configured. + * * @author Ryan Heaton * @author Andrew McCall */ @@ -172,4 +172,4 @@ public void setRequire10a(boolean require10a) { this.require10a = require10a; } -} \ No newline at end of file +} diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/nonce/ExpiringTimestampNonceServices.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/nonce/ExpiringTimestampNonceServices.java index 9b10ade5e..bfaf53972 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/nonce/ExpiringTimestampNonceServices.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/nonce/ExpiringTimestampNonceServices.java @@ -22,7 +22,7 @@ /** * Nonce services that only validates the timestamp of a consumer request. The nonce - * is not checked for replay attacks.

    + * is not checked for replay attacks. * * The timestamp is interpreted as the number of seconds from January 1, 1970 00:00:00 GMT. If the timestamp * is older than the configured validity window, the nonce is not valid. The default validity window is diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/nonce/InMemoryNonceServices.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/nonce/InMemoryNonceServices.java index cae26e37a..dce75709e 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/nonce/InMemoryNonceServices.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/nonce/InMemoryNonceServices.java @@ -24,9 +24,8 @@ /** * Expands on the {@link org.springframework.security.oauth.provider.nonce.ExpiringTimestampNonceServices} to include - * validation of the nonce for replay protection.
    - *
    - * + * validation of the nonce for replay protection. + * * To validate the nonce, the InMemoryNonceService first validates the consumer key and timestamp as does the * {@link org.springframework.security.oauth.provider.nonce.ExpiringTimestampNonceServices}. Assuming the consumer and * timestamp are valid, the InMemoryNonceServices further ensures that the specified nonce was not used with the diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/RandomValueProviderTokenServices.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/RandomValueProviderTokenServices.java index e0ed98ad2..8ae12b88f 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/RandomValueProviderTokenServices.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/RandomValueProviderTokenServices.java @@ -27,11 +27,10 @@ /** * Base implementation for token services that uses random values to generate tokens. Only the persistence mechanism - * is left unimplemented.

    + * is left unimplemented. * * This base implementation creates tokens that have an expiration. For request tokens, the default validity is - * 10 minutes. For access tokens, the default validity is 12 hours.

    - * + * 10 minutes. For access tokens, the default validity is 12 hours. * * @author Ryan Heaton */ @@ -70,7 +69,6 @@ public abstract class RandomValueProviderTokenServices implements OAuthProviderT /** * Initialze these token services. If no random generator is set, one will be created. * - * @throws Exception */ public void afterPropertiesSet() throws Exception { if (random == null) { @@ -97,7 +95,7 @@ else if (isExpired(tokenImpl)) { * Whether the auth token is expired. * * @param authToken The auth token to check for expiration. - * @return Whether the auth token is expired. + * @return Whether the auth token is expired. */ protected boolean isExpired(OAuthProviderTokenImpl authToken) { if (authToken.isAccessToken()) { From dd1ba7cb2795bb478adfaac104164dda11e826fa Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 1 Dec 2014 15:59:45 +0000 Subject: [PATCH 347/831] Remove unecessary GlobalAuthenticationConfigurer The client details authentication configuration as it was confuses Spring Boot autoconfig. It looks unecessary anyway, so this change removes the GlobalAuthenticationConfigurer and upgrades Spring Boot in the tests. --- .../AuthorizationServerSecurityConfiguration.java | 6 ------ ...sts.java => JwtAccessTokenConverterTests.java} | 15 ++++++++++++++- tests/annotation/pom.xml | 2 +- .../vanilla/src/main/resources/application.yml | 3 +++ tests/xml/pom.xml | 2 +- 5 files changed, 19 insertions(+), 9 deletions(-) rename spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/{JwtTokenEnhancerTests.java => JwtAccessTokenConverterTests.java} (89%) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java index 2f235baa8..540204b66 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java @@ -22,7 +22,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.core.annotation.Order; -import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.configuration.ClientDetailsServiceConfiguration; @@ -50,11 +49,6 @@ public class AuthorizationServerSecurityConfiguration extends WebSecurityConfigu @Autowired private AuthorizationServerEndpointsConfiguration endpoints; - @Configuration - protected static class ClientDetailsAuthenticationManagerConfiguration extends - GlobalAuthenticationConfigurerAdapter { - } - @Autowired public void configure(ClientDetailsServiceConfigurer clientDetails) throws Exception { for (AuthorizationServerConfigurer configurer : configurers) { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtTokenEnhancerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverterTests.java similarity index 89% rename from spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtTokenEnhancerTests.java rename to spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverterTests.java index 8d99840f2..22936b98d 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtTokenEnhancerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverterTests.java @@ -35,7 +35,7 @@ * @author Dave Syer * @author Luke Taylor */ -public class JwtTokenEnhancerTests { +public class JwtAccessTokenConverterTests { private JwtAccessTokenConverter tokenEnhancer; @@ -101,6 +101,7 @@ public void rsaKeyCreatesValidRsaSignedTokens() throws Exception { OAuth2Authentication authentication = new OAuth2Authentication(createOAuth2Request("foo", null), userAuthentication); OAuth2AccessToken token = tokenEnhancer.enhance(new DefaultOAuth2AccessToken("FOO"), authentication); + System.err.println(token.getValue()); JwtHelper.decodeAndVerify(token.getValue(), new RsaVerifier(rsaKey)); } @@ -148,6 +149,18 @@ public void rsaKeyPair() throws Exception { assertTrue(tokenEnhancer.getKey().get("value").contains("BEGIN PUBLIC")); } + @Test + public void publicKeyOnlyAllowedForVerification() throws Exception { + tokenEnhancer.setVerifierKey("-----BEGIN RSA PUBLIC KEY-----\n" + + "MGgCYQDk3m+AGfjcDrT4fspyIBqmulFjVXuiciYvpaD5j2XaR7c6Krm5wsBLOiUo\n" + + "kmd6wbrRAMPMpoC1eogWNNoXY7Jd4eWdDVmscfHczGX13uBKXwdOCEqKqoWQsXIb\n" + "7kgz+HkCAwEAAQ==\n" + + "-----END RSA PUBLIC KEY-----"); + tokenEnhancer.afterPropertiesSet(); + tokenEnhancer.decode("eyJhbGciOiJSUzI1NiJ9.eyJ1c2VyX25hbWUiOiJ0ZXN0MiIsImp0aSI6IkZPTyIsImNsaWVudF9pZCI6ImZvbyJ9.b43ob1ALSIwr_J2oEnfMhsXvYkr1qVBNhigNH2zlaE1OQLhLfT-DMlFtHcyUlyap0C2n0q61SPaGE_z715TV0uTAv2YKDN4fKZz2bMR7eHLsvaaCuvs7KCOi_aSROaUG"); + Map key = tokenEnhancer.getKey(); + assertTrue("Wrong key: " + key, key.get("value").contains("-----BEGIN")); + } + private OAuth2Request createOAuth2Request(String clientId, Set scope) { return new OAuth2Request(Collections. emptyMap(), clientId, null, true, scope, null, null, null, null); diff --git a/tests/annotation/pom.xml b/tests/annotation/pom.xml index 337313ea2..cf430b0ad 100644 --- a/tests/annotation/pom.xml +++ b/tests/annotation/pom.xml @@ -26,7 +26,7 @@ org.springframework.boot spring-boot-starter-parent - 1.1.7.RELEASE + 1.1.9.RELEASE diff --git a/tests/annotation/vanilla/src/main/resources/application.yml b/tests/annotation/vanilla/src/main/resources/application.yml index a9c0149f0..a7c74036e 100644 --- a/tests/annotation/vanilla/src/main/resources/application.yml +++ b/tests/annotation/vanilla/src/main/resources/application.yml @@ -6,3 +6,6 @@ management: security: user: password: password +logging: + level: + org.springframework.security: DEBUG \ No newline at end of file diff --git a/tests/xml/pom.xml b/tests/xml/pom.xml index 1f2d6c9d7..80b2c2941 100644 --- a/tests/xml/pom.xml +++ b/tests/xml/pom.xml @@ -24,7 +24,7 @@ org.springframework.boot spring-boot-starter-parent - 1.1.7.RELEASE + 1.1.9.RELEASE From 793ebe0a08b57f90b3c78147a21f36822ba3feab Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 16 Dec 2014 11:55:29 +0000 Subject: [PATCH 348/831] Add convenience method for reuseRefreshToken() Longer term (2.1.0) we should pull out the toke service builing into a separate builder. It's too big a change for a point release though. Fixes gh-318 --- .../AuthorizationServerEndpointsConfigurer.java | 8 ++++++++ 1 file changed, 8 insertions(+) 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 92e44d755..b06e9b484 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 @@ -107,6 +107,8 @@ public final class AuthorizationServerEndpointsConfigurer { private boolean tokenServicesOverride = false; + private boolean reuseRefreshToken; + public AuthorizationServerTokenServices getTokenServices() { return tokenServices; } @@ -153,6 +155,11 @@ public AuthorizationServerEndpointsConfigurer tokenEnhancer(TokenEnhancer tokenE return this; } + public AuthorizationServerEndpointsConfigurer reuseRefreshTokens() { + this.reuseRefreshToken = true; + return this; + } + public AuthorizationServerEndpointsConfigurer accessTokenConverter(AccessTokenConverter accessTokenConverter) { this.accessTokenConverter = accessTokenConverter; return this; @@ -307,6 +314,7 @@ private DefaultTokenServices createDefaultTokenServices() { DefaultTokenServices tokenServices = new DefaultTokenServices(); tokenServices.setTokenStore(tokenStore()); tokenServices.setSupportRefreshToken(true); + tokenServices.setReuseRefreshToken(reuseRefreshToken); tokenServices.setClientDetailsService(clientDetailsService()); tokenServices.setTokenEnhancer(tokenEnhancer()); return tokenServices; From b86edc8c73b6391087c77e0053ff520868910d5f Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 17 Dec 2014 09:35:28 +0000 Subject: [PATCH 349/831] Remove the @Bean TokenStore from default configuration Previously the AuthorizationServerConfiguration had exposed a TokenStore as a @Bean, mainly as a convenience for a ResourceServerConfiguration that happened to be in the same context. The problem is that there's a potential cycle if the user defines their own @Bean TokenStore, and uses it to configure a Resource Server, when it also happens to be part of an Authorization Server. Fixes gh-338 --- ...orizationServerEndpointsConfiguration.java | 28 ++++++++----------- .../ResourceServerConfiguration.java | 5 ++-- .../ResourceServerConfigurationTests.java | 15 ++++++++-- .../src/test/java/demo/ApplicationTests.java | 12 +++++--- 4 files changed, 34 insertions(+), 26 deletions(-) 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 2713290bc..1c5569e33 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 @@ -45,7 +45,6 @@ import org.springframework.security.oauth2.provider.endpoint.WhitelabelErrorEndpoint; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; import org.springframework.security.oauth2.provider.token.ConsumerTokenServices; -import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; /** @@ -80,7 +79,7 @@ public void init() { @Bean public AuthorizationEndpoint authorizationEndpoint() throws Exception { AuthorizationEndpoint authorizationEndpoint = new AuthorizationEndpoint(); - FrameworkEndpointHandlerMapping mapping = getEndpoints().getFrameworkEndpointHandlerMapping(); + FrameworkEndpointHandlerMapping mapping = getEndpointsConfigurer().getFrameworkEndpointHandlerMapping(); authorizationEndpoint.setUserApprovalPage(extractPath(mapping, "/oauth/confirm_access")); authorizationEndpoint.setErrorPage(extractPath(mapping, "/oauth/error")); authorizationEndpoint.setTokenGranter(tokenGranter()); @@ -104,8 +103,8 @@ public TokenEndpoint tokenEndpoint() throws Exception { @Bean public CheckTokenEndpoint checkTokenEndpoint() { - CheckTokenEndpoint endpoint = new CheckTokenEndpoint(getEndpoints().getResourceServerTokenServices()); - endpoint.setAccessTokenConverter(getEndpoints().getAccessTokenConverter()); + CheckTokenEndpoint endpoint = new CheckTokenEndpoint(getEndpointsConfigurer().getResourceServerTokenServices()); + endpoint.setAccessTokenConverter(getEndpointsConfigurer().getAccessTokenConverter()); return endpoint; } @@ -121,12 +120,12 @@ public WhitelabelErrorEndpoint whitelabelErrorEndpoint() { @Bean public FrameworkEndpointHandlerMapping oauth2EndpointHandlerMapping() throws Exception { - return getEndpoints().getFrameworkEndpointHandlerMapping(); + return getEndpointsConfigurer().getFrameworkEndpointHandlerMapping(); } @Bean public ConsumerTokenServices consumerTokenServices() throws Exception { - return getEndpoints().getConsumerTokenServices(); + return getEndpointsConfigurer().getConsumerTokenServices(); } /** @@ -141,12 +140,7 @@ public AuthorizationServerTokenServices defaultAuthorizationServerTokenServices( return endpoints.getDefaultAuthorizationServerTokenServices(); } - @Bean - public TokenStore tokenStore() throws Exception { - return getEndpoints().getTokenStore(); - } - - private AuthorizationServerEndpointsConfigurer getEndpoints() { + public AuthorizationServerEndpointsConfigurer getEndpointsConfigurer() { if (!endpoints.isTokenServicesOverride()) { endpoints.tokenServices(defaultAuthorizationServerTokenServices()); } @@ -154,23 +148,23 @@ private AuthorizationServerEndpointsConfigurer getEndpoints() { } private OAuth2RequestFactory oauth2RequestFactory() throws Exception { - return getEndpoints().getOAuth2RequestFactory(); + return getEndpointsConfigurer().getOAuth2RequestFactory(); } private UserApprovalHandler userApprovalHandler() throws Exception { - return getEndpoints().getUserApprovalHandler(); + return getEndpointsConfigurer().getUserApprovalHandler(); } private OAuth2RequestValidator oauth2RequestValidator() throws Exception { - return getEndpoints().getOAuth2RequestValidator(); + return getEndpointsConfigurer().getOAuth2RequestValidator(); } private AuthorizationCodeServices authorizationCodeServices() throws Exception { - return getEndpoints().getAuthorizationCodeServices(); + return getEndpointsConfigurer().getAuthorizationCodeServices(); } private TokenGranter tokenGranter() throws Exception { - return getEndpoints().getTokenGranter(); + return getEndpointsConfigurer().getTokenGranter(); } private String extractPath(FrameworkEndpointHandlerMapping mapping, String page) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java index 8eb8c110c..8518bc6fb 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java @@ -149,10 +149,11 @@ protected void configure(HttpSecurity http) throws Exception { ResourceServerTokenServices services = resolveTokenServices(); if (services != null) { resources.tokenServices(services); - } - else { + } else { if (tokenStore != null) { resources.tokenStore(tokenStore); + } else if (endpoints!=null) { + resources.tokenStore(endpoints.getEndpointsConfigurer().getTokenStore()); } } for (ResourceServerConfigurer configurer : configurers) { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java index acbc7d6e5..1fc87ae8b 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java @@ -12,6 +12,8 @@ */ package org.springframework.security.oauth2.config.annotation; +import java.util.Collections; + import javax.servlet.Filter; import javax.servlet.http.HttpServletRequest; @@ -80,6 +82,8 @@ public void testDefaults() throws Exception { .addFilters(new DelegatingFilterProxy(context.getBean("springSecurityFilterChain", Filter.class))) .build(); mvc.perform(MockMvcRequestBuilders.get("/")).andExpect(MockMvcResultMatchers.status().isUnauthorized()); + mvc.perform(MockMvcRequestBuilders.get("/").header("Authorization", "Bearer FOO")).andExpect( + MockMvcResultMatchers.status().isNotFound()); context.close(); } @@ -94,6 +98,8 @@ public void testCustomTokenServices() throws Exception { .addFilters(new DelegatingFilterProxy(context.getBean("springSecurityFilterChain", Filter.class))) .build(); mvc.perform(MockMvcRequestBuilders.get("/")).andExpect(MockMvcResultMatchers.status().isUnauthorized()); + mvc.perform(MockMvcRequestBuilders.get("/").header("Authorization", "Bearer FOO")).andExpect( + MockMvcResultMatchers.status().isNotFound()); context.close(); } @@ -146,7 +152,7 @@ protected static class AuthenticationEntryPointContext extends ResourceServerCon public void configure(HttpSecurity http) throws Exception { http.authorizeRequests().anyRequest().authenticated(); } - + @Override public void configure(ResourceServerSecurityConfigurer resources) throws Exception { resources.authenticationEntryPoint(authenticationEntryPoint()); @@ -170,7 +176,7 @@ public void configure(ResourceServerSecurityConfigurer resources) throws Excepti public Authentication extract(HttpServletRequest request) { return new PreAuthenticatedAuthenticationToken("FOO", "N/A"); } - }); + }).tokenStore(tokenStore()); } @Override @@ -191,7 +197,10 @@ protected static class TokenServicesContext { @Bean protected ClientDetailsService clientDetailsService() { - return new InMemoryClientDetailsService(); + InMemoryClientDetailsService service = new InMemoryClientDetailsService(); + service.setClientDetailsStore(Collections.singletonMap("client", new BaseClientDetails("client", null, + null, null, null))); + return service; } @Bean diff --git a/tests/annotation/jwt/src/test/java/demo/ApplicationTests.java b/tests/annotation/jwt/src/test/java/demo/ApplicationTests.java index e7dd671c2..5f0076c88 100644 --- a/tests/annotation/jwt/src/test/java/demo/ApplicationTests.java +++ b/tests/annotation/jwt/src/test/java/demo/ApplicationTests.java @@ -5,12 +5,14 @@ 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.boot.test.IntegrationTest; import org.springframework.boot.test.SpringApplicationConfiguration; -import org.springframework.security.oauth2.provider.token.TokenStore; +import org.springframework.security.oauth2.provider.token.DefaultTokenServices; 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.util.ReflectionTestUtils; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class) @@ -19,11 +21,13 @@ public class ApplicationTests { @Autowired - private TokenStore tokenStore; + @Qualifier("defaultAuthorizationServerTokenServices") + private DefaultTokenServices tokenServices; @Test - public void contextLoads() { - assertTrue("Wrong token store type: " + tokenStore, tokenStore instanceof JwtTokenStore); + public void tokenStoreIsJwt() { + assertTrue("Wrong token store type: " + tokenServices, + ReflectionTestUtils.getField(tokenServices, "tokenStore") instanceof JwtTokenStore); } } From fad4785a59d684a78cb9bed6adee41c6fb07a766 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 17 Dec 2014 14:25:14 +0000 Subject: [PATCH 350/831] Remove builder convenience method for ClientDetailsService The AuthorizationServerEndpointsConfigurer had a clientDetails() method that was supposed to be for internal use (but unfortunately had to be public so it can be called by a class in another package). Without changing the packaging, the safest change at this point (even though it's a public API) is to change the method signature and document it to make it clear that it's not public. Fixes gh-336 --- ...orizationServerEndpointsConfiguration.java | 2 +- ...uthorizationServerEndpointsConfigurer.java | 17 +++++++----- ...AuthorizationServerConfigurationTests.java | 27 +++++++++++++++++-- 3 files changed, 37 insertions(+), 9 deletions(-) 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 1c5569e33..83976c92f 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 @@ -73,7 +73,7 @@ public void init() { throw new IllegalStateException("Cannot configure enpdoints", e); } } - endpoints.clientDetailsService(clientDetailsService); + endpoints.setClientDetailsService(clientDetailsService); } @Bean 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 b06e9b484..22e1ed814 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 @@ -21,6 +21,8 @@ import java.util.Map; import org.springframework.security.authentication.AuthenticationManager; +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; @@ -167,10 +169,10 @@ public AuthorizationServerEndpointsConfigurer accessTokenConverter(AccessTokenCo public AuthorizationServerEndpointsConfigurer tokenServices(AuthorizationServerTokenServices tokenServices) { this.tokenServices = tokenServices; - this.tokenServicesOverride = true; + this.tokenServicesOverride = true; return this; } - + public boolean isTokenServicesOverride() { return tokenServicesOverride; } @@ -229,9 +231,12 @@ public AuthorizationServerEndpointsConfigurer tokenGranter(TokenGranter tokenGra return this; } - public AuthorizationServerEndpointsConfigurer clientDetailsService(ClientDetailsService clientDetailsService) { + /** + * N.B. this method is not part of the public API. To set up a custom ClientDetailsService please use + * {@link AuthorizationServerConfigurerAdapter#configure(ClientDetailsServiceConfigurer)}. + */ + public void setClientDetailsService(ClientDetailsService clientDetailsService) { this.clientDetailsService = clientDetailsService; - return this; } public AuthorizationServerEndpointsConfigurer requestFactory(OAuth2RequestFactory requestFactory) { @@ -301,9 +306,9 @@ private AuthorizationServerTokenServices tokenServices() { this.tokenServices = createDefaultTokenServices(); return tokenServices; } - + public AuthorizationServerTokenServices getDefaultAuthorizationServerTokenServices() { - if (defaultTokenServices !=null) { + if (defaultTokenServices != null) { return defaultTokenServices; } this.defaultTokenServices = createDefaultTokenServices(); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java index 13deea468..9c838867b 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java @@ -51,6 +51,7 @@ import org.springframework.security.oauth2.provider.approval.TokenApprovalStore; import org.springframework.security.oauth2.provider.approval.UserApprovalHandler; import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenGranter; +import org.springframework.security.oauth2.provider.client.InMemoryClientDetailsService; import org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; import org.springframework.security.oauth2.provider.token.DefaultTokenServices; @@ -89,7 +90,8 @@ public static List parameters() { new Object[] { null, new Class[] { AuthorizationServerEncoder.class } }, new Object[] { null, new Class[] { AuthorizationServerJwt.class } }, new Object[] { null, new Class[] { AuthorizationServerWithTokenServices.class } }, - new Object[] { null, new Class[] { AuthorizationServerApproval.class } }, + new Object[] { null, new Class[] { AuthorizationServerApproval.class } }, + new Object[] { null, new Class[] { AuthorizationServerCustomClientDetails.class } }, new Object[] { BeanCreationException.class, new Class[] { AuthorizationServerTypes.class } } // @formatter:on ); @@ -337,7 +339,7 @@ public void configure(ClientDetailsServiceConfigurer clients) throws Exception { .authorizedGrantTypes("client_credentials"); // @formatter:on } - + @Override public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { oauthServer.passwordEncoder(new BCryptPasswordEncoder()); @@ -468,4 +470,25 @@ public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws E } + @Configuration + @EnableWebMvcSecurity + @EnableAuthorizationServer + protected static class AuthorizationServerCustomClientDetails extends AuthorizationServerConfigurerAdapter + implements Runnable { + + @Autowired + private ApplicationContext context; + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + clients.withClientDetails(new InMemoryClientDetailsService()); + } + + @Override + public void run() { + assertNotNull(context.getBean(ClientDetailsService.class)); + } + + } + } From 605049bf2f4524a86fe9b923c27b669b65a4e5fd Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 8 Jan 2015 09:38:26 +0000 Subject: [PATCH 351/831] Add primary key in SQL for testing (as hint) --- spring-security-oauth2/src/test/resources/schema.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-security-oauth2/src/test/resources/schema.sql b/spring-security-oauth2/src/test/resources/schema.sql index 03b3d4ac4..1e5e28c22 100644 --- a/spring-security-oauth2/src/test/resources/schema.sql +++ b/spring-security-oauth2/src/test/resources/schema.sql @@ -16,7 +16,7 @@ create table oauth_client_details ( create table oauth_client_token ( token_id VARCHAR(256), token LONGVARBINARY, - authentication_id VARCHAR(256), + authentication_id VARCHAR(256) PRIMARY KEY, user_name VARCHAR(256), client_id VARCHAR(256) ); @@ -24,7 +24,7 @@ create table oauth_client_token ( create table oauth_access_token ( token_id VARCHAR(256), token LONGVARBINARY, - authentication_id VARCHAR(256), + authentication_id VARCHAR(256) PRIMARY KEY, user_name VARCHAR(256), client_id VARCHAR(256), authentication LONGVARBINARY, From abcdebf98ee52fea9c2464c48c3b34fce04f332e Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 8 Jan 2015 09:40:47 +0000 Subject: [PATCH 352/831] Switch to 2.0.6 snapshots --- pom.xml | 2 +- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- tests/annotation/approval/pom.xml | 2 +- tests/annotation/client/pom.xml | 2 +- tests/annotation/common/pom.xml | 2 +- tests/annotation/form/pom.xml | 2 +- tests/annotation/jaxb/pom.xml | 2 +- tests/annotation/jdbc/pom.xml | 2 +- tests/annotation/jwt/pom.xml | 2 +- tests/annotation/mappings/pom.xml | 2 +- tests/annotation/multi/pom.xml | 2 +- tests/annotation/pom.xml | 4 ++-- tests/annotation/resource/pom.xml | 2 +- tests/annotation/vanilla/pom.xml | 2 +- tests/pom.xml | 2 +- tests/xml/approval/pom.xml | 2 +- tests/xml/client/pom.xml | 2 +- tests/xml/common/pom.xml | 2 +- tests/xml/form/pom.xml | 2 +- tests/xml/jdbc/pom.xml | 2 +- tests/xml/jwt/pom.xml | 2 +- tests/xml/mappings/pom.xml | 2 +- tests/xml/pom.xml | 4 ++-- tests/xml/vanilla/pom.xml | 2 +- 30 files changed, 32 insertions(+), 32 deletions(-) diff --git a/pom.xml b/pom.xml index 14e5aae76..e9a86cc45 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.5.BUILD-SNAPSHOT + 2.0.6.BUILD-SNAPSHOT http://static.springframework.org/spring-security/oauth diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index c0ccea250..da52569d5 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.5.BUILD-SNAPSHOT + 2.0.6.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index cc2ad4890..4bc48e92d 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.5.BUILD-SNAPSHOT + 2.0.6.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index ec0567326..ca9fe9323 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.5.BUILD-SNAPSHOT + 2.0.6.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index ce1940a68..e4df0a71f 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.5.BUILD-SNAPSHOT + 2.0.6.BUILD-SNAPSHOT ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index 627277d36..c7b9110a6 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.5.BUILD-SNAPSHOT + 2.0.6.BUILD-SNAPSHOT spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index 399915cdd..47b9191ad 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.5.BUILD-SNAPSHOT + 2.0.6.BUILD-SNAPSHOT spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 0fecc679c..f9a2a378a 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.5.BUILD-SNAPSHOT + 2.0.6.BUILD-SNAPSHOT spring-security-oauth2 diff --git a/tests/annotation/approval/pom.xml b/tests/annotation/approval/pom.xml index 004538521..9aa0fcdd4 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.5.BUILD-SNAPSHOT + 2.0.6.BUILD-SNAPSHOT diff --git a/tests/annotation/client/pom.xml b/tests/annotation/client/pom.xml index be3b8551b..4d1d24c80 100644 --- a/tests/annotation/client/pom.xml +++ b/tests/annotation/client/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.0.5.BUILD-SNAPSHOT + 2.0.6.BUILD-SNAPSHOT diff --git a/tests/annotation/common/pom.xml b/tests/annotation/common/pom.xml index 4f92cbf2b..1010139fb 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.5.BUILD-SNAPSHOT + 2.0.6.BUILD-SNAPSHOT diff --git a/tests/annotation/form/pom.xml b/tests/annotation/form/pom.xml index cd5dbca48..984e2ef87 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.5.BUILD-SNAPSHOT + 2.0.6.BUILD-SNAPSHOT diff --git a/tests/annotation/jaxb/pom.xml b/tests/annotation/jaxb/pom.xml index 8b0906805..64c3c255c 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.5.BUILD-SNAPSHOT + 2.0.6.BUILD-SNAPSHOT diff --git a/tests/annotation/jdbc/pom.xml b/tests/annotation/jdbc/pom.xml index f3ab5f014..4ede1c2e4 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.5.BUILD-SNAPSHOT + 2.0.6.BUILD-SNAPSHOT diff --git a/tests/annotation/jwt/pom.xml b/tests/annotation/jwt/pom.xml index d86a8d34c..61fe600d9 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.5.BUILD-SNAPSHOT + 2.0.6.BUILD-SNAPSHOT diff --git a/tests/annotation/mappings/pom.xml b/tests/annotation/mappings/pom.xml index 0d0ab5fd9..6bd6274fe 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.5.BUILD-SNAPSHOT + 2.0.6.BUILD-SNAPSHOT diff --git a/tests/annotation/multi/pom.xml b/tests/annotation/multi/pom.xml index 3104cf559..1d5d9663f 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.5.BUILD-SNAPSHOT + 2.0.6.BUILD-SNAPSHOT diff --git a/tests/annotation/pom.xml b/tests/annotation/pom.xml index cf430b0ad..101072570 100644 --- a/tests/annotation/pom.xml +++ b/tests/annotation/pom.xml @@ -4,7 +4,7 @@ org.demo spring-oauth2-tests-parent - 2.0.5.BUILD-SNAPSHOT + 2.0.6.BUILD-SNAPSHOT pom @@ -34,7 +34,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.0.5.BUILD-SNAPSHOT + 2.0.6.BUILD-SNAPSHOT jackson-mapper-asl diff --git a/tests/annotation/resource/pom.xml b/tests/annotation/resource/pom.xml index a934a1bb0..a10254927 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.5.BUILD-SNAPSHOT + 2.0.6.BUILD-SNAPSHOT diff --git a/tests/annotation/vanilla/pom.xml b/tests/annotation/vanilla/pom.xml index 8861db26f..8109e4c5b 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.5.BUILD-SNAPSHOT + 2.0.6.BUILD-SNAPSHOT diff --git a/tests/pom.xml b/tests/pom.xml index eda061dfa..cc00d37fa 100644 --- a/tests/pom.xml +++ b/tests/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.5.BUILD-SNAPSHOT + 2.0.6.BUILD-SNAPSHOT spring-security-oauth-tests diff --git a/tests/xml/approval/pom.xml b/tests/xml/approval/pom.xml index 9e55b0515..e67441379 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.5.BUILD-SNAPSHOT + 2.0.6.BUILD-SNAPSHOT diff --git a/tests/xml/client/pom.xml b/tests/xml/client/pom.xml index 00e62fa4b..7b610be7b 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.5.BUILD-SNAPSHOT + 2.0.6.BUILD-SNAPSHOT diff --git a/tests/xml/common/pom.xml b/tests/xml/common/pom.xml index fba2f5bb4..f90077eb9 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.5.BUILD-SNAPSHOT + 2.0.6.BUILD-SNAPSHOT diff --git a/tests/xml/form/pom.xml b/tests/xml/form/pom.xml index bde4b3683..986c24bf7 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.5.BUILD-SNAPSHOT + 2.0.6.BUILD-SNAPSHOT diff --git a/tests/xml/jdbc/pom.xml b/tests/xml/jdbc/pom.xml index e44cc6ef3..614df628e 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.5.BUILD-SNAPSHOT + 2.0.6.BUILD-SNAPSHOT diff --git a/tests/xml/jwt/pom.xml b/tests/xml/jwt/pom.xml index bd3dff86f..e17b36054 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.5.BUILD-SNAPSHOT + 2.0.6.BUILD-SNAPSHOT diff --git a/tests/xml/mappings/pom.xml b/tests/xml/mappings/pom.xml index b8359fbc8..127611d01 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.5.BUILD-SNAPSHOT + 2.0.6.BUILD-SNAPSHOT diff --git a/tests/xml/pom.xml b/tests/xml/pom.xml index 80b2c2941..a4a8f8f77 100644 --- a/tests/xml/pom.xml +++ b/tests/xml/pom.xml @@ -4,7 +4,7 @@ org.demo spring-oauth2-tests-xml-parent - 2.0.5.BUILD-SNAPSHOT + 2.0.6.BUILD-SNAPSHOT pom @@ -32,7 +32,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.0.5.BUILD-SNAPSHOT + 2.0.6.BUILD-SNAPSHOT jackson-mapper-asl diff --git a/tests/xml/vanilla/pom.xml b/tests/xml/vanilla/pom.xml index cc5842816..40a61a7ea 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.5.BUILD-SNAPSHOT + 2.0.6.BUILD-SNAPSHOT From 7043cd702299cfacb677273d041579ebbe8bdc74 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 23 Jan 2015 14:01:55 +0000 Subject: [PATCH 353/831] Remove unused security filter chain Fixes gh-364 --- .../sparklr/config/OAuth2ServerConfig.java | 25 ++----------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java index f37cc3ca7..e0c35f699 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java @@ -23,11 +23,9 @@ import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.ScopedProxyMode; -import org.springframework.core.annotation.Order; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.oauth.examples.sparklr.oauth.SparklrUserApprovalHandler; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; @@ -54,25 +52,6 @@ public class OAuth2ServerConfig { private static final String SPARKLR_RESOURCE_ID = "sparklr"; - @Configuration - @Order(10) - protected static class UiResourceConfiguration extends WebSecurityConfigurerAdapter { - @Override - protected void configure(HttpSecurity http) throws Exception { - // @formatter:off - http - .requestMatchers().antMatchers("/photos/**","/me") - .and() - .authorizeRequests() - .antMatchers("/me").access("hasRole('ROLE_USER')") - .antMatchers("/photos").access("hasRole('ROLE_USER')") - .antMatchers("/photos/trusted/**").access("hasRole('ROLE_USER')") - .antMatchers("/photos/user/**").access("hasRole('ROLE_USER')") - .antMatchers("/photos/**").access("hasRole('ROLE_USER')"); - // @formatter:on - } - } - @Configuration @EnableResourceServer protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { @@ -90,10 +69,10 @@ public void configure(HttpSecurity http) throws Exception { .and() .authorizeRequests() .antMatchers("/me").access("#oauth2.hasScope('read')") - .antMatchers("/photos").access("#oauth2.hasScope('read') or hasRole('ROLE_USER')") + .antMatchers("/photos").access("#oauth2.hasScope('read') or (!#oauth2.isOAuth() and hasRole('ROLE_USER'))") .antMatchers("/photos/trusted/**").access("#oauth2.hasScope('trust')") .antMatchers("/photos/user/**").access("#oauth2.hasScope('trust')") - .antMatchers("/photos/**").access("#oauth2.hasScope('read') or hasRole('ROLE_USER')") + .antMatchers("/photos/**").access("#oauth2.hasScope('read') or (!#oauth2.isOAuth() and hasRole('ROLE_USER'))") .regexMatchers(HttpMethod.DELETE, "/oauth/users/([^/].*?)/tokens/.*") .access("#oauth2.clientHasRole('ROLE_CLIENT') and (hasRole('ROLE_USER') or #oauth2.isClient()) and #oauth2.hasScope('write')") .regexMatchers(HttpMethod.GET, "/oauth/clients/([^/].*?)/users/.*") From d8bcdb4eae77d7687be169be2e4594ee11a6594e Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 18 Dec 2014 18:23:14 +0000 Subject: [PATCH 354/831] Fix customization of expression handler Re-ordering the calls to HttpSecurity seems to make sense. The ResourceServerConfigurers get a chance to provide exception handlers and expression handlers now. Fixes gh-315 --- ...2ClientAuthenticationProcessingFilter.java | 8 +++- .../ResourceServerConfiguration.java | 42 +++++++---------- .../ResourceServerSecurityConfigurer.java | 5 ++- ...ntAuthenticationProcessingFilterTests.java | 15 +++++++ .../ResourceServerConfigurationTests.java | 45 ++++++++++++++++++- .../demo/AuthorizationCodeProviderTests.java | 3 ++ 6 files changed, 89 insertions(+), 29 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilter.java index 95a39a805..1782efbaa 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilter.java @@ -32,6 +32,7 @@ import org.springframework.security.oauth2.client.http.AccessTokenRequiredException; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; +import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails; import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetailsSource; @@ -88,7 +89,12 @@ public void afterPropertiesSet() { public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException { - OAuth2AccessToken accessToken = restTemplate.getAccessToken(); + OAuth2AccessToken accessToken; + try { + accessToken = restTemplate.getAccessToken(); + } catch (OAuth2Exception e) { + throw new BadCredentialsException("Could not obtain access token", e); + } try { OAuth2Authentication result = tokenServices.loadAuthentication(accessToken.getValue()); if (authenticationDetailsSource!=null) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java index 8518bc6fb..b7478802e 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java @@ -32,11 +32,8 @@ import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; import org.springframework.security.oauth2.provider.endpoint.FrameworkEndpointHandlerMapping; -import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; -import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler; import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices; import org.springframework.security.oauth2.provider.token.TokenStore; -import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.security.web.util.matcher.RequestMatcher; /** @@ -59,8 +56,6 @@ public class ResourceServerConfiguration extends WebSecurityConfigurerAdapter im private List configurers = Collections.emptyList(); - private AccessDeniedHandler accessDeniedHandler = new OAuth2AccessDeniedHandler(); - @Autowired(required = false) private AuthorizationServerEndpointsConfiguration endpoints; @@ -121,16 +116,28 @@ protected void init(AuthenticationManagerBuilder builder) { @Override protected void configure(HttpSecurity http) throws Exception { + ResourceServerSecurityConfigurer resources = new ResourceServerSecurityConfigurer(); + ResourceServerTokenServices services = resolveTokenServices(); + if (services != null) { + resources.tokenServices(services); + } else { + if (tokenStore != null) { + resources.tokenStore(tokenStore); + } else if (endpoints!=null) { + resources.tokenStore(endpoints.getEndpointsConfigurer().getTokenStore()); + } + } + for (ResourceServerConfigurer configurer : configurers) { + configurer.configure(resources); + } + http.apply(resources); RequestMatcherConfigurer requests = http.requestMatchers(); if (endpoints != null) { // Assume we are in an Authorization Server requests.requestMatchers(new NotOAuthRequestMatcher(endpoints.oauth2EndpointHandlerMapping())); } // @formatter:off - http - .exceptionHandling().accessDeniedHandler(accessDeniedHandler) - .and() - .anonymous().disable() + http.anonymous().disable() .csrf().disable(); // @formatter:on for (ResourceServerConfigurer configurer : configurers) { @@ -142,23 +149,6 @@ protected void configure(HttpSecurity http) throws Exception { // with this one, so to avoid that we only add it if the user hasn't configured anything. http.authorizeRequests().anyRequest().authenticated(); } - // And set the default expression handler in case one isn't explicit elsewhere - http.authorizeRequests().expressionHandler(new OAuth2WebSecurityExpressionHandler()); - ResourceServerSecurityConfigurer resources = new ResourceServerSecurityConfigurer(); - http.apply(resources); - ResourceServerTokenServices services = resolveTokenServices(); - if (services != null) { - resources.tokenServices(services); - } else { - if (tokenStore != null) { - resources.tokenStore(tokenStore); - } else if (endpoints!=null) { - resources.tokenStore(endpoints.getEndpointsConfigurer().getTokenStore()); - } - } - for (ResourceServerConfigurer configurer : configurers) { - configurer.configure(resources); - } } private ResourceServerTokenServices resolveTokenServices() { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java index 2c1c43363..5932e17af 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java @@ -128,6 +128,7 @@ public ResourceServerSecurityConfigurer tokenServices(ResourceServerTokenService @Override public void init(HttpSecurity http) throws Exception { registerDefaultAuthenticationEntryPoint(http); + // TODO: remove this http.csrf().disable(); } @@ -175,7 +176,9 @@ public void configure(HttpSecurity http) throws Exception { .authorizeRequests().expressionHandler(expressionHandler) .and() .addFilterBefore(resourcesServerFilter, AbstractPreAuthenticatedProcessingFilter.class) - .exceptionHandling().accessDeniedHandler(accessDeniedHandler); + .exceptionHandling() + .accessDeniedHandler(accessDeniedHandler) + .authenticationEntryPoint(authenticationEntryPoint); // @formatter:on } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilterTests.java index ea99d2daf..0d9248680 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilterTests.java @@ -25,14 +25,18 @@ import javax.servlet.ServletException; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.mockito.Mockito; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.client.OAuth2RestOperations; import org.springframework.security.oauth2.client.http.AccessTokenRequiredException; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; +import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.RequestTokenFactory; @@ -48,6 +52,9 @@ public class OAuth2ClientAuthenticationProcessingFilterTests { private OAuth2RestOperations restTemplate = Mockito.mock(OAuth2RestOperations.class); private OAuth2Authentication authentication; + + @Rule + public ExpectedException expected = ExpectedException.none(); @Test public void testAuthentication() throws Exception { @@ -75,6 +82,14 @@ public void testSuccessfulAuthentication() throws Exception { Mockito.verify(restTemplate, Mockito.times(1)).getAccessToken(); } + @Test + public void testDeniedToken() throws Exception { + filter.setRestTemplate(restTemplate); + Mockito.when(restTemplate.getAccessToken()).thenThrow(new OAuth2Exception("User denied acess token")); + expected.expect(BadCredentialsException.class); + filter.attemptAuthentication(null, null); + } + @Test public void testUnsuccessfulAuthentication() throws IOException, ServletException { try { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java index 1fc87ae8b..497e05105 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java @@ -18,7 +18,9 @@ import javax.servlet.http.HttpServletRequest; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.mock.web.MockServletContext; @@ -41,6 +43,7 @@ import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore; import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler; import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken; import org.springframework.test.web.servlet.MockMvc; @@ -61,6 +64,9 @@ public class ResourceServerConfigurationTests { private OAuth2AccessToken token; private OAuth2Authentication authentication; + + @Rule + public ExpectedException expected = ExpectedException.none(); @Before public void init() { @@ -118,6 +124,23 @@ public void testCustomTokenExtractor() throws Exception { context.close(); } + @Test + public void testCustomExpressionHandler() throws Exception { + tokenStore.storeAccessToken(token, authentication); + AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); + context.setServletContext(new MockServletContext()); + context.register(ExpressionHandlerContext.class); + context.refresh(); + MockMvc mvc = MockMvcBuilders.webAppContextSetup(context) + .addFilters(new DelegatingFilterProxy(context.getBean("springSecurityFilterChain", Filter.class))) + .build(); + expected.expect(IllegalArgumentException.class); + expected.expectMessage("#oauth2"); + mvc.perform(MockMvcRequestBuilders.get("/").header("Authorization", "Bearer FOO")).andExpect( + MockMvcResultMatchers.status().isUnauthorized()); + context.close(); + } + @Test public void testCustomAuthenticationEntryPoint() throws Exception { tokenStore.storeAccessToken(token, authentication); @@ -181,7 +204,27 @@ public Authentication extract(HttpServletRequest request) { @Override public void configure(HttpSecurity http) throws Exception { - http.authorizeRequests().anyRequest().authenticated(); + http.authorizeRequests().anyRequest().access("#oauth2.isClient()"); + } + + @Bean + public TokenStore tokenStore() { + return tokenStore; + } + } + + @Configuration + @EnableResourceServer + @EnableWebSecurity + protected static class ExpressionHandlerContext extends ResourceServerConfigurerAdapter { + @Override + public void configure(ResourceServerSecurityConfigurer resources) throws Exception { + resources.expressionHandler(new DefaultWebSecurityExpressionHandler()); + } + + @Override + public void configure(HttpSecurity http) throws Exception { + http.authorizeRequests().anyRequest().access("#oauth2.isClient()"); } @Bean diff --git a/tests/annotation/mappings/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/mappings/src/test/java/demo/AuthorizationCodeProviderTests.java index 36e02d25f..04f4e3c31 100755 --- a/tests/annotation/mappings/src/test/java/demo/AuthorizationCodeProviderTests.java +++ b/tests/annotation/mappings/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -45,6 +45,9 @@ public void testInsufficientScopeInResourceRequest() throws Exception { } catch (InsufficientScopeException ex) { assertTrue("Wrong summary: " + ex, ex.getSummary().contains("scope=\"read")); + } catch (Exception e) { + fail("Wrong exception: " + e.getClass()); + throw e; } } From 1a04ec9890e1cecfeff3436607dae35c465dcddd Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 23 Jan 2015 14:02:02 +0000 Subject: [PATCH 355/831] Register AccessDeniedHandler earlier so that it gets used This is baffling (might need help from @rwinch to understand), but there is an integration test in sparklr2 that fails without this change. As far as I can tell it registers the right access denied handler even before this change, but it never gets called. See gh-315 --- .../web/configuration/ResourceServerConfiguration.java | 10 ++++++---- .../configurers/ResourceServerSecurityConfigurer.java | 4 ++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java index b7478802e..8e01f8fc0 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java @@ -130,16 +130,18 @@ protected void configure(HttpSecurity http) throws Exception { for (ResourceServerConfigurer configurer : configurers) { configurer.configure(resources); } + // @formatter:off + http + .exceptionHandling().accessDeniedHandler(resources.getAccessDeniedHandler()).and() + .anonymous().disable() + .csrf().disable(); + // @formatter:on http.apply(resources); RequestMatcherConfigurer requests = http.requestMatchers(); if (endpoints != null) { // Assume we are in an Authorization Server requests.requestMatchers(new NotOAuthRequestMatcher(endpoints.oauth2EndpointHandlerMapping())); } - // @formatter:off - http.anonymous().disable() - .csrf().disable(); - // @formatter:on for (ResourceServerConfigurer configurer : configurers) { // Delegates can add authorizeRequests() here configurer.configure(http); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java index 5932e17af..a8d1c4fab 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java @@ -220,4 +220,8 @@ private TokenStore tokenStore() { return this.tokenStore; } + public AccessDeniedHandler getAccessDeniedHandler() { + return this.accessDeniedHandler; + } + } From c5d6f1f660e5c4ffb7863255a04ad370e36807da Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 23 Jan 2015 15:02:19 +0000 Subject: [PATCH 356/831] Add "stateless" flag to resource server configuration Default to true, so that security context is cleared if no access token is presented. Useful default in mixed servers where some resources are not stateless, or where they might accept anonymous authentication. Using default=true changes the behaviour of existing applications, but in a way that makes them more secure (it's better to opt into anything with a risk of authenticating accidentally). Fixes gh-360 --- .../sparklr/config/OAuth2ServerConfig.java | 2 +- .../ResourceServerSecurityConfigurer.java | 13 ++++++ .../OAuth2AuthenticationManager.java | 3 ++ .../OAuth2AuthenticationProcessingFilter.java | 41 ++++++++++++++----- ...h2AuthenticationProcessingFilterTests.java | 28 +++++++++++-- 5 files changed, 71 insertions(+), 16 deletions(-) diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java index e0c35f699..4641b2f1b 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java @@ -58,7 +58,7 @@ protected static class ResourceServerConfiguration extends ResourceServerConfigu @Override public void configure(ResourceServerSecurityConfigurer resources) { - resources.resourceId(SPARKLR_RESOURCE_ID); + resources.resourceId(SPARKLR_RESOURCE_ID).stateless(false); } @Override diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java index a8d1c4fab..77122ff58 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java @@ -72,6 +72,8 @@ public final class ResourceServerSecurityConfigurer extends private TokenExtractor tokenExtractor; + private boolean stateless = true; + public ResourceServerSecurityConfigurer() { resourceId(resourceId); } @@ -84,6 +86,16 @@ public TokenStore getTokenStore() { return tokenStore; } + /** + * Flag to indicate that only token-based authentication is allowed on these resources. + * @param stateless the flag value (default true) + * @return this (for fluent builder) + */ + public ResourceServerSecurityConfigurer stateless(boolean stateless) { + this.stateless = stateless; + return this; + } + public ResourceServerSecurityConfigurer authenticationEntryPoint(AuthenticationEntryPoint authenticationEntryPoint) { this.authenticationEntryPoint = authenticationEntryPoint; return this; @@ -170,6 +182,7 @@ public void configure(HttpSecurity http) throws Exception { resourcesServerFilter.setTokenExtractor(tokenExtractor); } resourcesServerFilter = postProcess(resourcesServerFilter); + resourcesServerFilter.setStateless(stateless); // @formatter:off http diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java index 4e586aa5b..27b94da54 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java @@ -76,6 +76,9 @@ public void afterPropertiesSet() { */ public Authentication authenticate(Authentication authentication) throws AuthenticationException { + if (authentication == null) { + throw new InvalidTokenException("Invalid token (token not found)"); + } String token = (String) authentication.getPrincipal(); OAuth2Authentication auth = tokenServices.loadAuthentication(token); if (auth == null) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilter.java index e29dcd83c..b256166b6 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilter.java @@ -58,6 +58,19 @@ public class OAuth2AuthenticationProcessingFilter implements Filter, Initializin private TokenExtractor tokenExtractor = new BearerTokenExtractor(); + private boolean stateless = true; + + /** + * Flag to say that this filter guards stateless resources (default true). Set this to true if the only way the + * resource can be accessed is with a token. If false then an incoming cookie can populate the security context and + * allow access to a caller that isn't an OAuth2 client. + * + * @param stateless the flag to set (default true) + */ + public void setStateless(boolean stateless) { + this.stateless = stateless; + } + /** * @param authenticationEntryPoint the authentication entry point to set */ @@ -71,7 +84,7 @@ public void setAuthenticationEntryPoint(AuthenticationEntryPoint authenticationE public void setAuthenticationManager(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; } - + /** * @param tokenExtractor the tokenExtractor to set */ @@ -79,14 +92,14 @@ public void setTokenExtractor(TokenExtractor tokenExtractor) { this.tokenExtractor = tokenExtractor; } - /** - * @param authenticationDetailsSource - * The AuthenticationDetailsSource to use - */ - public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) { - Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required"); - this.authenticationDetailsSource = authenticationDetailsSource; - } + /** + * @param authenticationDetailsSource The AuthenticationDetailsSource to use + */ + public void setAuthenticationDetailsSource( + AuthenticationDetailsSource authenticationDetailsSource) { + Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required"); + this.authenticationDetailsSource = authenticationDetailsSource; + } public void afterPropertiesSet() { Assert.state(authenticationManager != null, "AuthenticationManager is required"); @@ -100,10 +113,16 @@ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) final HttpServletResponse response = (HttpServletResponse) res; try { - + Authentication authentication = tokenExtractor.extract(request); if (authentication == null) { + if (stateless) { + if (debug) { + logger.debug("Clearing security context."); + } + SecurityContextHolder.clearContext(); + } if (debug) { logger.debug("No token in request, will continue chain."); } @@ -112,7 +131,7 @@ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_VALUE, authentication.getPrincipal()); if (authentication instanceof AbstractAuthenticationToken) { AbstractAuthenticationToken needsDetails = (AbstractAuthenticationToken) authentication; - needsDetails.setDetails(authenticationDetailsSource.buildDetails(request)); + needsDetails.setDetails(authenticationDetailsSource.buildDetails(request)); } Authentication authResult = authenticationManager.authenticate(authentication); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilterTests.java index 1f9255d33..af238925b 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilterTests.java @@ -11,11 +11,11 @@ * specific language governing permissions and limitations under the License. */ - package org.springframework.security.oauth2.provider.authentication; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import javax.servlet.FilterChain; @@ -23,10 +23,12 @@ import org.junit.Test; import org.mockito.Mockito; import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.RequestTokenFactory; @@ -43,7 +45,8 @@ public class OAuth2AuthenticationProcessingFilterTests { private Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala"); - private OAuth2Authentication authentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request(null, "foo", null, false, null, null, null, null, null), userAuthentication); + private OAuth2Authentication authentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request( + null, "foo", null, false, null, null, null, null, null), userAuthentication); private FilterChain chain = Mockito.mock(FilterChain.class); @@ -56,7 +59,7 @@ public Authentication authenticate(Authentication request) throws Authentication } }); } - + @After public void clear() { SecurityContextHolder.clearContext(); @@ -65,11 +68,28 @@ public void clear() { @Test public void testDetailsAdded() throws Exception { request.addHeader("Authorization", "Bearer FOO"); - filter.doFilter(request, null, chain ); + filter.doFilter(request, null, chain); assertNotNull(request.getAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_VALUE)); Authentication result = SecurityContextHolder.getContext().getAuthentication(); assertEquals(authentication, result); assertNotNull(result.getDetails()); } + @Test + public void testStateless() throws Exception { + SecurityContextHolder.getContext().setAuthentication( + new AnonymousAuthenticationToken("FOO", "foo", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"))); + filter.doFilter(request, null, chain); + assertNull(SecurityContextHolder.getContext().getAuthentication()); + } + + @Test + public void testStateful() throws Exception { + filter.setStateless(false); + SecurityContextHolder.getContext().setAuthentication( + new AnonymousAuthenticationToken("FOO", "foo", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"))); + filter.doFilter(request, null, chain); + assertNotNull(SecurityContextHolder.getContext().getAuthentication()); + } + } From 395f2636bb36a69d91c5cbfa1256132756b24710 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 23 Jan 2015 15:11:19 +0000 Subject: [PATCH 357/831] Add integration test for /oauth/token_key See gh-370 --- .../src/test/java/demo/ApplicationTests.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/annotation/jwt/src/test/java/demo/ApplicationTests.java b/tests/annotation/jwt/src/test/java/demo/ApplicationTests.java index 5f0076c88..82a5ffee6 100644 --- a/tests/annotation/jwt/src/test/java/demo/ApplicationTests.java +++ b/tests/annotation/jwt/src/test/java/demo/ApplicationTests.java @@ -1,13 +1,17 @@ package demo; +import static org.junit.Assert.assertEquals; 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.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.http.HttpStatus; import org.springframework.security.oauth2.provider.token.DefaultTokenServices; import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -20,6 +24,9 @@ @IntegrationTest("server.port=0") public class ApplicationTests { + @Value("${local.server.port}") + private int port; + @Autowired @Qualifier("defaultAuthorizationServerTokenServices") private DefaultTokenServices tokenServices; @@ -30,4 +37,19 @@ public void tokenStoreIsJwt() { ReflectionTestUtils.getField(tokenServices, "tokenStore") instanceof JwtTokenStore); } + @Test + public void tokenKeyEndpointProtected() { + assertEquals(HttpStatus.UNAUTHORIZED, + new TestRestTemplate().getForEntity("http://localhost/" + port + "/oauth/token_key", String.class) + .getStatusCode()); + } + + @Test + public void tokenKeyEndpointWithSecret() { + assertEquals( + HttpStatus.OK, + new TestRestTemplate("my-client-with-secret", "secret").getForEntity( + "http://localhost/" + port + "/oauth/token_key", String.class).getStatusCode()); + } + } From bdb3390b19c54bdca3da6383ec9ad191ef4734cd Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 23 Jan 2015 15:14:20 +0000 Subject: [PATCH 358/831] Make it possible to change value of reuseRefreshToken Fixes gh-351 --- .../configurers/AuthorizationServerEndpointsConfigurer.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 22e1ed814..688561b32 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 @@ -109,7 +109,7 @@ public final class AuthorizationServerEndpointsConfigurer { private boolean tokenServicesOverride = false; - private boolean reuseRefreshToken; + private boolean reuseRefreshToken = true; public AuthorizationServerTokenServices getTokenServices() { return tokenServices; @@ -157,8 +157,8 @@ public AuthorizationServerEndpointsConfigurer tokenEnhancer(TokenEnhancer tokenE return this; } - public AuthorizationServerEndpointsConfigurer reuseRefreshTokens() { - this.reuseRefreshToken = true; + public AuthorizationServerEndpointsConfigurer reuseRefreshTokens(boolean reuseRefreshToken) { + this.reuseRefreshToken = reuseRefreshToken; return this; } From 138e8b66eec42651842eb83650488aca5f2932d0 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 23 Jan 2015 16:01:05 +0000 Subject: [PATCH 359/831] Make exception translator pluggable in @Configuration Adds exceptionTranslator() convenience methods to configurers (should get injected into TokenEndpoint, AuthorizationEndpoint and CheckTokenEndpoint. Fixes gh-343 --- ...orizationServerEndpointsConfiguration.java | 8 ++++ ...uthorizationServerEndpointsConfigurer.java | 22 +++++++++++ .../provider/endpoint/CheckTokenEndpoint.java | 7 ++++ ...AuthorizationServerConfigurationTests.java | 37 +++++++++++++++++++ 4 files changed, 74 insertions(+) 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 83976c92f..b7d8d4d77 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 @@ -43,6 +43,7 @@ import org.springframework.security.oauth2.provider.endpoint.TokenKeyEndpoint; import org.springframework.security.oauth2.provider.endpoint.WhitelabelApprovalEndpoint; import org.springframework.security.oauth2.provider.endpoint.WhitelabelErrorEndpoint; +import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; import org.springframework.security.oauth2.provider.token.ConsumerTokenServices; import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; @@ -81,6 +82,7 @@ public AuthorizationEndpoint authorizationEndpoint() throws Exception { AuthorizationEndpoint authorizationEndpoint = new AuthorizationEndpoint(); FrameworkEndpointHandlerMapping mapping = getEndpointsConfigurer().getFrameworkEndpointHandlerMapping(); authorizationEndpoint.setUserApprovalPage(extractPath(mapping, "/oauth/confirm_access")); + authorizationEndpoint.setProviderExceptionHandler(exceptionTranslator()); authorizationEndpoint.setErrorPage(extractPath(mapping, "/oauth/error")); authorizationEndpoint.setTokenGranter(tokenGranter()); authorizationEndpoint.setClientDetailsService(clientDetailsService); @@ -95,6 +97,7 @@ public AuthorizationEndpoint authorizationEndpoint() throws Exception { public TokenEndpoint tokenEndpoint() throws Exception { TokenEndpoint tokenEndpoint = new TokenEndpoint(); tokenEndpoint.setClientDetailsService(clientDetailsService); + tokenEndpoint.setProviderExceptionHandler(exceptionTranslator()); tokenEndpoint.setTokenGranter(tokenGranter()); tokenEndpoint.setOAuth2RequestFactory(oauth2RequestFactory()); tokenEndpoint.setOAuth2RequestValidator(oauth2RequestValidator()); @@ -105,6 +108,7 @@ public TokenEndpoint tokenEndpoint() throws Exception { public CheckTokenEndpoint checkTokenEndpoint() { CheckTokenEndpoint endpoint = new CheckTokenEndpoint(getEndpointsConfigurer().getResourceServerTokenServices()); endpoint.setAccessTokenConverter(getEndpointsConfigurer().getAccessTokenConverter()); + endpoint.setExceptionTranslator(exceptionTranslator()); return endpoint; } @@ -162,6 +166,10 @@ private OAuth2RequestValidator oauth2RequestValidator() throws Exception { private AuthorizationCodeServices authorizationCodeServices() throws Exception { return getEndpointsConfigurer().getAuthorizationCodeServices(); } + + private WebResponseExceptionTranslator exceptionTranslator() { + return getEndpointsConfigurer().getExceptionTranslator(); + } private TokenGranter tokenGranter() throws Exception { return getEndpointsConfigurer().getTokenGranter(); 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 688561b32..f9df9a6cd 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 @@ -39,6 +39,8 @@ import org.springframework.security.oauth2.provider.code.AuthorizationCodeTokenGranter; import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices; 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.implicit.ImplicitTokenGranter; import org.springframework.security.oauth2.provider.password.ResourceOwnerPasswordTokenGranter; import org.springframework.security.oauth2.provider.refresh.RefreshTokenGranter; @@ -111,6 +113,8 @@ public final class AuthorizationServerEndpointsConfigurer { private boolean reuseRefreshToken = true; + private WebResponseExceptionTranslator exceptionTranslator; + public AuthorizationServerTokenServices getTokenServices() { return tokenServices; } @@ -215,6 +219,11 @@ public AuthorizationServerEndpointsConfigurer addInterceptor(WebRequestIntercept return this; } + public AuthorizationServerEndpointsConfigurer exceptionTranslator(WebResponseExceptionTranslator exceptionTranslator) { + this.exceptionTranslator = exceptionTranslator; + return this; + } + /** * The AuthenticationManager for the password grant. * @@ -279,6 +288,10 @@ public FrameworkEndpointHandlerMapping getFrameworkEndpointHandlerMapping() { return frameworkEndpointHandlerMapping(); } + public WebResponseExceptionTranslator getExceptionTranslator() { + return exceptionTranslator(); + } + private ResourceServerTokenServices resourceTokenServices() { if (resourceTokenServices == null) { if (tokenServices instanceof ResourceServerTokenServices) { @@ -401,6 +414,14 @@ private AuthorizationCodeServices authorizationCodeServices() { return authorizationCodeServices; } + private WebResponseExceptionTranslator exceptionTranslator() { + if (exceptionTranslator != null) { + return exceptionTranslator; + } + exceptionTranslator = new DefaultWebResponseExceptionTranslator(); + return exceptionTranslator; + } + private OAuth2RequestFactory requestFactory() { if (requestFactory != null) { return requestFactory; @@ -449,4 +470,5 @@ private FrameworkEndpointHandlerMapping frameworkEndpointHandlerMapping() { } return frameworkEndpointHandlerMapping; } + } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/CheckTokenEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/CheckTokenEndpoint.java index a4fd32809..8c2315614 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/CheckTokenEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/CheckTokenEndpoint.java @@ -51,6 +51,13 @@ public class CheckTokenEndpoint { public CheckTokenEndpoint(ResourceServerTokenServices resourceServerTokenServices) { this.resourceServerTokenServices = resourceServerTokenServices; } + + /** + * @param exceptionTranslator the exception translator to set + */ + public void setExceptionTranslator(WebResponseExceptionTranslator exceptionTranslator) { + this.exceptionTranslator = exceptionTranslator; + } /** * @param accessTokenConverter the accessTokenConverter to set diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java index 9c838867b..b0a472106 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java @@ -12,6 +12,7 @@ */ package org.springframework.security.oauth2.config.annotation; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -53,6 +54,7 @@ import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenGranter; import org.springframework.security.oauth2.provider.client.InMemoryClientDetailsService; import org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint; +import org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; import org.springframework.security.oauth2.provider.token.DefaultTokenServices; import org.springframework.security.oauth2.provider.token.TokenStore; @@ -91,6 +93,7 @@ public static List parameters() { new Object[] { null, new Class[] { AuthorizationServerJwt.class } }, new Object[] { null, new Class[] { AuthorizationServerWithTokenServices.class } }, new Object[] { null, new Class[] { AuthorizationServerApproval.class } }, + new Object[] { null, new Class[] { AuthorizationServerExceptionTranslator.class } }, new Object[] { null, new Class[] { AuthorizationServerCustomClientDetails.class } }, new Object[] { BeanCreationException.class, new Class[] { AuthorizationServerTypes.class } } // @formatter:on @@ -449,6 +452,40 @@ public void run() { } + @Configuration + @EnableWebMvcSecurity + @EnableAuthorizationServer + protected static class AuthorizationServerExceptionTranslator extends AuthorizationServerConfigurerAdapter implements Runnable { + + private TokenStore tokenStore = new InMemoryTokenStore(); + + @Autowired + private ApplicationContext context; + + private DefaultWebResponseExceptionTranslator exceptionTranslator = new DefaultWebResponseExceptionTranslator(); + + @Override + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + endpoints.tokenStore(tokenStore).exceptionTranslator(exceptionTranslator); + } + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + // @formatter:off + clients.inMemory() + .withClient("my-trusted-client") + .authorizedGrantTypes("password"); + // @formatter:on + } + + @Override + public void run() { + assertEquals(exceptionTranslator, ReflectionTestUtils.getField(context.getBean(AuthorizationEndpoint.class), + "providerExceptionHandler")); + } + + } + @Configuration @EnableWebMvcSecurity protected static class AuthorizationServerTypes extends AuthorizationServerConfigurerAdapter { From 5d07955c8bb81289ebf696aa85e7da5008b2b770 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Sun, 25 Jan 2015 16:11:17 +0000 Subject: [PATCH 360/831] Add catchall @ExceptionHandler to TokenEndpoint Because it is always a machine client, it's a good idea to have a consistent response for errors in the TokenEndpoint, instead of falling through to the container's own handler. Fixes gh-347 --- .../security/oauth2/provider/endpoint/TokenEndpoint.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java index 64d776b92..a35ff09e2 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java @@ -138,6 +138,12 @@ protected String getClientId(Principal principal) { return clientId; } + @ExceptionHandler(Exception.class) + public ResponseEntity handleException(Exception e) throws Exception { + logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage()); + return getExceptionTranslator().translate(e); + } + @ExceptionHandler(ClientRegistrationException.class) public ResponseEntity handleClientRegistrationException(Exception e) throws Exception { logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage()); @@ -145,7 +151,7 @@ public ResponseEntity handleClientRegistrationException(Excepti } @ExceptionHandler(OAuth2Exception.class) - public ResponseEntity handleException(Exception e) throws Exception { + public ResponseEntity handleException(OAuth2Exception e) throws Exception { logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage()); return getExceptionTranslator().translate(e); } From 03b0ccc7c56b45e5659a927539efb7eb78d8f3f6 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 26 Jan 2015 09:09:02 +0000 Subject: [PATCH 361/831] Add token type to OAuth2AuthenticationDetails Clients that rely on the OAuth2AuthenticationDetails to figure out the way to send authentication to a server could not, before this change, take into account the token type to use in the header. Defaulting to "bearer" sometimes fails (e.g. apparently on Facebook). There are no such clients in Spring OAuth as it happens, but other projects are using this feature so now we make the data available. It's a little bit messy in the OAuth2ClientAuthenticationProcessingFilter since the TokenExtractor implementation we have has protected methods whose signatures do not permit the token type to be determined. Maybe in 2.1 we can break those methods and make their function clearer. Fixes gh-354 --- .../DefaultOAuth2RequestAuthenticator.java | 7 ++- ...2ClientAuthenticationProcessingFilter.java | 1 + .../authentication/BearerTokenExtractor.java | 6 +++ .../OAuth2AuthenticationDetails.java | 18 +++++++ ...efaultOAuth2RequestAuthenticatorTests.java | 51 +++++++++++++++++++ ...ntAuthenticationProcessingFilterTests.java | 17 +++++++ ...h2AuthenticationProcessingFilterTests.java | 13 +++++ 7 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/DefaultOAuth2RequestAuthenticatorTests.java diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/DefaultOAuth2RequestAuthenticator.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/DefaultOAuth2RequestAuthenticator.java index 11d331888..fa825e1de 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/DefaultOAuth2RequestAuthenticator.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/DefaultOAuth2RequestAuthenticator.java @@ -14,6 +14,7 @@ package org.springframework.security.oauth2.client; import org.springframework.http.client.ClientHttpRequest; +import org.springframework.security.oauth2.client.http.AccessTokenRequiredException; import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.util.StringUtils; @@ -25,8 +26,12 @@ public class DefaultOAuth2RequestAuthenticator implements OAuth2RequestAuthenticator { @Override - public void authenticate(OAuth2ProtectedResourceDetails resource, OAuth2ClientContext clientContext, ClientHttpRequest request) { + public void authenticate(OAuth2ProtectedResourceDetails resource, OAuth2ClientContext clientContext, + ClientHttpRequest request) { OAuth2AccessToken accessToken = clientContext.getAccessToken(); + if (accessToken == null) { + throw new AccessTokenRequiredException(resource); + } String tokenType = accessToken.getTokenType(); if (!StringUtils.hasText(tokenType)) { tokenType = OAuth2AccessToken.BEARER_TYPE; // we'll assume basic bearer token type if none is specified. diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilter.java index 1782efbaa..6fd1a6e27 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilter.java @@ -99,6 +99,7 @@ public Authentication attemptAuthentication(HttpServletRequest request, HttpServ OAuth2Authentication result = tokenServices.loadAuthentication(accessToken.getValue()); if (authenticationDetailsSource!=null) { request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_VALUE, accessToken.getValue()); + request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_TYPE, accessToken.getTokenType()); result.setDetails(authenticationDetailsSource.buildDetails(request)); } return result; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/BearerTokenExtractor.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/BearerTokenExtractor.java index 437933dd3..281c06fd6 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/BearerTokenExtractor.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/BearerTokenExtractor.java @@ -56,6 +56,9 @@ protected String extractToken(HttpServletRequest request) { if (token == null) { logger.debug("Token not found in request parameters. Not an OAuth2 request."); } + else { + request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_TYPE, OAuth2AccessToken.BEARER_TYPE); + } } return token; @@ -73,6 +76,9 @@ protected String extractHeaderToken(HttpServletRequest request) { String value = headers.nextElement(); if ((value.toLowerCase().startsWith(OAuth2AccessToken.BEARER_TYPE.toLowerCase()))) { String authHeaderValue = value.substring(OAuth2AccessToken.BEARER_TYPE.length()).trim(); + // Add this here for the auth details later. Would be better to change the signature of this method. + request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_TYPE, + value.substring(0, OAuth2AccessToken.BEARER_TYPE.length()).trim()); int commaIndex = authHeaderValue.indexOf(','); if (commaIndex > 0) { authHeaderValue = authHeaderValue.substring(0, commaIndex); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationDetails.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationDetails.java index ac398d9a2..49ff29292 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationDetails.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationDetails.java @@ -31,16 +31,21 @@ public class OAuth2AuthenticationDetails implements Serializable { public static final String ACCESS_TOKEN_VALUE = OAuth2AuthenticationDetails.class.getSimpleName() + ".ACCESS_TOKEN_VALUE"; + public static final String ACCESS_TOKEN_TYPE = OAuth2AuthenticationDetails.class.getSimpleName() + ".ACCESS_TOKEN_TYPE"; + private final String remoteAddress; private final String sessionId; private final String tokenValue; + private final String tokenType; + private final String display; private Object decodedDetails; + /** * Records the access token value and remote address and will also set the session Id if a session already exists * (it won't create one). @@ -49,6 +54,7 @@ public class OAuth2AuthenticationDetails implements Serializable { */ public OAuth2AuthenticationDetails(HttpServletRequest request) { this.tokenValue = (String) request.getAttribute(ACCESS_TOKEN_VALUE); + this.tokenType = (String) request.getAttribute(ACCESS_TOKEN_TYPE); this.remoteAddress = request.getRemoteAddr(); HttpSession session = request.getSession(false); @@ -66,6 +72,9 @@ public OAuth2AuthenticationDetails(HttpServletRequest request) { builder.append(", "); } } + if (tokenType!=null) { + builder.append("tokenType=").append(this.tokenType); + } if (tokenValue!=null) { builder.append("tokenValue="); } @@ -80,6 +89,15 @@ public OAuth2AuthenticationDetails(HttpServletRequest request) { public String getTokenValue() { return tokenValue; } + + /** + * The access token type used to authenticate the request (normally in an authorization header). + * + * @return the tokenType used to authenticate the request if known + */ + public String getTokenType() { + return tokenType; + } /** * Indicates the TCP/IP address the authentication request was received from. diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/DefaultOAuth2RequestAuthenticatorTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/DefaultOAuth2RequestAuthenticatorTests.java new file mode 100644 index 000000000..2c5e745d3 --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/DefaultOAuth2RequestAuthenticatorTests.java @@ -0,0 +1,51 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.springframework.security.oauth2.client; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.springframework.mock.http.client.MockClientHttpRequest; +import org.springframework.security.oauth2.client.http.AccessTokenRequiredException; +import org.springframework.security.oauth2.client.resource.BaseOAuth2ProtectedResourceDetails; +import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; + +/** + * @author Dave Syer + * + */ +public class DefaultOAuth2RequestAuthenticatorTests { + + private DefaultOAuth2RequestAuthenticator authenticator = new DefaultOAuth2RequestAuthenticator(); + + private MockClientHttpRequest request = new MockClientHttpRequest(); + + private DefaultOAuth2ClientContext context = new DefaultOAuth2ClientContext(); + + @Test(expected = AccessTokenRequiredException.class) + public void missingAccessToken() { + BaseOAuth2ProtectedResourceDetails resource = new BaseOAuth2ProtectedResourceDetails(); + authenticator.authenticate(resource, new DefaultOAuth2ClientContext(), request); + } + + @Test + public void addsAccessToken() { + context.setAccessToken(new DefaultOAuth2AccessToken("FOO")); + BaseOAuth2ProtectedResourceDetails resource = new BaseOAuth2ProtectedResourceDetails(); + authenticator.authenticate(resource, context, request); + String header = request.getHeaders().getFirst("Authorization"); + assertEquals("bearer FOO", header); + } + +} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilterTests.java index 0d9248680..1b84f709d 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilterTests.java @@ -40,6 +40,7 @@ import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.RequestTokenFactory; +import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails; import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices; public class OAuth2ClientAuthenticationProcessingFilterTests { @@ -71,6 +72,22 @@ public void testAuthentication() throws Exception { Mockito.verify(restTemplate, Mockito.times(1)).getAccessToken(); } + @Test + public void testAuthenticationWithTokenType() throws Exception { + filter.setRestTemplate(restTemplate); + filter.setTokenServices(tokenServices); + DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken("FOO"); + token.setTokenType("foo"); + Mockito.when(restTemplate.getAccessToken()).thenReturn(token); + Set scopes = new HashSet(); + scopes.addAll(Arrays.asList("read", "write")); + OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request("client", false, scopes); + this.authentication = new OAuth2Authentication(storedOAuth2Request, null); + Mockito.when(tokenServices.loadAuthentication("FOO")).thenReturn(authentication); + Authentication authentication = filter.attemptAuthentication(new MockHttpServletRequest(), null); + assertEquals("foo", ((OAuth2AuthenticationDetails) authentication.getDetails()).getTokenType()); + } + @Test public void testSuccessfulAuthentication() throws Exception { filter.setRestTemplate(restTemplate); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilterTests.java index af238925b..bbfb95802 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilterTests.java @@ -30,6 +30,7 @@ import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.RequestTokenFactory; @@ -70,6 +71,18 @@ public void testDetailsAdded() throws Exception { request.addHeader("Authorization", "Bearer FOO"); filter.doFilter(request, null, chain); assertNotNull(request.getAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_VALUE)); + assertEquals("Bearer", request.getAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_TYPE)); + Authentication result = SecurityContextHolder.getContext().getAuthentication(); + assertEquals(authentication, result); + assertNotNull(result.getDetails()); + } + + @Test + public void testDetailsAddedWithForm() throws Exception { + request.addParameter("access_token", "FOO"); + filter.doFilter(request, null, chain); + assertNotNull(request.getAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_VALUE)); + assertEquals(OAuth2AccessToken.BEARER_TYPE, request.getAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_TYPE)); Authentication result = SecurityContextHolder.getContext().getAuthentication(); assertEquals(authentication, result); assertNotNull(result.getDetails()); From b0bb5d3d5960d985c937a632f9c1e55a536568d2 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 26 Jan 2015 09:43:16 +0000 Subject: [PATCH 362/831] Add optional UserDetailsService to DefaultUserAuthenticationConverter Now authorities (and other interesting details) can be stored externally to the token, at least optionally. Often the token provider might have a different idea of user authorities than the local service decoding the token, so it helps to be able to extend the potential source of that data. The Principal in the resulting Authentication is the UserDetails, so there might also be other interesting data in there for access decisions. Fixes gh-358 --- .../DefaultUserAuthenticationConverter.java | 26 +++++- ...faultUserAuthenticationConverterTests.java | 87 +++++++++++-------- 2 files changed, 72 insertions(+), 41 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultUserAuthenticationConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultUserAuthenticationConverter.java index 318495365..c8891c48c 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultUserAuthenticationConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultUserAuthenticationConverter.java @@ -21,11 +21,13 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.util.StringUtils; /** - * Default implementation of {@link UserAuthenticationConverter}. Converts to and from an Authentication using only its name and - * authorities. + * Default implementation of {@link UserAuthenticationConverter}. Converts to and from an Authentication using only its + * name and authorities. * * @author Dave Syer * @@ -34,6 +36,17 @@ public class DefaultUserAuthenticationConverter implements UserAuthenticationCon private Collection defaultAuthorities; + private UserDetailsService userDetailsService; + + /** + * Optional {@link UserDetailsService} to use when extracting an {@link Authentication} from the incoming map. + * + * @param userDetailsService the userDetailsService to set + */ + public void setUserDetailsService(UserDetailsService userDetailsService) { + this.userDetailsService = userDetailsService; + } + /** * Default value for authorities if an Authentication is being created and the input has no data for authorities. * Note that unless this property is set, the default Authentication created by {@link #extractAuthentication(Map)} @@ -57,7 +70,14 @@ public void setDefaultAuthorities(String[] defaultAuthorities) { public Authentication extractAuthentication(Map map) { if (map.containsKey(USERNAME)) { - return new UsernamePasswordAuthenticationToken(map.get(USERNAME), "N/A", getAuthorities(map)); + Object principal = map.get(USERNAME); + Collection authorities = getAuthorities(map); + if (userDetailsService != null) { + UserDetails user = userDetailsService.loadUserByUsername((String) map.get(USERNAME)); + authorities = user.getAuthorities(); + principal = user; + } + return new UsernamePasswordAuthenticationToken(principal, "N/A", authorities); } return null; } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultUserAuthenticationConverterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultUserAuthenticationConverterTests.java index ff1fd4700..647324ddc 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultUserAuthenticationConverterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultUserAuthenticationConverterTests.java @@ -1,51 +1,62 @@ package org.springframework.security.oauth2.provider.token; -import org.junit.Test; -import org.springframework.security.core.Authentication; +import static org.junit.Assert.assertEquals; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; +import org.junit.Test; +import org.mockito.Mockito; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetailsService; /** - * Created with IntelliJ IDEA. - * User: saket - * Date: 29/09/2014 - * Time: 16:25 - * To change this template use File | Settings | File Templates. + * Created with IntelliJ IDEA. User: saket Date: 29/09/2014 Time: 16:25 To change this template use File | Settings | + * File Templates. */ public class DefaultUserAuthenticationConverterTests { - private UserAuthenticationConverter converter = new DefaultUserAuthenticationConverter(); - - @Test - public void shouldExtractAuthenticationWhenAuthoritiesIsCollection() throws Exception { - Map map = new HashMap(); - map.put(UserAuthenticationConverter.USERNAME, "test_user"); - ArrayList lists = new ArrayList(); - lists.add("a1"); - lists.add("a2"); - map.put(UserAuthenticationConverter.AUTHORITIES, lists); - - Authentication authentication = converter.extractAuthentication(map); - - assertNotEquals(authentication.getAuthorities(), null); - assertEquals(authentication.getAuthorities().size(), 2); - } - - @Test - public void shouldExtractAuthenticationWhenAuthoritiesIsString() throws Exception { - Map map = new HashMap(); - map.put(UserAuthenticationConverter.USERNAME, "test_user"); - map.put(UserAuthenticationConverter.AUTHORITIES, "a1,a2"); - - Authentication authentication = converter.extractAuthentication(map); - - assertNotEquals(authentication.getAuthorities(), null); - assertEquals(authentication.getAuthorities().size(), 2); - } + private DefaultUserAuthenticationConverter converter = new DefaultUserAuthenticationConverter(); + + @Test + public void shouldExtractAuthenticationWhenAuthoritiesIsCollection() throws Exception { + Map map = new HashMap(); + map.put(UserAuthenticationConverter.USERNAME, "test_user"); + ArrayList lists = new ArrayList(); + lists.add("a1"); + lists.add("a2"); + map.put(UserAuthenticationConverter.AUTHORITIES, lists); + + Authentication authentication = converter.extractAuthentication(map); + + assertEquals(2, authentication.getAuthorities().size()); + } + + @Test + public void shouldExtractAuthenticationWhenAuthoritiesIsString() throws Exception { + Map map = new HashMap(); + map.put(UserAuthenticationConverter.USERNAME, "test_user"); + map.put(UserAuthenticationConverter.AUTHORITIES, "a1,a2"); + + Authentication authentication = converter.extractAuthentication(map); + + assertEquals(2, authentication.getAuthorities().size()); + } + + @Test + public void shouldExtractAuthenticationWhenUserDetailsProvided() throws Exception { + Map map = new HashMap(); + map.put(UserAuthenticationConverter.USERNAME, "test_user"); + + UserDetailsService userDetailsService = Mockito.mock(UserDetailsService.class); + Mockito.when(userDetailsService.loadUserByUsername("test_user")).thenReturn( + new User("foo", "bar", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_SPAM"))); + converter.setUserDetailsService(userDetailsService); + Authentication authentication = converter.extractAuthentication(map); + + assertEquals("ROLE_SPAM", authentication.getAuthorities().iterator().next().toString()); + } } - From 2dc744bff4a2ebdfbf9eebdfc9d44fd84b4b4ccd Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 27 Jan 2015 08:58:25 +0000 Subject: [PATCH 363/831] Clarify CSRF and session creation policy for resource server It *is* possible to disable CSRF on a per-HttpSecurity basis, and also the same for session creation policy (I believe). So rather than making CRSF mandatory by default it is better to switch it off and also set to SessionCreationPolicy.STATELESS. N.B. if CRSF is *on*, even SessionCreationPolicy.STATELESS does not prevent the creation of a session (since the CsrfFilter itself has to look in the session for a token). Fixes gh-339 --- .../client/test/OAuth2ContextSetup.java | 6 +- .../token/OAuth2AccessTokenSupport.java | 1 + .../AuthorizationCodeAccessTokenProvider.java | 4 +- ...horizationServerSecurityConfiguration.java | 5 +- .../ResourceServerConfiguration.java | 13 +- .../ResourceServerSecurityConfigurer.java | 2 - ...bstractAuthorizationCodeProviderTests.java | 215 +-------------- ...ctEmptyAuthorizationCodeProviderTests.java | 255 ++++++++++++++++++ .../common/AbstractIntegrationTests.java | 29 ++ .../AbstractRefreshTokenSupportTests.java | 3 + .../src/main/java/demo/Application.java | 35 ++- .../src/test/java/demo/AdHocTests.java | 35 +++ .../AuthorizationCodeProviderCookieTests.java | 52 ++++ .../demo/AuthorizationCodeProviderTests.java | 12 + 14 files changed, 442 insertions(+), 225 deletions(-) create mode 100644 tests/annotation/common/src/main/java/sparklr/common/AbstractEmptyAuthorizationCodeProviderTests.java create mode 100644 tests/annotation/vanilla/src/test/java/demo/AdHocTests.java create mode 100644 tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderCookieTests.java diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/OAuth2ContextSetup.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/OAuth2ContextSetup.java index 3dad19eff..ee68b3995 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/OAuth2ContextSetup.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/OAuth2ContextSetup.java @@ -214,10 +214,10 @@ public OAuth2AccessToken getAccessToken() { if (accessToken != null) { return accessToken; } + if (accessTokenProvider != null) { + client.setAccessTokenProvider(accessTokenProvider); + } try { - if (accessTokenProvider != null) { - client.setAccessTokenProvider(accessTokenProvider); - } return client.getAccessToken(); } catch (OAuth2AccessDeniedException e) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/OAuth2AccessTokenSupport.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/OAuth2AccessTokenSupport.java index eaf3653ed..022882b11 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/OAuth2AccessTokenSupport.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/OAuth2AccessTokenSupport.java @@ -82,6 +82,7 @@ protected void prepareConnection(HttpURLConnection connection, String httpMethod throws IOException { super.prepareConnection(connection, httpMethod); connection.setInstanceFollowRedirects(false); + connection.setUseCaches(false); } }; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProvider.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProvider.java index 866cdb2ad..9e312f752 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProvider.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProvider.java @@ -216,9 +216,7 @@ public OAuth2AccessToken refreshAccessToken(OAuth2ProtectedResourceDetails resou private HttpHeaders getHeadersForTokenRequest(AccessTokenRequest request) { HttpHeaders headers = new HttpHeaders(); - if (request.getCookie() != null) { - headers.set("Cookie", request.getCookie()); - } + // No cookie for token request return headers; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java index 540204b66..7c996de17 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java @@ -24,6 +24,7 @@ import org.springframework.core.annotation.Order; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.oauth2.config.annotation.configuration.ClientDetailsServiceConfiguration; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; @@ -74,7 +75,9 @@ protected void configure(HttpSecurity http) throws Exception { .antMatchers(checkTokenPath).access(configurer.getCheckTokenAccess()) .and() .requestMatchers() - .antMatchers(tokenEndpointPath, tokenKeyPath, checkTokenPath); + .antMatchers(tokenEndpointPath, tokenKeyPath, checkTokenPath) + .and() + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER); // @formatter:on http.setSharedObject(ClientDetailsService.class, clientDetailsService); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java index 8e01f8fc0..b53870aa6 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java @@ -30,6 +30,7 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity.RequestMatcherConfigurer; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; import org.springframework.security.oauth2.provider.endpoint.FrameworkEndpointHandlerMapping; import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices; @@ -120,10 +121,12 @@ protected void configure(HttpSecurity http) throws Exception { ResourceServerTokenServices services = resolveTokenServices(); if (services != null) { resources.tokenServices(services); - } else { + } + else { if (tokenStore != null) { resources.tokenStore(tokenStore); - } else if (endpoints!=null) { + } + else if (endpoints != null) { resources.tokenStore(endpoints.getEndpointsConfigurer().getTokenStore()); } } @@ -132,8 +135,12 @@ protected void configure(HttpSecurity http) throws Exception { } // @formatter:off http - .exceptionHandling().accessDeniedHandler(resources.getAccessDeniedHandler()).and() + // N.B. exceptionHandling is duplicated in resources.configure() so that it works + .exceptionHandling().accessDeniedHandler(resources.getAccessDeniedHandler()) + .and() .anonymous().disable() + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) + .and() .csrf().disable(); // @formatter:on http.apply(resources); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java index 77122ff58..92f0e5c38 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java @@ -140,8 +140,6 @@ public ResourceServerSecurityConfigurer tokenServices(ResourceServerTokenService @Override public void init(HttpSecurity http) throws Exception { registerDefaultAuthenticationEntryPoint(http); - // TODO: remove this - http.csrf().disable(); } @SuppressWarnings("unchecked") diff --git a/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java b/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java index fcb5512bb..96b20bbc3 100755 --- a/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java @@ -15,39 +15,24 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import java.io.IOException; -import java.nio.charset.Charset; import java.util.Arrays; -import java.util.concurrent.atomic.AtomicReference; import org.junit.Test; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -import org.springframework.http.client.ClientHttpResponse; -import org.springframework.security.oauth2.client.OAuth2RestTemplate; -import org.springframework.security.oauth2.client.resource.UserApprovalRequiredException; import org.springframework.security.oauth2.client.resource.UserRedirectRequiredException; -import org.springframework.security.oauth2.client.test.BeforeOAuth2Context; import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration; import org.springframework.security.oauth2.client.token.AccessTokenRequest; -import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider; -import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.exceptions.RedirectMismatchException; import org.springframework.security.oauth2.common.util.OAuth2Utils; import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.StreamUtils; -import org.springframework.web.client.DefaultResponseErrorHandler; import org.springframework.web.client.HttpClientErrorException; -import org.springframework.web.client.ResourceAccessException; -import org.springframework.web.client.ResponseErrorHandler; -import org.springframework.web.client.ResponseExtractor; import sparklr.common.HttpTestUtils.UriBuilder; @@ -55,68 +40,7 @@ * @author Dave Syer * @author Luke Taylor */ -public abstract class AbstractAuthorizationCodeProviderTests extends AbstractIntegrationTests { - - private AuthorizationCodeAccessTokenProvider accessTokenProvider; - - private ClientHttpResponse tokenEndpointResponse; - - @BeforeOAuth2Context - public void setupAccessTokenProvider() { - accessTokenProvider = new AuthorizationCodeAccessTokenProvider() { - - private ResponseExtractor extractor = super.getResponseExtractor(); - - private ResponseExtractor> authExtractor = super.getAuthorizationResponseExtractor(); - - private ResponseErrorHandler errorHandler = super.getResponseErrorHandler(); - - @Override - protected ResponseErrorHandler getResponseErrorHandler() { - return new DefaultResponseErrorHandler() { - public void handleError(ClientHttpResponse response) throws IOException { - response.getHeaders(); - response.getStatusCode(); - tokenEndpointResponse = response; - errorHandler.handleError(response); - } - }; - } - - @Override - protected ResponseExtractor getResponseExtractor() { - return new ResponseExtractor() { - - public OAuth2AccessToken extractData(ClientHttpResponse response) throws IOException { - try { - response.getHeaders(); - response.getStatusCode(); - tokenEndpointResponse = response; - return extractor.extractData(response); - } - catch (ResourceAccessException e) { - return null; - } - } - - }; - } - - @Override - protected ResponseExtractor> getAuthorizationResponseExtractor() { - return new ResponseExtractor>() { - - public ResponseEntity extractData(ClientHttpResponse response) throws IOException { - response.getHeaders(); - response.getStatusCode(); - tokenEndpointResponse = response; - return authExtractor.extractData(response); - } - }; - } - }; - context.setAccessTokenProvider(accessTokenProvider); - } +public abstract class AbstractAuthorizationCodeProviderTests extends AbstractEmptyAuthorizationCodeProviderTests { @Test @OAuth2ContextConfiguration(resource = MyTrustedClient.class, initialize = false) @@ -127,7 +51,7 @@ public void testUnauthenticatedAuthorizationRespondsUnauthorized() throws Except request.add(OAuth2Utils.USER_OAUTH_APPROVAL, "true"); try { - String code = accessTokenProvider.obtainAuthorizationCode(context.getResource(), request); + String code = getAccessTokenProvider().obtainAuthorizationCode(context.getResource(), request); assertNotNull(code); fail("Expected UserRedirectRequiredException"); } @@ -168,7 +92,7 @@ public void testWrongRedirectUri() throws Exception { catch (RedirectMismatchException e) { // expected } - assertEquals(HttpStatus.BAD_REQUEST, tokenEndpointResponse.getStatusCode()); + assertEquals(HttpStatus.BAD_REQUEST, getTokenEndpointResponse().getStatusCode()); } @Test @@ -187,7 +111,7 @@ public void testUserDeniesConfirmation() throws Exception { assertTrue(location.startsWith("http://anywhere/")); assertTrue(location.substring(location.indexOf('?')).contains("error=access_denied")); // It was a redirect that triggered our client redirect exception: - assertEquals(HttpStatus.FOUND, tokenEndpointResponse.getStatusCode()); + assertEquals(HttpStatus.FOUND, getTokenEndpointResponse().getStatusCode()); } @Test @@ -310,135 +234,4 @@ public void testRegisteredRedirectWithWrongOneInTokenEndpoint() throws Exception } } - protected ResponseEntity attemptToGetConfirmationPage(String clientId, String redirectUri) { - return attemptToGetConfirmationPage(clientId, redirectUri, "code"); - } - - protected ResponseEntity attemptToGetConfirmationPage(String clientId, String redirectUri, String responseType) { - HttpHeaders headers = getAuthenticatedHeaders(); - return http.getForString(getAuthorizeUrl(clientId, redirectUri, responseType, "read"), headers); - } - - private String getAuthorizeUrl(String clientId, String redirectUri, String responseType, String scope) { - UriBuilder uri = http.buildUri(authorizePath()).queryParam("state", "mystateid").queryParam("scope", scope); - if (responseType != null) { - uri.queryParam("response_type", responseType); - } - if (clientId != null) { - uri.queryParam("client_id", clientId); - } - if (redirectUri != null) { - uri.queryParam("redirect_uri", redirectUri); - } - return uri.build().toString(); - } - - private HttpHeaders getAuthenticatedHeaders() { - HttpHeaders headers = new HttpHeaders(); - headers.setAccept(Arrays.asList(MediaType.TEXT_HTML)); - headers.set("Authorization", getBasicAuthentication()); - if (context.getRestTemplate() != null) { - context.getAccessTokenRequest().setHeaders(headers); - } - return headers; - } - - private String getAuthorizeUrl(String clientId, String redirectUri, String scope) { - UriBuilder uri = http.buildUri(authorizePath()).queryParam("response_type", "code") - .queryParam("state", "mystateid").queryParam("scope", scope); - if (clientId != null) { - uri.queryParam("client_id", clientId); - } - if (redirectUri != null) { - uri.queryParam("redirect_uri", redirectUri); - } - return uri.build().toString(); - } - - protected void approveAccessTokenGrant(String currentUri, boolean approved) { - - AccessTokenRequest request = context.getAccessTokenRequest(); - request.setHeaders(getAuthenticatedHeaders()); - AuthorizationCodeResourceDetails resource = (AuthorizationCodeResourceDetails) context.getResource(); - - if (currentUri != null) { - request.setCurrentUri(currentUri); - } - - String location = null; - - try { - // First try to obtain the access token... - assertNotNull(context.getAccessToken()); - fail("Expected UserRedirectRequiredException"); - } - catch (UserRedirectRequiredException e) { - // Expected and necessary, so that the correct state is set up in the request... - location = e.getRedirectUri(); - } - - assertTrue(location.startsWith(resource.getUserAuthorizationUri())); - assertNull(request.getAuthorizationCode()); - - verifyAuthorizationPage(context.getRestTemplate(), location); - - try { - // Now try again and the token provider will redirect for user approval... - assertNotNull(context.getAccessToken()); - fail("Expected UserRedirectRequiredException"); - } - catch (UserApprovalRequiredException e) { - // Expected and necessary, so that the user can approve the grant... - location = e.getApprovalUri(); - } - - assertTrue(location.startsWith(resource.getUserAuthorizationUri())); - assertNull(request.getAuthorizationCode()); - - // The approval (will be processed on the next attempt to obtain an access token)... - request.set(OAuth2Utils.USER_OAUTH_APPROVAL, "" + approved); - - } - - private void verifyAuthorizationPage(OAuth2RestTemplate restTemplate, String location) { - final AtomicReference confirmationPage = new AtomicReference(); - AuthorizationCodeAccessTokenProvider provider = new AuthorizationCodeAccessTokenProvider() { - @Override - protected ResponseExtractor> getAuthorizationResponseExtractor() { - return new ResponseExtractor>() { - public ResponseEntity extractData(ClientHttpResponse response) throws IOException { - confirmationPage.set(StreamUtils.copyToString(response.getBody(), Charset.forName("UTF-8"))); - return new ResponseEntity(response.getHeaders(), response.getStatusCode()); - } - }; - } - }; - try { - provider.obtainAuthorizationCode(restTemplate.getResource(), restTemplate.getOAuth2ClientContext().getAccessTokenRequest()); - } catch (UserApprovalRequiredException e) { - // ignore - } - String page = confirmationPage.get(); - verifyAuthorizationPage(page); - } - - protected void verifyAuthorizationPage(String page) { - } - - protected static class MyTrustedClient extends AuthorizationCodeResourceDetails { - public MyTrustedClient(Object target) { - super(); - setClientId("my-trusted-client"); - setScope(Arrays.asList("read")); - setId(getClientId()); - } - } - - protected static class MyClientWithRegisteredRedirect extends MyTrustedClient { - public MyClientWithRegisteredRedirect(Object target) { - super(target); - setClientId("my-client-with-registered-redirect"); - setPreEstablishedRedirectUri("http://anywhere/?key=value"); - } - } } diff --git a/tests/annotation/common/src/main/java/sparklr/common/AbstractEmptyAuthorizationCodeProviderTests.java b/tests/annotation/common/src/main/java/sparklr/common/AbstractEmptyAuthorizationCodeProviderTests.java new file mode 100644 index 000000000..1459a9817 --- /dev/null +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractEmptyAuthorizationCodeProviderTests.java @@ -0,0 +1,255 @@ +/* + * Copyright 2006-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 sparklr.common; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.concurrent.atomic.AtomicReference; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.security.oauth2.client.OAuth2RestTemplate; +import org.springframework.security.oauth2.client.resource.UserApprovalRequiredException; +import org.springframework.security.oauth2.client.resource.UserRedirectRequiredException; +import org.springframework.security.oauth2.client.test.BeforeOAuth2Context; +import org.springframework.security.oauth2.client.token.AccessTokenRequest; +import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider; +import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.common.util.OAuth2Utils; +import org.springframework.util.StreamUtils; +import org.springframework.web.client.DefaultResponseErrorHandler; +import org.springframework.web.client.ResourceAccessException; +import org.springframework.web.client.ResponseErrorHandler; +import org.springframework.web.client.ResponseExtractor; + +import sparklr.common.HttpTestUtils.UriBuilder; + +/** + * @author Dave Syer + * @author Luke Taylor + */ +public abstract class AbstractEmptyAuthorizationCodeProviderTests extends AbstractIntegrationTests { + + private AuthorizationCodeAccessTokenProvider accessTokenProvider; + + private ClientHttpResponse tokenEndpointResponse; + + @BeforeOAuth2Context + public void setupAccessTokenProvider() { + accessTokenProvider = new AuthorizationCodeAccessTokenProvider() { + + private ResponseExtractor extractor = super.getResponseExtractor(); + + private ResponseExtractor> authExtractor = super.getAuthorizationResponseExtractor(); + + private ResponseErrorHandler errorHandler = super.getResponseErrorHandler(); + + @Override + protected ResponseErrorHandler getResponseErrorHandler() { + return new DefaultResponseErrorHandler() { + public void handleError(ClientHttpResponse response) throws IOException { + response.getHeaders(); + response.getStatusCode(); + tokenEndpointResponse = response; + errorHandler.handleError(response); + } + }; + } + + @Override + protected ResponseExtractor getResponseExtractor() { + return new ResponseExtractor() { + + public OAuth2AccessToken extractData(ClientHttpResponse response) throws IOException { + try { + response.getHeaders(); + response.getStatusCode(); + tokenEndpointResponse = response; + return extractor.extractData(response); + } + catch (ResourceAccessException e) { + return null; + } + } + + }; + } + + @Override + protected ResponseExtractor> getAuthorizationResponseExtractor() { + return new ResponseExtractor>() { + + public ResponseEntity extractData(ClientHttpResponse response) throws IOException { + response.getHeaders(); + response.getStatusCode(); + tokenEndpointResponse = response; + return authExtractor.extractData(response); + } + }; + } + }; + context.setAccessTokenProvider(getAccessTokenProvider()); + } + + protected ResponseEntity attemptToGetConfirmationPage(String clientId, String redirectUri) { + return attemptToGetConfirmationPage(clientId, redirectUri, "code"); + } + + protected ResponseEntity attemptToGetConfirmationPage(String clientId, String redirectUri, + String responseType) { + HttpHeaders headers = getAuthenticatedHeaders(); + return http.getForString(getAuthorizeUrl(clientId, redirectUri, responseType, "read"), headers); + } + + private String getAuthorizeUrl(String clientId, String redirectUri, String responseType, String scope) { + UriBuilder uri = http.buildUri(authorizePath()).queryParam("state", "mystateid").queryParam("scope", scope); + if (responseType != null) { + uri.queryParam("response_type", responseType); + } + if (clientId != null) { + uri.queryParam("client_id", clientId); + } + if (redirectUri != null) { + uri.queryParam("redirect_uri", redirectUri); + } + return uri.build().toString(); + } + + protected HttpHeaders getAuthenticatedHeaders() { + HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Arrays.asList(MediaType.TEXT_HTML)); + headers.set("Authorization", getBasicAuthentication()); + if (context.getRestTemplate() != null) { + context.getAccessTokenRequest().setHeaders(headers); + } + return headers; + } + + protected String getAuthorizeUrl(String clientId, String redirectUri, String scope) { + UriBuilder uri = http.buildUri(authorizePath()).queryParam("response_type", "code") + .queryParam("state", "mystateid").queryParam("scope", scope); + if (clientId != null) { + uri.queryParam("client_id", clientId); + } + if (redirectUri != null) { + uri.queryParam("redirect_uri", redirectUri); + } + return uri.build().toString(); + } + + protected void approveAccessTokenGrant(String currentUri, boolean approved) { + + AccessTokenRequest request = context.getAccessTokenRequest(); + request.setHeaders(getAuthenticatedHeaders()); + AuthorizationCodeResourceDetails resource = (AuthorizationCodeResourceDetails) context.getResource(); + + if (currentUri != null) { + request.setCurrentUri(currentUri); + } + + String location = null; + + try { + // First try to obtain the access token... + assertNotNull(context.getAccessToken()); + fail("Expected UserRedirectRequiredException"); + } + catch (UserRedirectRequiredException e) { + // Expected and necessary, so that the correct state is set up in the request... + location = e.getRedirectUri(); + } + + assertTrue(location.startsWith(resource.getUserAuthorizationUri())); + assertNull(request.getAuthorizationCode()); + + verifyAuthorizationPage(context.getRestTemplate(), location); + + try { + // Now try again and the token provider will redirect for user approval... + assertNotNull(context.getAccessToken()); + fail("Expected UserRedirectRequiredException"); + } + catch (UserApprovalRequiredException e) { + // Expected and necessary, so that the user can approve the grant... + location = e.getApprovalUri(); + } + + assertTrue(location.startsWith(resource.getUserAuthorizationUri())); + assertNull(request.getAuthorizationCode()); + + // The approval (will be processed on the next attempt to obtain an access token)... + request.set(OAuth2Utils.USER_OAUTH_APPROVAL, "" + approved); + + } + + private void verifyAuthorizationPage(OAuth2RestTemplate restTemplate, String location) { + final AtomicReference confirmationPage = new AtomicReference(); + AuthorizationCodeAccessTokenProvider provider = new AuthorizationCodeAccessTokenProvider() { + @Override + protected ResponseExtractor> getAuthorizationResponseExtractor() { + return new ResponseExtractor>() { + public ResponseEntity extractData(ClientHttpResponse response) throws IOException { + confirmationPage.set(StreamUtils.copyToString(response.getBody(), Charset.forName("UTF-8"))); + return new ResponseEntity(response.getHeaders(), response.getStatusCode()); + } + }; + } + }; + try { + provider.obtainAuthorizationCode(restTemplate.getResource(), restTemplate.getOAuth2ClientContext() + .getAccessTokenRequest()); + } + catch (UserApprovalRequiredException e) { + // ignore + } + String page = confirmationPage.get(); + verifyAuthorizationPage(page); + } + + protected void verifyAuthorizationPage(String page) { + } + + protected AuthorizationCodeAccessTokenProvider getAccessTokenProvider() { + return accessTokenProvider; + } + + protected ClientHttpResponse getTokenEndpointResponse() { + return tokenEndpointResponse; + } + + protected static class MyTrustedClient extends AuthorizationCodeResourceDetails { + public MyTrustedClient(Object target) { + super(); + setClientId("my-trusted-client"); + setScope(Arrays.asList("read")); + setId(getClientId()); + } + } + + protected static class MyClientWithRegisteredRedirect extends MyTrustedClient { + public MyClientWithRegisteredRedirect(Object target) { + super(target); + setClientId("my-client-with-registered-redirect"); + setPreEstablishedRedirectUri("http://anywhere/?key=value"); + } + } +} 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 5fb4878a5..ca90a208f 100644 --- a/tests/annotation/common/src/main/java/sparklr/common/AbstractIntegrationTests.java +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractIntegrationTests.java @@ -26,6 +26,7 @@ import org.junit.runner.RunWith; import org.springframework.aop.framework.Advised; 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.autoconfigure.security.SecurityProperties; import org.springframework.boot.autoconfigure.web.ServerProperties; @@ -41,9 +42,11 @@ import org.springframework.security.oauth2.client.token.grant.implicit.ImplicitResourceDetails; import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordResourceDetails; import org.springframework.security.oauth2.client.token.grant.redirect.AbstractRedirectResourceDetails; +import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.provider.approval.ApprovalStore; import org.springframework.security.oauth2.provider.approval.InMemoryApprovalStore; import org.springframework.security.oauth2.provider.approval.JdbcApprovalStore; +import org.springframework.security.oauth2.provider.token.ConsumerTokenServices; 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; @@ -90,6 +93,32 @@ public abstract class AbstractIntegrationTests { @Autowired private ServerProperties server; + @Autowired(required=false) + @Qualifier("consumerTokenServices") + private ConsumerTokenServices tokenServices; + + @After + public void cancelToken() { + try { + OAuth2AccessToken token = context.getOAuth2ClientContext().getAccessToken(); + if (token != null) { + tokenServices.revokeToken(token.getValue()); + } + } + catch (Exception e) { + // ignore + } + } + + protected void cancelToken(String value) { + try { + tokenServices.revokeToken(value); + } + catch (Exception e) { + // ignore + } + } + @Before public void init() { String prefix = server.getServletPrefix(); diff --git a/tests/annotation/common/src/main/java/sparklr/common/AbstractRefreshTokenSupportTests.java b/tests/annotation/common/src/main/java/sparklr/common/AbstractRefreshTokenSupportTests.java index 726b1fc2d..644aef77e 100644 --- a/tests/annotation/common/src/main/java/sparklr/common/AbstractRefreshTokenSupportTests.java +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractRefreshTokenSupportTests.java @@ -36,6 +36,9 @@ public void testHappyDay() throws Exception { assertFalse(newAccessToken.getValue().equals(accessToken.getValue())); verifyAccessTokens(accessToken, newAccessToken); + + cancelToken(accessToken.getValue()); + cancelToken(newAccessToken.getValue()); } diff --git a/tests/annotation/vanilla/src/main/java/demo/Application.java b/tests/annotation/vanilla/src/main/java/demo/Application.java index 94559d110..d84285bac 100644 --- a/tests/annotation/vanilla/src/main/java/demo/Application.java +++ b/tests/annotation/vanilla/src/main/java/demo/Application.java @@ -1,21 +1,30 @@ package demo; +import javax.servlet.http.HttpSessionEvent; +import javax.servlet.http.HttpSessionListener; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; 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.context.annotation.Configuration; +import org.springframework.http.HttpStatus; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; 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.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; +import org.springframework.stereotype.Component; +import org.springframework.util.MultiValueMap; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; @Configuration -@ComponentScan @EnableAutoConfiguration @EnableResourceServer @RestController @@ -30,6 +39,12 @@ public String home() { return "Hello World"; } + @RequestMapping(value="/", method=RequestMethod.POST) + @ResponseStatus(HttpStatus.CREATED) + public String create(@RequestBody MultiValueMap map) { + return "OK"; + } + @Configuration @EnableAuthorizationServer protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter { @@ -71,4 +86,20 @@ public void configure(ClientDetailsServiceConfigurer clients) throws Exception { } + @Component + protected static class SessionListener implements HttpSessionListener { + + private static Log logger = LogFactory.getLog(SessionListener.class); + + @Override + public void sessionCreated(HttpSessionEvent event) { + logger.info("Created: " + event.getSession().getId()); + } + + @Override + public void sessionDestroyed(HttpSessionEvent event) { + logger.info("Destroyed: " + event.getSession().getId()); + } + + } } diff --git a/tests/annotation/vanilla/src/test/java/demo/AdHocTests.java b/tests/annotation/vanilla/src/test/java/demo/AdHocTests.java new file mode 100644 index 000000000..f3f947369 --- /dev/null +++ b/tests/annotation/vanilla/src/test/java/demo/AdHocTests.java @@ -0,0 +1,35 @@ +/* + * Copyright 20013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package demo; + +import org.junit.Ignore; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +/** + * @author Dave Syer + * + */ +@RunWith(Suite.class) +// @formatter:off +@SuiteClasses({ + RefreshTokenSupportTests.class, + AuthorizationCodeProviderCookieTests.class + }) +// @formatter:on +@Ignore("Test suite for tracking order dependencies") +public class AdHocTests { + +} diff --git a/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderCookieTests.java b/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderCookieTests.java new file mode 100644 index 000000000..1b6f55475 --- /dev/null +++ b/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderCookieTests.java @@ -0,0 +1,52 @@ +/* + * Copyright 2006-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 demo; + +import static org.junit.Assert.assertEquals; +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; +import org.springframework.util.LinkedMultiValueMap; + +import sparklr.common.AbstractEmptyAuthorizationCodeProviderTests; + +/** + * @author Dave Syer + */ +@SpringApplicationConfiguration(classes = Application.class) +public class AuthorizationCodeProviderCookieTests extends AbstractEmptyAuthorizationCodeProviderTests { + + @Test + @OAuth2ContextConfiguration(resource = MyTrustedClient.class, initialize = false) + public void testPostToProtectedResource() throws Exception { + approveAccessTokenGrant("http://anywhere/", true); + assertNotNull(context.getAccessToken()); + LinkedMultiValueMap form = new LinkedMultiValueMap<>(); + assertEquals(HttpStatus.CREATED, http.postForStatus("/", getAuthenticatedHeaders(), form).getStatusCode()); + } + + @Override + protected HttpHeaders getAuthenticatedHeaders() { + HttpHeaders headers = super.getAuthenticatedHeaders(); + if (context.getAccessTokenRequest().getCookie() != null) { + headers.remove("Authorization"); + headers.set("Cookie", context.getAccessTokenRequest().getCookie()); + } + return headers; + } + +} diff --git a/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java index 20c5b9ef7..beabbc002 100755 --- a/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java +++ b/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -13,12 +13,15 @@ package demo; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; 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; +import org.springframework.util.LinkedMultiValueMap; import sparklr.common.AbstractAuthorizationCodeProviderTests; @@ -27,6 +30,15 @@ */ @SpringApplicationConfiguration(classes = Application.class) public class AuthorizationCodeProviderTests extends AbstractAuthorizationCodeProviderTests { + + @Test + @OAuth2ContextConfiguration(resource = MyTrustedClient.class, initialize = false) + public void testPostToProtectedResource() throws Exception { + approveAccessTokenGrant("http://anywhere/", true); + assertNotNull(context.getAccessToken()); + LinkedMultiValueMap form = new LinkedMultiValueMap<>(); + assertEquals(HttpStatus.CREATED, http.postForStatus("/", form).getStatusCode()); + } @Test public void testWrongClientIdProvided() throws Exception { From d3eea9eef09efb28def87626280a0fe92e589b24 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 27 Jan 2015 11:18:20 +0000 Subject: [PATCH 364/831] Add some more docs for @EnableResourceServer --- docs/oauth2.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/oauth2.md b/docs/oauth2.md index e6aafd1ee..172e3093a 100644 --- a/docs/oauth2.md +++ b/docs/oauth2.md @@ -128,6 +128,10 @@ A Resource Server (can be the same as the Authorization Server or a separate app * `tokenServices`: the bean that defines the token services (instance of `ResourceServerTokenServices`). * `resourceId`: the id for the resource (optional, but recommended and will be validated by the auth server if present). +* other extension points for the resourecs server (e.g. `tokenExtractor` for extracting the tokens from incoming requests) +* request matchers for protected resources (defaults to all) +* access rules for protected resources (defaults to plain "authenticated") +* other customizations for the protected resources permitted by the `HttpSecurity` configurer in Spring Security The `@EnableResourceServer` annotation adds a filter of type `OAuth2AuthenticationProcessingFilter` automatically to the Spring Security filter chain. From d8cb5c4dab0c7f296da1111dd150616510e5ae7e Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 27 Jan 2015 12:06:18 +0000 Subject: [PATCH 365/831] Optionally create refresh tokens with infinite lifetime If a DefaultTokenServices or a ClientDetails has a refreshTokenValidity less than or equal to zero, it will result in a non-expiring refresh token. Fixes gh-166 --- .../oauth2/provider/ClientDetails.java | 3 ++- .../provider/token/DefaultTokenServices.java | 17 +++++++++++------ .../provider/token/store/JwtTokenStore.java | 13 ++++++++++--- .../AbstractDefaultTokenServicesTests.java | 10 ++++++++++ .../token/store/JwtTokenStoreTests.java | 18 ++++++++++++++++-- 5 files changed, 49 insertions(+), 12 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientDetails.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientDetails.java index 45bbd4d30..e5f345ddc 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientDetails.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientDetails.java @@ -90,7 +90,8 @@ public interface ClientDetails extends Serializable { Integer getAccessTokenValiditySeconds(); /** - * The refresh token validity period for this client. Zero or negative for default value set by token service. + * The refresh token validity period for this client. Null for default value set by token service, and + * zero or negative for non-expiring tokens. * * @return the refresh token validity period */ diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java index 277c8d760..d19093b48 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java @@ -21,6 +21,7 @@ import org.springframework.security.core.AuthenticationException; import org.springframework.security.oauth2.common.DefaultExpiringOAuth2RefreshToken; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; +import org.springframework.security.oauth2.common.DefaultOAuth2RefreshToken; import org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2RefreshToken; @@ -207,7 +208,8 @@ public OAuth2AccessToken readAccessToken(String accessToken) { return tokenStore.readAccessToken(accessToken); } - public OAuth2Authentication loadAuthentication(String accessTokenValue) throws AuthenticationException, InvalidTokenException { + public OAuth2Authentication loadAuthentication(String accessTokenValue) throws AuthenticationException, + InvalidTokenException { OAuth2AccessToken accessToken = tokenStore.readAccessToken(accessTokenValue); if (accessToken == null) { throw new InvalidTokenException("Invalid access token: " + accessTokenValue); @@ -254,14 +256,17 @@ public boolean revokeToken(String tokenValue) { return true; } - private ExpiringOAuth2RefreshToken createRefreshToken(OAuth2Authentication authentication) { + private OAuth2RefreshToken createRefreshToken(OAuth2Authentication authentication) { if (!isSupportRefreshToken(authentication.getOAuth2Request())) { return null; } int validitySeconds = getRefreshTokenValiditySeconds(authentication.getOAuth2Request()); - ExpiringOAuth2RefreshToken refreshToken = new DefaultExpiringOAuth2RefreshToken(UUID.randomUUID().toString(), - new Date(System.currentTimeMillis() + (validitySeconds * 1000L))); - return refreshToken; + String value = UUID.randomUUID().toString(); + if (validitySeconds > 0) { + return new DefaultExpiringOAuth2RefreshToken(value, new Date(System.currentTimeMillis() + + (validitySeconds * 1000L))); + } + return new DefaultOAuth2RefreshToken(value); } private OAuth2AccessToken createAccessToken(OAuth2Authentication authentication, OAuth2RefreshToken refreshToken) { @@ -335,7 +340,7 @@ public void setTokenEnhancer(TokenEnhancer accessTokenEnhancer) { } /** - * The validity (in seconds) of the refresh token. + * The validity (in seconds) of the refresh token. If less than or equal to zero then the tokens will be non-expiring. * * @param refreshTokenValiditySeconds The validity (in seconds) of the refresh token. */ diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStore.java index 816ff56ff..0aa82e3c3 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStore.java @@ -21,7 +21,7 @@ import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.common.DefaultExpiringOAuth2RefreshToken; -import org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken; +import org.springframework.security.oauth2.common.DefaultOAuth2RefreshToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2RefreshToken; import org.springframework.security.oauth2.provider.OAuth2Authentication; @@ -106,8 +106,7 @@ public void storeRefreshToken(OAuth2RefreshToken refreshToken, OAuth2Authenticat @Override public OAuth2RefreshToken readRefreshToken(String tokenValue) { OAuth2AccessToken encodedRefreshToken = readAccessToken(tokenValue); - ExpiringOAuth2RefreshToken refreshToken = new DefaultExpiringOAuth2RefreshToken(encodedRefreshToken.getValue(), - encodedRefreshToken.getExpiration()); + OAuth2RefreshToken refreshToken = createRefreshToken(encodedRefreshToken); if (approvalStore != null) { OAuth2Authentication authentication = readAuthentication(tokenValue); if (authentication.getUserAuthentication() != null) { @@ -128,6 +127,14 @@ public OAuth2RefreshToken readRefreshToken(String tokenValue) { return refreshToken; } + private OAuth2RefreshToken createRefreshToken(OAuth2AccessToken encodedRefreshToken) { + if (encodedRefreshToken.getExpiration()!=null) { + return new DefaultExpiringOAuth2RefreshToken(encodedRefreshToken.getValue(), + encodedRefreshToken.getExpiration()); + } + return new DefaultOAuth2RefreshToken(encodedRefreshToken.getValue()); + } + @Override public OAuth2Authentication readAuthenticationForRefreshToken(OAuth2RefreshToken token) { return readAuthentication(token.getValue()); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractDefaultTokenServicesTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractDefaultTokenServicesTests.java index cb8918a44..40207ea5f 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractDefaultTokenServicesTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractDefaultTokenServicesTests.java @@ -14,6 +14,7 @@ package org.springframework.security.oauth2.provider.token; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -29,6 +30,7 @@ import org.springframework.security.oauth2.common.DefaultExpiringOAuth2RefreshToken; import org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.common.OAuth2RefreshToken; import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; @@ -165,6 +167,14 @@ public void testRefreshedTokenHasScopes() throws Exception { assertEquals("[read, write]", refreshedAccessToken.getScope().toString()); } + @Test + public void testRefreshedTokenNotExpiring() throws Exception { + getTokenServices().setRefreshTokenValiditySeconds(0); + OAuth2RefreshToken expectedExpiringRefreshToken = getTokenServices() + .createAccessToken(createAuthentication()).getRefreshToken(); + assertFalse(expectedExpiringRefreshToken instanceof DefaultExpiringOAuth2RefreshToken); + } + protected void configureTokenServices(DefaultTokenServices services) throws Exception { services.setTokenStore(tokenStore); services.setSupportRefreshToken(true); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStoreTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStoreTests.java index 0c0ba0d2f..d431b8f16 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStoreTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStoreTests.java @@ -1,6 +1,8 @@ package org.springframework.security.oauth2.provider.token.store; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import java.util.Collections; import java.util.Date; @@ -8,6 +10,7 @@ import org.junit.Before; import org.junit.Test; import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.oauth2.common.DefaultExpiringOAuth2RefreshToken; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.DefaultOAuth2RefreshToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; @@ -17,8 +20,6 @@ import org.springframework.security.oauth2.provider.approval.Approval; import org.springframework.security.oauth2.provider.approval.Approval.ApprovalStatus; import org.springframework.security.oauth2.provider.approval.InMemoryApprovalStore; -import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; -import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; /** * @author Dave Syer @@ -72,6 +73,19 @@ public void testReadRefreshToken() throws Exception { assertEquals(expectedOAuth2AccessToken, tokenStore.readRefreshToken(expectedOAuth2AccessToken.getValue())); } + @Test + public void testReadNonExpiringRefreshToken() throws Exception { + assertFalse(tokenStore.readRefreshToken(expectedOAuth2AccessToken.getValue()) instanceof DefaultExpiringOAuth2RefreshToken); + } + + @Test + public void testReadExpiringRefreshToken() throws Exception { + DefaultOAuth2AccessToken original = new DefaultOAuth2AccessToken("FOO"); + original.setExpiration(new Date()); + DefaultOAuth2AccessToken token = (DefaultOAuth2AccessToken) enhancer.enhance(original, expectedAuthentication); + assertTrue(tokenStore.readRefreshToken(token.getValue()) instanceof DefaultExpiringOAuth2RefreshToken); + } + @Test public void testReadAuthentication() throws Exception { checkAuthentications(expectedAuthentication, tokenStore.readAuthentication(expectedOAuth2AccessToken)); From 4be7f8d627d203e992135dafbcf302dd54665492 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 27 Jan 2015 13:15:57 +0000 Subject: [PATCH 366/831] Ensure JWT refresh tokens cannot be used as access tokens ... and vice-versa (not such a problem). This change adds a new claim to JWT refresh tokens referring back to the original access token (ati). Fixes gh-363 --- .../provider/token/AccessTokenConverter.java | 2 + .../token/store/JwtAccessTokenConverter.java | 10 +++ .../provider/token/store/JwtTokenStore.java | 14 +++- .../store/JwtAccessTokenConverterTests.java | 26 ++++--- .../token/store/JwtTokenStoreTests.java | 69 ++++++++++++++++--- 5 files changed, 100 insertions(+), 21 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AccessTokenConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AccessTokenConverter.java index 4a0b0607f..faa4c2eef 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AccessTokenConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AccessTokenConverter.java @@ -33,6 +33,8 @@ public interface AccessTokenConverter { final String JTI = "jti"; + final String ATI = "ati"; + final String SCOPE = OAuth2AccessToken.SCOPE; final String AUTHORITIES = "authorities"; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java index 25828e878..a525f82a2 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java @@ -64,6 +64,11 @@ public class JwtAccessTokenConverter implements TokenEnhancer, AccessTokenConver */ public static final String TOKEN_ID = AccessTokenConverter.JTI; + /** + * Field name for access token id. + */ + public static final String ACCESS_TOKEN_ID = AccessTokenConverter.ATI; + private static final Log logger = LogFactory.getLog(JwtAccessTokenConverter.class); private AccessTokenConverter tokenConverter = new DefaultAccessTokenConverter(); @@ -200,6 +205,7 @@ public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentica encodedRefreshToken.setValue(refreshToken.getValue()); Map refreshTokenInfo = new LinkedHashMap(accessToken.getAdditionalInformation()); refreshTokenInfo.put(TOKEN_ID, encodedRefreshToken.getValue()); + refreshTokenInfo.put(ACCESS_TOKEN_ID, tokenId); encodedRefreshToken.setAdditionalInformation(refreshTokenInfo); DefaultOAuth2RefreshToken token = new DefaultOAuth2RefreshToken(encode(encodedRefreshToken, authentication)); if (refreshToken instanceof ExpiringOAuth2RefreshToken) { @@ -211,6 +217,10 @@ public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentica } return result; } + + public boolean isRefreshToken(OAuth2AccessToken token) { + return token.getAdditionalInformation().containsKey(ACCESS_TOKEN_ID); + } protected String encode(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { String content; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStore.java index 0aa82e3c3..9e62294b5 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStore.java @@ -24,6 +24,7 @@ import org.springframework.security.oauth2.common.DefaultOAuth2RefreshToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2RefreshToken; +import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.approval.Approval; import org.springframework.security.oauth2.provider.approval.Approval.ApprovalStatus; @@ -80,6 +81,14 @@ public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authe @Override public OAuth2AccessToken readAccessToken(String tokenValue) { + OAuth2AccessToken accessToken = convertAccessToken(tokenValue); + if (jwtTokenEnhancer.isRefreshToken(accessToken)) { + throw new InvalidTokenException("Encoded token is a refresh token"); + } + return accessToken; + } + + private OAuth2AccessToken convertAccessToken(String tokenValue) { return jwtTokenEnhancer.extractAccessToken(tokenValue, jwtTokenEnhancer.decode(tokenValue)); } @@ -105,7 +114,7 @@ public void storeRefreshToken(OAuth2RefreshToken refreshToken, OAuth2Authenticat @Override public OAuth2RefreshToken readRefreshToken(String tokenValue) { - OAuth2AccessToken encodedRefreshToken = readAccessToken(tokenValue); + OAuth2AccessToken encodedRefreshToken = convertAccessToken(tokenValue); OAuth2RefreshToken refreshToken = createRefreshToken(encodedRefreshToken); if (approvalStore != null) { OAuth2Authentication authentication = readAuthentication(tokenValue); @@ -128,6 +137,9 @@ public OAuth2RefreshToken readRefreshToken(String tokenValue) { } private OAuth2RefreshToken createRefreshToken(OAuth2AccessToken encodedRefreshToken) { + if (!jwtTokenEnhancer.isRefreshToken(encodedRefreshToken)) { + throw new InvalidTokenException("Encoded token is not a refresh token"); + } if (encodedRefreshToken.getExpiration()!=null) { return new DefaultExpiringOAuth2RefreshToken(encodedRefreshToken.getValue(), encodedRefreshToken.getExpiration()); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverterTests.java index 22936b98d..137e10207 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverterTests.java @@ -56,13 +56,13 @@ public void testEnhanceAccessToken() { assertEquals("FOO", token.getAdditionalInformation().get(AccessTokenConverter.JTI)); String claims = JwtHelper.decode(token.getValue()).getClaims(); assertTrue("Wrong claims: " + claims, claims.contains("\"" + AccessTokenConverter.JTI + "\"")); - assertTrue("Wrong claims: " + claims, claims.contains("\"" + UserAuthenticationConverter.USERNAME + "\"")); + assertTrue("Wrong claims: " + claims, claims.contains("\"" + UserAuthenticationConverter.USERNAME + "\"")); } @Test public void testScopePreserved() { - OAuth2Authentication authentication = new OAuth2Authentication(createOAuth2Request("foo", Collections.singleton("read")), - userAuthentication); + OAuth2Authentication authentication = new OAuth2Authentication(createOAuth2Request("foo", + Collections.singleton("read")), userAuthentication); DefaultOAuth2AccessToken original = new DefaultOAuth2AccessToken("FOO"); original.setScope(authentication.getOAuth2Request().getScope()); OAuth2AccessToken token = tokenEnhancer.enhance(original, authentication); @@ -71,9 +71,9 @@ public void testScopePreserved() { } @Test - public void testRefreshTokenAdded() { - OAuth2Authentication authentication = new OAuth2Authentication(createOAuth2Request("foo", Collections.singleton("read")), - userAuthentication); + public void testRefreshTokenAdded() throws Exception { + OAuth2Authentication authentication = new OAuth2Authentication(createOAuth2Request("foo", + Collections.singleton("read")), userAuthentication); DefaultOAuth2AccessToken original = new DefaultOAuth2AccessToken("FOO"); original.setScope(authentication.getOAuth2Request().getScope()); original.setRefreshToken(new DefaultOAuth2RefreshToken("BAR")); @@ -82,6 +82,9 @@ public void testRefreshTokenAdded() { assertNotNull(token.getRefreshToken()); String claims = JwtHelper.decode(token.getRefreshToken().getValue()).getClaims(); assertTrue("Wrong claims: " + claims, claims.contains("\"" + AccessTokenConverter.SCOPE + "\"")); + tokenEnhancer.afterPropertiesSet(); + assertTrue(tokenEnhancer.isRefreshToken(tokenEnhancer.extractAccessToken(token.getRefreshToken().getValue(), + tokenEnhancer.decode(token.getRefreshToken().getValue())))); } @Test @@ -129,8 +132,7 @@ public void publicKeyStringIsReturnedFromTokenKeyEndpointWithNullPrincipal() thr @Test public void sharedSecretIsReturnedFromTokenKeyEndpoint() throws Exception { tokenEnhancer.setVerifierKey("someKey"); - assertEquals("{alg=HMACSHA256, value=someKey}", - tokenEnhancer.getKey().toString()); + assertEquals("{alg=HMACSHA256, value=someKey}", tokenEnhancer.getKey().toString()); } @Test(expected = IllegalStateException.class) @@ -139,10 +141,11 @@ public void keysNotMatchingWithMacSigner() throws Exception { tokenEnhancer.setVerifierKey("someKey"); tokenEnhancer.afterPropertiesSet(); } - + @Test public void rsaKeyPair() throws Exception { - KeyStoreKeyFactory factory = new KeyStoreKeyFactory(new ClassPathResource("keystore.jks"), "foobar".toCharArray()); + KeyStoreKeyFactory factory = new KeyStoreKeyFactory(new ClassPathResource("keystore.jks"), + "foobar".toCharArray()); KeyPair keys = factory.getKeyPair("test"); tokenEnhancer.setKeyPair(keys); tokenEnhancer.afterPropertiesSet(); @@ -156,7 +159,8 @@ public void publicKeyOnlyAllowedForVerification() throws Exception { + "kmd6wbrRAMPMpoC1eogWNNoXY7Jd4eWdDVmscfHczGX13uBKXwdOCEqKqoWQsXIb\n" + "7kgz+HkCAwEAAQ==\n" + "-----END RSA PUBLIC KEY-----"); tokenEnhancer.afterPropertiesSet(); - tokenEnhancer.decode("eyJhbGciOiJSUzI1NiJ9.eyJ1c2VyX25hbWUiOiJ0ZXN0MiIsImp0aSI6IkZPTyIsImNsaWVudF9pZCI6ImZvbyJ9.b43ob1ALSIwr_J2oEnfMhsXvYkr1qVBNhigNH2zlaE1OQLhLfT-DMlFtHcyUlyap0C2n0q61SPaGE_z715TV0uTAv2YKDN4fKZz2bMR7eHLsvaaCuvs7KCOi_aSROaUG"); + tokenEnhancer + .decode("eyJhbGciOiJSUzI1NiJ9.eyJ1c2VyX25hbWUiOiJ0ZXN0MiIsImp0aSI6IkZPTyIsImNsaWVudF9pZCI6ImZvbyJ9.b43ob1ALSIwr_J2oEnfMhsXvYkr1qVBNhigNH2zlaE1OQLhLfT-DMlFtHcyUlyap0C2n0q61SPaGE_z715TV0uTAv2YKDN4fKZz2bMR7eHLsvaaCuvs7KCOi_aSROaUG"); Map key = tokenEnhancer.getKey(); assertTrue("Wrong key: " + key, key.get("value").contains("-----BEGIN")); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStoreTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStoreTests.java index d431b8f16..e8b6b030b 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStoreTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStoreTests.java @@ -2,24 +2,31 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.util.Collections; import java.util.Date; +import java.util.HashMap; +import java.util.Map; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.oauth2.common.DefaultExpiringOAuth2RefreshToken; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.DefaultOAuth2RefreshToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.RequestTokenFactory; import org.springframework.security.oauth2.provider.approval.Approval; import org.springframework.security.oauth2.provider.approval.Approval.ApprovalStatus; import org.springframework.security.oauth2.provider.approval.InMemoryApprovalStore; +import org.springframework.security.oauth2.provider.token.AccessTokenConverter; /** * @author Dave Syer @@ -27,6 +34,9 @@ */ public class JwtTokenStoreTests { + @Rule + public ExpectedException expected = ExpectedException.none(); + private JwtAccessTokenConverter enhancer = new JwtAccessTokenConverter(); private JwtTokenStore tokenStore = new JwtTokenStore(enhancer); @@ -41,12 +51,22 @@ public class JwtTokenStoreTests { private OAuth2AccessToken expectedOAuth2AccessToken; + private OAuth2AccessToken expectedOAuth2RefreshToken; + @Before public void init() throws Exception { enhancer.afterPropertiesSet(); DefaultOAuth2AccessToken original = new DefaultOAuth2AccessToken("testToken"); original.setScope(expectedAuthentication.getOAuth2Request().getScope()); expectedOAuth2AccessToken = enhancer.enhance(original, expectedAuthentication); + convertToRefreshToken(original); + expectedOAuth2RefreshToken = enhancer.enhance(original, expectedAuthentication); + } + + protected void convertToRefreshToken(DefaultOAuth2AccessToken original) { + Map map = new HashMap(original.getAdditionalInformation()); + map.put(AccessTokenConverter.ATI, "FOO"); + original.setAdditionalInformation(map); } @Test @@ -60,28 +80,54 @@ public void testReadAccessToken() throws Exception { assertEquals(expectedOAuth2AccessToken, tokenStore.readAccessToken(expectedOAuth2AccessToken.getValue())); } + @Test(expected = InvalidTokenException.class) + public void testNonAccessTokenNotReadable() throws Exception { + assertNull(tokenStore.readAccessToken("FOO")); + } + + @Test(expected = InvalidTokenException.class) + public void testNonRefreshTokenNotReadable() throws Exception { + assertNull(tokenStore.readRefreshToken("FOO")); + } + + @Test + public void testAccessTokenIsNotARefreshToken() throws Exception { + DefaultOAuth2AccessToken original = new DefaultOAuth2AccessToken("FOO"); + original.setExpiration(new Date()); + DefaultOAuth2AccessToken token = (DefaultOAuth2AccessToken) enhancer.enhance(original, expectedAuthentication); + expected.expect(InvalidTokenException.class); + assertNull(tokenStore.readRefreshToken(token.getValue())); + } + + @Test + public void testRefreshTokenIsNotAnAccessToken() throws Exception { + expected.expect(InvalidTokenException.class); + assertNull(tokenStore.readAccessToken(expectedOAuth2RefreshToken.getValue())); + } + @Test public void testReadAccessTokenWithLongExpiration() throws Exception { DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(expectedOAuth2AccessToken); - token.setExpiration(new Date(Long.MAX_VALUE-1)); + token.setExpiration(new Date(Long.MAX_VALUE - 1)); expectedOAuth2AccessToken = enhancer.enhance(token, expectedAuthentication); assertEquals(expectedOAuth2AccessToken, tokenStore.readAccessToken(expectedOAuth2AccessToken.getValue())); } @Test public void testReadRefreshToken() throws Exception { - assertEquals(expectedOAuth2AccessToken, tokenStore.readRefreshToken(expectedOAuth2AccessToken.getValue())); + assertEquals(expectedOAuth2RefreshToken, tokenStore.readRefreshToken(expectedOAuth2RefreshToken.getValue())); } @Test public void testReadNonExpiringRefreshToken() throws Exception { - assertFalse(tokenStore.readRefreshToken(expectedOAuth2AccessToken.getValue()) instanceof DefaultExpiringOAuth2RefreshToken); + assertFalse(tokenStore.readRefreshToken(expectedOAuth2RefreshToken.getValue()) instanceof DefaultExpiringOAuth2RefreshToken); } @Test public void testReadExpiringRefreshToken() throws Exception { DefaultOAuth2AccessToken original = new DefaultOAuth2AccessToken("FOO"); original.setExpiration(new Date()); + convertToRefreshToken(original); DefaultOAuth2AccessToken token = (DefaultOAuth2AccessToken) enhancer.enhance(original, expectedAuthentication); assertTrue(tokenStore.readRefreshToken(token.getValue()) instanceof DefaultExpiringOAuth2RefreshToken); } @@ -107,7 +153,8 @@ public void testReadAuthenticationForRefreshToken() throws Exception { @Test public void removeAccessToken() throws Exception { tokenStore.setApprovalStore(approvalStore); - approvalStore.addApprovals(Collections.singleton(new Approval("test", "id", "read", new Date(), ApprovalStatus.APPROVED))); + approvalStore.addApprovals(Collections.singleton(new Approval("test", "id", "read", new Date(), + ApprovalStatus.APPROVED))); assertEquals(1, approvalStore.getApprovals("test", "id").size()); tokenStore.removeAccessToken(expectedOAuth2AccessToken); assertEquals(0, approvalStore.getApprovals("test", "id").size()); @@ -116,7 +163,8 @@ public void removeAccessToken() throws Exception { @Test public void removeRefreshToken() throws Exception { tokenStore.setApprovalStore(approvalStore); - approvalStore.addApprovals(Collections.singleton(new Approval("test", "id", "read", new Date(), ApprovalStatus.APPROVED))); + approvalStore.addApprovals(Collections.singleton(new Approval("test", "id", "read", new Date(), + ApprovalStatus.APPROVED))); assertEquals(1, approvalStore.getApprovals("test", "id").size()); tokenStore.removeRefreshToken(new DefaultOAuth2RefreshToken(expectedOAuth2AccessToken.getValue())); assertEquals(0, approvalStore.getApprovals("test", "id").size()); @@ -125,18 +173,21 @@ public void removeRefreshToken() throws Exception { @Test public void removeAccessTokenFromRefreshToken() throws Exception { tokenStore.setApprovalStore(approvalStore); - approvalStore.addApprovals(Collections.singleton(new Approval("test", "id", "read", new Date(), ApprovalStatus.APPROVED))); + approvalStore.addApprovals(Collections.singleton(new Approval("test", "id", "read", new Date(), + ApprovalStatus.APPROVED))); assertEquals(1, approvalStore.getApprovals("test", "id").size()); - tokenStore.removeAccessTokenUsingRefreshToken(new DefaultOAuth2RefreshToken(expectedOAuth2AccessToken.getValue())); + tokenStore.removeAccessTokenUsingRefreshToken(new DefaultOAuth2RefreshToken(expectedOAuth2AccessToken + .getValue())); assertEquals(0, approvalStore.getApprovals("test", "id").size()); } @Test public void testReadRefreshTokenForUnapprovedScope() throws Exception { tokenStore.setApprovalStore(approvalStore); - approvalStore.addApprovals(Collections.singleton(new Approval("test", "id", "write", new Date(), ApprovalStatus.APPROVED))); + approvalStore.addApprovals(Collections.singleton(new Approval("test", "id", "write", new Date(), + ApprovalStatus.APPROVED))); assertEquals(1, approvalStore.getApprovals("test", "id").size()); - assertEquals(null, tokenStore.readRefreshToken(expectedOAuth2AccessToken.getValue())); + assertEquals(null, tokenStore.readRefreshToken(expectedOAuth2RefreshToken.getValue())); } private void checkAuthentications(OAuth2Authentication expected, OAuth2Authentication actual) { From 684387b488247337a80ea700a67c2fa591a348a8 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 27 Jan 2015 16:08:53 +0000 Subject: [PATCH 367/831] Rationalize redirect rendering in AuthorizationEndpoint There are 3 methods in AuthorizationEndpoint that need to build a redirect URI, and up to now there were 3 different methods of doing it. This change unifies them into a single convenience method. It also allows the incoming redirect URI to be either encoded or unencoded (fixes gh-349). An unencoded URI can easily be provided as part of a ClientDetails registration, and an encoded one would come in as a request parameter. (Actually request parameters can be unencoded too, but most clients will encode to avoid ambiguity.) --- .../endpoint/AuthorizationEndpoint.java | 102 ++++++++++++------ .../endpoint/AuthorizationEndpointTests.java | 35 +++++- 2 files changed, 104 insertions(+), 33 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java index 5abf42ea8..0dfb70d7b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java @@ -13,6 +13,7 @@ package org.springframework.security.oauth2.provider.endpoint; +import java.net.URI; import java.security.Principal; import java.util.Collections; import java.util.Date; @@ -65,7 +66,6 @@ import org.springframework.web.servlet.View; import org.springframework.web.servlet.view.RedirectView; import org.springframework.web.util.UriComponentsBuilder; -import org.springframework.web.util.UriTemplate; /** *

    @@ -269,7 +269,8 @@ private OAuth2AccessToken getAccessTokenForImplicitGrant(TokenRequest tokenReque // These 1 method calls have to be atomic, otherwise the ImplicitGrantService can have a race condition where // one thread removes the token request before another has a chance to redeem it. synchronized (this.implicitLock) { - accessToken = getTokenGranter().grant("implicit", new ImplicitTokenRequest(tokenRequest, storedOAuth2Request)); + accessToken = getTokenGranter().grant("implicit", + new ImplicitTokenRequest(tokenRequest, storedOAuth2Request)); } return accessToken; } @@ -287,51 +288,38 @@ private View getAuthorizationCodeResponse(AuthorizationRequest authorizationRequ private String appendAccessToken(AuthorizationRequest authorizationRequest, OAuth2AccessToken accessToken) { Map vars = new HashMap(); + Map keys = new HashMap(); - String requestedRedirect = authorizationRequest.getRedirectUri(); if (accessToken == null) { throw new InvalidRequestException("An implicit grant could not be made"); } - StringBuilder url = new StringBuilder(requestedRedirect); - if (requestedRedirect.contains("#")) { - url.append("&"); - } - else { - url.append("#"); - } - url.append("access_token={access_token}"); - url.append("&token_type={token_type}"); vars.put("access_token", accessToken.getValue()); vars.put("token_type", accessToken.getTokenType()); String state = authorizationRequest.getState(); if (state != null) { - url.append("&state={state}"); vars.put("state", state); } Date expiration = accessToken.getExpiration(); if (expiration != null) { long expires_in = (expiration.getTime() - System.currentTimeMillis()) / 1000; - url.append("&expires_in={expires_in}"); vars.put("expires_in", expires_in); } String originalScope = authorizationRequest.getRequestParameters().get(OAuth2Utils.SCOPE); if (originalScope == null || !OAuth2Utils.parseParameterList(originalScope).equals(accessToken.getScope())) { - url.append("&" + OAuth2Utils.SCOPE + "={scope}"); vars.put("scope", OAuth2Utils.formatParameterList(accessToken.getScope())); } Map additionalInformation = accessToken.getAdditionalInformation(); for (String key : additionalInformation.keySet()) { Object value = additionalInformation.get(key); if (value != null) { - url.append("&" + key + "={extra_" + key + "}"); + keys.put("extra_" + key, key); vars.put("extra_" + key, value); } } - UriTemplate template = new UriTemplate(url.toString()); // Do not include the refresh token (even if there is one) - return template.expand(vars).toString(); + return append(authorizationRequest.getRedirectUri(), vars, keys, true); } private String generateCode(AuthorizationRequest authorizationRequest, Authentication authentication) @@ -364,15 +352,15 @@ private String getSuccessfulRedirect(AuthorizationRequest authorizationRequest, throw new IllegalStateException("No authorization code found in the current request scope."); } - UriComponentsBuilder template = UriComponentsBuilder.fromUriString(authorizationRequest.getRedirectUri()); - template.queryParam("code", authorizationCode); + Map query = new LinkedHashMap(); + query.put("code", authorizationCode); String state = authorizationRequest.getState(); if (state != null) { - template.queryParam("state", state); + query.put("state", state); } - return template.build().encode().toUriString(); + return append(authorizationRequest.getRedirectUri(), query, false); } private String getUnsuccessfulRedirect(AuthorizationRequest authorizationRequest, OAuth2Exception failure, @@ -383,33 +371,82 @@ private String getUnsuccessfulRedirect(AuthorizationRequest authorizationRequest throw new UnapprovedClientAuthenticationException("Authorization failure, and no redirect URI.", failure); } - UriComponentsBuilder template = UriComponentsBuilder.fromUriString(authorizationRequest.getRedirectUri()); Map query = new LinkedHashMap(); - StringBuilder values = new StringBuilder(); - values.append("error={error}"); query.put("error", failure.getOAuth2ErrorCode()); - - values.append("&error_description={error_description}"); query.put("error_description", failure.getMessage()); if (authorizationRequest.getState() != null) { - values.append("&state={state}"); query.put("state", authorizationRequest.getState()); } if (failure.getAdditionalInformation() != null) { for (Map.Entry additionalInfo : failure.getAdditionalInformation().entrySet()) { - values.append("&" + additionalInfo.getKey() + "={" + additionalInfo.getKey() + "}"); query.put(additionalInfo.getKey(), additionalInfo.getValue()); } } + return append(authorizationRequest.getRedirectUri(), query, fragment); + + } + + private String append(String base, Map query, boolean fragment) { + return append(base, query, null, fragment); + } + + private String append(String base, Map query, Map keys, boolean fragment) { + + UriComponentsBuilder template = UriComponentsBuilder.newInstance(); + UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(base); + URI redirectUri; + try { + // assume it's encoded to start with (if it came in over the wire) + redirectUri = builder.build(true).toUri(); + } + catch (Exception e) { + // ... but allow client registrations to contain hard-coded non-encoded values + redirectUri = builder.build().toUri(); + } + template.scheme(redirectUri.getScheme()).port(redirectUri.getPort()).host(redirectUri.getHost()) + .userInfo(redirectUri.getUserInfo()).path(redirectUri.getPath()); + + StringBuilder values = new StringBuilder(); + for (String key : query.keySet()) { + if (values.length() > 0) { + values.append("&"); + } + String name = key; + if (keys != null && keys.containsKey(key)) { + name = keys.get(key); + } + values.append(name + "={" + key + "}"); + } + if (fragment) { - template.fragment(values.toString()); + if (redirectUri.getFragment() != null) { + String append = redirectUri.getFragment(); + if (values.length() > 0) { + append = append + "&"; + } + values.insert(0, append); + } + if (values.length() > 0) { + template.fragment(values.toString()); + } + template.query(redirectUri.getQuery()); } else { - template.query(values.toString()); + if (redirectUri.getQuery() != null) { + String append = redirectUri.getQuery(); + if (values.length() > 0) { + append = append + "&"; + } + values.insert(0, append); + } + if (values.length() > 0) { + template.query(values.toString()); + } + template.fragment(redirectUri.getFragment()); } return template.build().expand(query).encode().toUriString(); @@ -437,7 +474,8 @@ public void setOAuth2RequestValidator(OAuth2RequestValidator oauth2RequestValida } @SuppressWarnings("deprecation") - public void setImplicitGrantService(org.springframework.security.oauth2.provider.implicit.ImplicitGrantService implicitGrantService) { + public void setImplicitGrantService( + org.springframework.security.oauth2.provider.implicit.ImplicitGrantService implicitGrantService) { } @ExceptionHandler(ClientRegistrationException.class) diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java index 12fcd1e03..ff065ebd5 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java @@ -120,7 +120,6 @@ public void testMandatoryProperties() throws Exception { @Test public void testStartAuthorizationCodeFlow() throws Exception { - ModelAndView result = endpoint.authorize(model, getAuthorizationRequest("foo", null, null, "read", Collections.singleton("code")) .getRequestParameters(), sessionStatus, principal); @@ -203,6 +202,18 @@ public void testAuthorizationCodeWithTrickyQueryParams() throws Exception { assertEquals("http://anywhere.com/?foo=b%20%3D&bar=f%20http://anywhere.com?foo=b%20%3D&bar=f%20$&code=thecodecode=thecode", ((RedirectView) result).getUrl()); } + @Test + public void testAuthorizationCodeWithTrickyEncodedQueryParams() throws Exception { + endpoint.setAuthorizationCodeServices(new StubAuthorizationCodeServices()); + model.put( + "authorizationRequest", + getAuthorizationRequest("foo", "http://anywhere.com/path?foo=b%20%3D&bar=f%20$", null, null, + Collections.singleton("code"))); + View result = endpoint.approveOrDeny(Collections.singletonMap(OAuth2Utils.USER_OAUTH_APPROVAL, "true"), model, + sessionStatus, principal); + assertEquals("http://anywhere.com/path?foo=b%20%3D&bar=f%20http://anywhere.com/path?foo=b%20%3D&bar=f%20$&code=thecodecode=thecode", ((RedirectView) result).getUrl()); + } + @Test public void testAuthorizationCodeError() throws Exception { endpoint.setUserApprovalHandler(new DefaultUserApprovalHandler() { @@ -338,6 +349,28 @@ public boolean isApproved(AuthorizationRequest authorizationRequest, Authenticat assertTrue("Wrong url: " + result, url.contains("foo=bar")); } + @Test + public void testImplicitWithAdditionalInfo() throws Exception { + endpoint.setTokenGranter(new TokenGranter() { + public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) { + DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken("FOO"); + token.setAdditionalInformation(Collections. singletonMap("foo", "bar")); + return token; + } + }); + endpoint.setUserApprovalHandler(new DefaultUserApprovalHandler() { + public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { + return true; + } + }); + AuthorizationRequest authorizationRequest = getAuthorizationRequest("foo", "http://anywhere.com/", + "mystate", "myscope", Collections.singleton("token")); + ModelAndView result = endpoint.authorize(model, authorizationRequest.getRequestParameters(), sessionStatus, + principal); + String url = ((RedirectView) result.getView()).getUrl(); + assertTrue("Wrong url: " + result, url.contains("foo=bar")); + } + @Test public void testImplicitAppendsScopeWhenDefaulting() throws Exception { endpoint.setTokenGranter(new TokenGranter() { From 2ceebcdd3a2006e2bd926ad20edd1b20695b5a55 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 27 Jan 2015 16:24:07 +0000 Subject: [PATCH 368/831] Fix test (fails on command line not IDE) --- .../oauth2/provider/endpoint/AuthorizationEndpointTests.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java index ff065ebd5..ea59b32e7 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java @@ -325,7 +325,7 @@ public boolean isApproved(AuthorizationRequest authorizationRequest, Authenticat ModelAndView result = endpoint.authorize(model, authorizationRequest.getRequestParameters(), sessionStatus, principal); String url = ((RedirectView) result.getView()).getUrl(); - assertTrue("Wrong scope: " + result, url.contains("&scope=read")); + assertTrue("Wrong scope: " + result, url.contains("scope=read")); } @Test @@ -401,7 +401,7 @@ public AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizati ModelAndView result = endpoint.authorize(model, authorizationRequest.getRequestParameters(), sessionStatus, principal); String url = ((RedirectView) result.getView()).getUrl(); - assertTrue("Wrong scope: " + result, url.contains("&scope=read%20write")); + assertTrue("Wrong scope: " + result, url.contains("scope=read%20write")); } @Test(expected = InvalidScopeException.class) From 3c089c5960ce4c5646c2c335ce0c16c1eb86459f Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 27 Jan 2015 16:31:59 +0000 Subject: [PATCH 369/831] Make sure fragment params are ordered in implicit response --- .../oauth2/provider/endpoint/AuthorizationEndpoint.java | 2 +- .../oauth2/provider/endpoint/AuthorizationEndpointTests.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java index 0dfb70d7b..1d88ba5fe 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java @@ -287,7 +287,7 @@ private View getAuthorizationCodeResponse(AuthorizationRequest authorizationRequ private String appendAccessToken(AuthorizationRequest authorizationRequest, OAuth2AccessToken accessToken) { - Map vars = new HashMap(); + Map vars = new LinkedHashMap(); Map keys = new HashMap(); if (accessToken == null) { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java index ea59b32e7..ff065ebd5 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java @@ -325,7 +325,7 @@ public boolean isApproved(AuthorizationRequest authorizationRequest, Authenticat ModelAndView result = endpoint.authorize(model, authorizationRequest.getRequestParameters(), sessionStatus, principal); String url = ((RedirectView) result.getView()).getUrl(); - assertTrue("Wrong scope: " + result, url.contains("scope=read")); + assertTrue("Wrong scope: " + result, url.contains("&scope=read")); } @Test @@ -401,7 +401,7 @@ public AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizati ModelAndView result = endpoint.authorize(model, authorizationRequest.getRequestParameters(), sessionStatus, principal); String url = ((RedirectView) result.getView()).getUrl(); - assertTrue("Wrong scope: " + result, url.contains("scope=read%20write")); + assertTrue("Wrong scope: " + result, url.contains("&scope=read%20write")); } @Test(expected = InvalidScopeException.class) From f764279dfb785d382e97ee7d6f239de76f3383b8 Mon Sep 17 00:00:00 2001 From: John Kim Date: Mon, 26 Jan 2015 15:25:54 +0900 Subject: [PATCH 370/831] Modify minor misspellings and link Fixes gh-374 --- docs/oauth2.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/oauth2.md b/docs/oauth2.md index 172e3093a..a97d830d2 100644 --- a/docs/oauth2.md +++ b/docs/oauth2.md @@ -46,7 +46,7 @@ In XML there is an `` element that is used in a similar w ### Configuring Client Details -The `ClientDetailsServiceConfigurer` (a callback from your `AuthorizationServerConfigurer`) can be used used to define an in-memory or JDBC implementation of the client details service. Important attributes of a client are +The `ClientDetailsServiceConfigurer` (a callback from your `AuthorizationServerConfigurer`) can be used to define an in-memory or JDBC implementation of the client details service. Important attributes of a client are * `clientId`: (required) the client id. * `secret`: (required for trusted clients) the client secret, if any. @@ -63,13 +63,13 @@ The [`AuthorizationServerTokenServices`][AuthorizationServerTokenServices] inter * When an access token is created, the authentication must be stored so that resources accepting the access token can reference it later. * The access token is used to load the authentication that was used to authorize its creation. -When creating your `AuthorizationServerTokenServices` implementation, you may want to consider using the [`DefaultTokenServices`][DefaultTokenServices] which has many strategies that can be plugged in to change the format ans storage of access tokens. By default it creates tokens via random value and handles everything except for the persistence of the tokens which it delegates to a `TokenStore`. The default store is an [in-memory implementation][InMemoryTokenStore], but there are some other implementations available. Here's a description with some discussion of each of them +When creating your `AuthorizationServerTokenServices` implementation, you may want to consider using the [`DefaultTokenServices`][DefaultTokenServices] which has many strategies that can be plugged in to change the format and storage of access tokens. By default it creates tokens via random value and handles everything except for the persistence of the tokens which it delegates to a `TokenStore`. The default store is an [in-memory implementation][InMemoryTokenStore], but there are some other implementations available. Here's a description with some discussion of each of them * The default `InMemoryTokenStore` is perfectly fine for a single server (i.e. low traffic and no hot swap to a backup server in the case of failure). Most projects can start here, and maybe operate this way in development mode, to make it easy to start a server with no dependencies. * The `JdbcTokenStore` is the [JDBC version](JdbcTokenStore) of the same thing, which stores token data in a relational database. Use the JDBC version if you can share a database between servers, either scaled up instances of the same server if there is only one, or the Authorization and Resources Servers if there are multiple components. To use the `JdbcTokenStore` you need "spring-jdbc" on the classpath. -* The [JSON Web Token (JWT) version](`JwtTokenStore`) of the store encodes all the data about the grant into the token itself (so no back end store at all which is a significant advantage). One disadvantage is that you can't easily revoke an access token, so they normally are granted with short expiry and the revocation is handled at the refresh token. Another disadvantage is that the tokens can get quite large if you are storing a lot of user credential information in them. The `JwtTokenStore` is not really a "store" in the sense that it doesn't persist any data, but it plays the same role of translating betweeen token values and authentication information in the `DefaultTokenServices`. +* The [JSON Web Token (JWT) version](`JwtTokenStore`) of the store encodes all the data about the grant into the token itself (so no back end store at all which is a significant advantage). One disadvantage is that you can't easily revoke an access token, so they normally are granted with short expiry and the revocation is handled at the refresh token. Another disadvantage is that the tokens can get quite large if you are storing a lot of user credential information in them. The `JwtTokenStore` is not really a "store" in the sense that it doesn't persist any data, but it plays the same role of translating betweeen token values and authentication information in the `DefaultTokenServices`. ### JWT Tokens @@ -96,7 +96,7 @@ In XML grant types are included as child elements of the `authorization-server`. The `AuthorizationServerEndpointsConfigurer` has a `pathMapping()` method. It takes two arguments: * The default (framework implementation) URL path for the endpoint -* The custom path required (starting with a "/") +* The custom path required (starting with a "/") The URL paths provided by the framework are `/oauth/authorize` (the authorization endpoint), `/oauth/token` (the token endpoint), `/oauth/confirm_access` (user posts approval for grants here), `/oauth/error` (used to render errors in the authorization server), `/oauth/check_token` (used by Resource Servers to decode access tokens), and `/oauth/token_key` (exposes public key for token verification if using JWT tokens). @@ -191,7 +191,7 @@ state related to individual users from colliding. The filter has to be wired into the application (e.g. using a Servlet initializer or `web.xml` configuration for a `DelegatingFilterProxy` -with the same name). +with the same name). The `AccessTokenRequest` can be used in an `OAuth2RestTemplate` like this: @@ -257,8 +257,8 @@ Facebook token responses also contain a non-compliant JSON entry for the expiry [AuthorizationServerTokenServices]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/token/AuthorizationServerTokenServices.html "AuthorizationServerTokenServices" [OAuth2AuthenticationProcessingFilter]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/filter/OAuth2AuthenticationProcessingFilter.html "OAuth2AuthenticationProcessingFilter" [oauth2.xsd]: http://www.springframework.org/schema/security/spring-security-oauth2.xsd "oauth2.xsd" - [expressions]: http://static.springsource.org/spring-security/site/docs/3.2.x/reference/el-access.html "Expression Access Control" - + [expressions]: http://docs.spring.io/spring-security/site/docs/3.2.5.RELEASE/reference/htmlsingle/#el-access "Expression Access Control" + [AccessTokenProviderChain]: /spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/AccessTokenProviderChain.java [OAuth2RestTemplate]: /spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/OAuth2RestTemplate.java [OAuth2ProtectedResourceDetails]: /spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/resource/OAuth2ProtectedResourceDetails.java From 4f066601b04445dc630480e73bfb265767a635dd Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 27 Jan 2015 16:50:09 +0000 Subject: [PATCH 371/831] Make OAuth2ExpressionParser public so it can be instantiated Fixes gh-362 --- .../oauth2/provider/expression/OAuth2ExpressionParser.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionParser.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionParser.java index 571d8c013..861411969 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionParser.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionParser.java @@ -35,7 +35,8 @@ * @author Rob Winch * */ -final class OAuth2ExpressionParser implements ExpressionParser { +public class OAuth2ExpressionParser implements ExpressionParser { + private final ExpressionParser delegate; public OAuth2ExpressionParser(ExpressionParser delegate) { From 04f7b1a39ef985d6c1163bd449032f859e1493e4 Mon Sep 17 00:00:00 2001 From: Chris Campo Date: Thu, 11 Dec 2014 12:22:37 -0500 Subject: [PATCH 372/831] Restricted token endpoint to HTTP POST by default. --- .../security/oauth2/provider/endpoint/TokenEndpoint.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java index a35ff09e2..0122484bd 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java @@ -42,6 +42,7 @@ import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; /** @@ -66,7 +67,7 @@ public class TokenEndpoint extends AbstractEndpoint { private OAuth2RequestValidator oAuth2RequestValidator = new DefaultOAuth2RequestValidator(); - @RequestMapping(value = "/oauth/token") + @RequestMapping(value = "/oauth/token", method = RequestMethod.POST) public ResponseEntity getAccessToken(Principal principal, @RequestParam Map parameters) { From 6dfee4424501744e19081277c7cc488821ca00e6 Mon Sep 17 00:00:00 2001 From: Chris Campo Date: Tue, 16 Dec 2014 17:31:18 -0500 Subject: [PATCH 373/831] Added ability to restrict token endpoint HTTP request methods ... using the AuthorizationServerEndpointsConfigurer class. Fixes gh-334, fixes gh-327 --- ...orizationServerEndpointsConfiguration.java | 7 ++ ...uthorizationServerEndpointsConfigurer.java | 25 +++++-- .../provider/endpoint/TokenEndpoint.java | 19 +++-- ...AuthorizationServerConfigurationTests.java | 69 ++++++++++++++++++- .../provider/endpoint/TokenEndpointTests.java | 50 +++++++++++--- 5 files changed, 150 insertions(+), 20 deletions(-) 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 b7d8d4d77..163edd923 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 @@ -15,6 +15,7 @@ import java.util.Collections; import java.util.List; +import java.util.Set; import javax.annotation.PostConstruct; @@ -28,6 +29,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import org.springframework.http.HttpMethod; import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerEndpointsConfiguration.TokenKeyEndpointRegistrar; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; import org.springframework.security.oauth2.provider.ClientDetailsService; @@ -101,6 +103,7 @@ public TokenEndpoint tokenEndpoint() throws Exception { tokenEndpoint.setTokenGranter(tokenGranter()); tokenEndpoint.setOAuth2RequestFactory(oauth2RequestFactory()); tokenEndpoint.setOAuth2RequestValidator(oauth2RequestValidator()); + tokenEndpoint.setAllowedRequestMethods(allowedTokenEndpointRequestMethods()); return tokenEndpoint; } @@ -151,6 +154,10 @@ public AuthorizationServerEndpointsConfigurer getEndpointsConfigurer() { return endpoints; } + private Set allowedTokenEndpointRequestMethods() { + return getEndpointsConfigurer().getAllowedTokenEndpointRequestMethods(); + } + private OAuth2RequestFactory oauth2RequestFactory() throws Exception { return getEndpointsConfigurer().getOAuth2RequestFactory(); } 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 f9df9a6cd..3f92e9388 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,11 +15,9 @@ */ package org.springframework.security.oauth2.config.annotation.web.configurers; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; +import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; @@ -101,6 +99,8 @@ public final class AuthorizationServerEndpointsConfigurer { private Map patternMap = new HashMap(); + private Set allowedTokenEndpointRequestMethods = new HashSet(); + private FrameworkEndpointHandlerMapping frameworkEndpointHandlerMapping; private boolean approvalStoreDisabled; @@ -264,6 +264,11 @@ public AuthorizationServerEndpointsConfigurer authorizationCodeServices( return this; } + public AuthorizationServerEndpointsConfigurer allowedTokenEndpointRequestMethods(HttpMethod... requestMethods) { + Collections.addAll(allowedTokenEndpointRequestMethods, requestMethods); + return this; + } + public ConsumerTokenServices getConsumerTokenServices() { return consumerTokenServices(); } @@ -276,6 +281,10 @@ public AuthorizationCodeServices getAuthorizationCodeServices() { return authorizationCodeServices(); } + public Set getAllowedTokenEndpointRequestMethods() { + return allowedTokenEndpointRequestMethods(); + } + public OAuth2RequestValidator getRequestValidator() { return requestValidator(); } @@ -302,6 +311,14 @@ private ResourceServerTokenServices resourceTokenServices() { return resourceTokenServices; } + private Set allowedTokenEndpointRequestMethods() { + // HTTP POST should be the only allowed endpoint request method by default. + if (allowedTokenEndpointRequestMethods.isEmpty()) { + allowedTokenEndpointRequestMethods.add(HttpMethod.POST); + } + return allowedTokenEndpointRequestMethods; + } + private ConsumerTokenServices consumerTokenServices() { if (consumerTokenServices == null) { if (tokenServices instanceof ConsumerTokenServices) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java index 0122484bd..9d15b6f10 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java @@ -17,10 +17,10 @@ package org.springframework.security.oauth2.provider.endpoint; import java.security.Principal; -import java.util.Collections; -import java.util.Map; +import java.util.*; import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.authentication.InsufficientAuthenticationException; @@ -40,9 +40,9 @@ import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestValidator; import org.springframework.util.StringUtils; +import org.springframework.web.HttpRequestMethodNotSupportedException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; /** @@ -67,9 +67,15 @@ public class TokenEndpoint extends AbstractEndpoint { private OAuth2RequestValidator oAuth2RequestValidator = new DefaultOAuth2RequestValidator(); - @RequestMapping(value = "/oauth/token", method = RequestMethod.POST) + private Set allowedRequestMethods = new HashSet(Arrays.asList(HttpMethod.POST)); + + @RequestMapping(value = "/oauth/token") public ResponseEntity getAccessToken(Principal principal, @RequestParam - Map parameters) { + Map parameters, HttpMethod requestMethod) throws HttpRequestMethodNotSupportedException { + + if (!allowedRequestMethods.contains(requestMethod)) { + throw new HttpRequestMethodNotSupportedException(requestMethod.toString()); + } if (!(principal instanceof Authentication)) { throw new InsufficientAuthenticationException( @@ -176,4 +182,7 @@ public void setOAuth2RequestValidator(OAuth2RequestValidator oAuth2RequestValida this.oAuth2RequestValidator = oAuth2RequestValidator; } + public void setAllowedRequestMethods(Set allowedRequestMethods) { + this.allowedRequestMethods = allowedRequestMethods; + } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java index b0a472106..c193ccae1 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java @@ -20,6 +20,7 @@ import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.Set; import javax.sql.DataSource; @@ -36,6 +37,7 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; import org.springframework.mock.web.MockServletContext; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity; @@ -54,6 +56,7 @@ import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenGranter; import org.springframework.security.oauth2.provider.client.InMemoryClientDetailsService; import org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint; +import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint; import org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; import org.springframework.security.oauth2.provider.token.DefaultTokenServices; @@ -88,14 +91,16 @@ public static List parameters() { new Object[] { null, new Class[] { AuthorizationServerVanilla.class } }, new Object[] { null, new Class[] { AuthorizationServerDisableApproval.class } }, new Object[] { null, new Class[] { AuthorizationServerExtras.class } }, - new Object[] { null, new Class[] { AuthorizationServerJdbc.class } }, + new Object[] { null, new Class[] { AuthorizationServerJdbc.class } }, new Object[] { null, new Class[] { AuthorizationServerEncoder.class } }, new Object[] { null, new Class[] { AuthorizationServerJwt.class } }, new Object[] { null, new Class[] { AuthorizationServerWithTokenServices.class } }, new Object[] { null, new Class[] { AuthorizationServerApproval.class } }, new Object[] { null, new Class[] { AuthorizationServerExceptionTranslator.class } }, new Object[] { null, new Class[] { AuthorizationServerCustomClientDetails.class } }, - new Object[] { BeanCreationException.class, new Class[] { AuthorizationServerTypes.class } } + new Object[] { null, new Class[] { AuthorizationServerAllowsSpecificRequestMethods.class} }, + new Object[] { null, new Class[] { AuthorizationServerAllowsOnlyPost.class} }, + new Object[] { BeanCreationException.class, new Class[] { AuthorizationServerTypes.class } } // @formatter:on ); } @@ -245,6 +250,66 @@ public void run() { } + @Configuration + @EnableWebMvcSecurity + @EnableAuthorizationServer + protected static class AuthorizationServerAllowsSpecificRequestMethods extends + AuthorizationServerConfigurerAdapter implements Runnable { + + @Autowired + private TokenEndpoint endpoint; + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + // @formatter:off + clients.inMemory() + .withClient("my-trusted-client") + .authorizedGrantTypes("password"); + // @formatter:on + } + + @Override + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + endpoints.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.PUT); + } + + @Override + public void run() { + @SuppressWarnings("unchecked") + Set allowedRequestMethods = (Set) ReflectionTestUtils.getField(endpoint, "allowedRequestMethods"); + assertTrue(allowedRequestMethods.contains(HttpMethod.GET)); + assertTrue(allowedRequestMethods.contains(HttpMethod.PUT)); + assertFalse(allowedRequestMethods.contains(HttpMethod.POST)); + } + } + + @Configuration + @EnableWebMvcSecurity + @EnableAuthorizationServer + protected static class AuthorizationServerAllowsOnlyPost extends AuthorizationServerConfigurerAdapter + implements Runnable { + + @Autowired + private TokenEndpoint endpoint; + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + // @formatter:off + clients.inMemory() + .withClient("my-trusted-client") + .authorizedGrantTypes("password"); + // @formatter:on + } + + @Override + public void run() { + @SuppressWarnings("unchecked") + Set allowedRequestMethods = (Set) ReflectionTestUtils.getField(endpoint, "allowedRequestMethods"); + assertFalse(allowedRequestMethods.contains(HttpMethod.GET)); + assertTrue(allowedRequestMethods.contains(HttpMethod.POST)); + } + } + @Configuration @EnableWebMvcSecurity @EnableAuthorizationServer diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointTests.java index f2623a741..bbf0bdc2f 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointTests.java @@ -22,9 +22,7 @@ import static org.mockito.Mockito.when; import java.security.Principal; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; +import java.util.*; import org.junit.Before; import org.junit.Test; @@ -33,6 +31,7 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.runners.MockitoJUnitRunner; +import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; @@ -47,6 +46,7 @@ import org.springframework.security.oauth2.provider.TokenGranter; import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.client.BaseClientDetails; +import org.springframework.web.HttpRequestMethodNotSupportedException; /** * @author Dave Syer @@ -89,7 +89,7 @@ public void init() { } @Test - public void testGetAccessTokenWithNoClientId() { + public void testGetAccessTokenWithNoClientId() throws HttpRequestMethodNotSupportedException { HashMap parameters = new HashMap(); parameters.put(OAuth2Utils.GRANT_TYPE, "authorization_code"); @@ -104,7 +104,8 @@ public void testGetAccessTokenWithNoClientId() { clientAuthentication = new UsernamePasswordAuthenticationToken(null, null, Collections.singleton(new SimpleGrantedAuthority("ROLE_CLIENT"))); - ResponseEntity response = endpoint.getAccessToken(clientAuthentication, parameters); + ResponseEntity response = endpoint.getAccessToken(clientAuthentication, parameters, + HttpMethod.POST); assertNotNull(response); assertEquals(HttpStatus.OK, response.getStatusCode()); @@ -114,7 +115,7 @@ public void testGetAccessTokenWithNoClientId() { } @Test - public void testGetAccessTokenWithScope() { + public void testGetAccessTokenWithScope() throws HttpRequestMethodNotSupportedException { when(clientDetailsService.loadClientByClientId(clientId)).thenReturn(clientDetails); @@ -133,7 +134,8 @@ public void testGetAccessTokenWithScope() { when(authorizationRequestFactory.createTokenRequest(anyMap, Mockito.eq(clientDetails))).thenReturn( createFromParameters(parameters)); - ResponseEntity response = endpoint.getAccessToken(clientAuthentication, parameters); + ResponseEntity response = endpoint.getAccessToken(clientAuthentication, parameters, + HttpMethod.POST); assertNotNull(response); assertEquals(HttpStatus.OK, response.getStatusCode()); @@ -143,8 +145,38 @@ public void testGetAccessTokenWithScope() { assertTrue("Scope of token request not cleared", captor.getValue().getScope().isEmpty()); } + @Test(expected = HttpRequestMethodNotSupportedException.class) + public void testGetAccessTokenWithUnsupportedRequestParameters() throws HttpRequestMethodNotSupportedException { + endpoint.getAccessToken(clientAuthentication, new HashMap(), HttpMethod.GET); + } + + @Test + public void testGetAccessTokenWithSupportedRequestParametersNotPost() throws HttpRequestMethodNotSupportedException { + endpoint.setAllowedRequestMethods(new HashSet(Arrays.asList(HttpMethod.GET))); + HashMap parameters = new HashMap(); + parameters.put("client_id", clientId); + parameters.put("scope", "read"); + parameters.put("grant_type", "authorization_code"); + parameters.put("code", "kJAHDFG"); + + OAuth2AccessToken expectedToken = new DefaultOAuth2AccessToken("FOO"); + when(tokenGranter.grant(Mockito.eq("authorization_code"), Mockito.any(TokenRequest.class))).thenReturn( + expectedToken); + @SuppressWarnings("unchecked") + Map anyMap = Mockito.any(Map.class); + when(authorizationRequestFactory.createTokenRequest(anyMap, Mockito.any(ClientDetails.class))).thenReturn( + createFromParameters(parameters)); + + ResponseEntity response = endpoint.getAccessToken(clientAuthentication, parameters, HttpMethod.GET); + assertNotNull(response); + assertEquals(HttpStatus.OK, response.getStatusCode()); + OAuth2AccessToken body = response.getBody(); + assertEquals(body, expectedToken); + assertTrue("Wrong body: " + body, body.getTokenType() != null); + } + @Test(expected = InvalidGrantException.class) - public void testImplicitGrant() { + public void testImplicitGrant() throws HttpRequestMethodNotSupportedException { HashMap parameters = new HashMap(); parameters.put(OAuth2Utils.GRANT_TYPE, "implicit"); parameters.put("client_id", clientId); @@ -154,6 +186,6 @@ public void testImplicitGrant() { when(authorizationRequestFactory.createTokenRequest(anyMap, Mockito.eq(clientDetails))).thenReturn( createFromParameters(parameters)); when(clientDetailsService.loadClientByClientId(clientId)).thenReturn(clientDetails); - endpoint.getAccessToken(clientAuthentication, parameters); + endpoint.getAccessToken(clientAuthentication, parameters, HttpMethod.POST); } } From c784a64d46514b5d9413a5eec8db207bae0dedbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=BChrk?= Date: Sun, 11 Jan 2015 23:33:13 +0100 Subject: [PATCH 374/831] Convert client authorities to a set of strings. Makes it the same format as user authorities. Fixes gh-356 --- .../provider/token/DefaultAccessTokenConverter.java | 4 +++- .../token/DefaultAccessTokenConverterTests.java | 13 +++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java index 32dc3a083..b6800eb3b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java @@ -22,6 +22,7 @@ import java.util.Set; import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.provider.OAuth2Authentication; @@ -54,7 +55,8 @@ public void setUserTokenConverter(UserAuthenticationConverter userTokenConverter response.putAll(userTokenConverter.convertUserAuthentication(authentication.getUserAuthentication())); } else { if (clientToken.getAuthorities()!=null && !clientToken.getAuthorities().isEmpty()) { - response.put(UserAuthenticationConverter.AUTHORITIES, clientToken.getAuthorities()); + response.put(UserAuthenticationConverter.AUTHORITIES, + AuthorityUtils.authorityListToSet(clientToken.getAuthorities())); } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverterTests.java index e2f86d72a..1d5e07314 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverterTests.java @@ -13,9 +13,9 @@ package org.springframework.security.oauth2.provider.token; +import static java.util.Collections.singleton; import static org.junit.Assert.*; -import java.util.Collections; import java.util.Map; import org.junit.Before; @@ -34,18 +34,21 @@ */ public class DefaultAccessTokenConverterTests { + private String ROLE_CLIENT = "ROLE_CLIENT"; + private String ROLE_USER = "ROLE_USER"; + private DefaultAccessTokenConverter converter = new DefaultAccessTokenConverter(); private UsernamePasswordAuthenticationToken userAuthentication = new UsernamePasswordAuthenticationToken("foo", - "bar", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"))); + "bar", singleton(new SimpleGrantedAuthority(ROLE_USER))); private OAuth2Request request; @Before public void init() { request = RequestTokenFactory.createOAuth2Request(null, "id", - AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_CLIENT"), true, Collections.singleton("read"), - Collections.singleton("resource"), null, null, null); + AuthorityUtils.commaSeparatedStringToAuthorityList(ROLE_CLIENT), true, singleton("read"), + singleton("resource"), null, null, null); } @Test @@ -57,6 +60,7 @@ public void extractAuthentication() { assertTrue(map.containsKey(AccessTokenConverter.AUD)); assertTrue(map.containsKey(AccessTokenConverter.SCOPE)); assertTrue(map.containsKey(AccessTokenConverter.AUTHORITIES)); + assertEquals(singleton(ROLE_USER), map.get(AccessTokenConverter.AUTHORITIES)); OAuth2Authentication extracted = converter.extractAuthentication(map); assertTrue(extracted.getOAuth2Request().getResourceIds().contains("resource")); } @@ -70,6 +74,7 @@ public void extractAuthenticationFromClientToken() { assertTrue(map.containsKey(AccessTokenConverter.AUD)); assertTrue(map.containsKey(AccessTokenConverter.SCOPE)); assertTrue(map.containsKey(AccessTokenConverter.AUTHORITIES)); + assertEquals(singleton(ROLE_CLIENT), map.get(AccessTokenConverter.AUTHORITIES)); OAuth2Authentication extracted = converter.extractAuthentication(map); assertTrue(extracted.getOAuth2Request().getResourceIds().contains("resource")); } From 3e015a9b5294e8fdffa4f91238b8ff9c705b3a3d Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 28 Jan 2015 17:10:45 +0000 Subject: [PATCH 375/831] Allow anonymous access to oauth2 resources by default Sometimes it's actually useful to be able to accept an anonymous authentication. The default access rule still denies access, but at least if anonymous tokens are created all you have to change is the rule. --- .../configuration/ResourceServerConfiguration.java | 1 - .../OAuth2AuthenticationProcessingFilter.java | 11 ++++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java index b53870aa6..eb05826b9 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java @@ -138,7 +138,6 @@ else if (endpoints != null) { // N.B. exceptionHandling is duplicated in resources.configure() so that it works .exceptionHandling().accessDeniedHandler(resources.getAccessDeniedHandler()) .and() - .anonymous().disable() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .csrf().disable(); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilter.java index b256166b6..8943a3d75 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilter.java @@ -27,6 +27,7 @@ import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.security.authentication.AuthenticationDetailsSource; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.InsufficientAuthenticationException; @@ -117,7 +118,7 @@ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) Authentication authentication = tokenExtractor.extract(request); if (authentication == null) { - if (stateless) { + if (stateless && isAuthenticated()) { if (debug) { logger.debug("Clearing security context."); } @@ -159,6 +160,14 @@ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) chain.doFilter(request, response); } + private boolean isAuthenticated() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + if (authentication==null || authentication instanceof AnonymousAuthenticationToken) { + return false; + } + return true; + } + public void init(FilterConfig filterConfig) throws ServletException { } From 53500f3ed5c5d0f703792d97741770278a4730b4 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 28 Jan 2015 17:12:35 +0000 Subject: [PATCH 376/831] Improve tests (anticipating Spring 4) --- .../AbstractAuthorizationCodeProviderTests.java | 2 +- .../main/java/sparklr/common/HttpTestUtils.java | 16 ++++++++-------- .../vanilla/src/main/java/demo/Application.java | 2 +- .../AuthorizationCodeProviderCookieTests.java | 1 + .../demo/AuthorizationCodeProviderTests.java | 1 + 5 files changed, 12 insertions(+), 10 deletions(-) diff --git a/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java b/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java index 96b20bbc3..b8609ba89 100755 --- a/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java @@ -142,7 +142,7 @@ public void testIllegalAttemptToApproveWithoutUsingAuthorizationRequest() throws String authorizeUrl = getAuthorizeUrl("my-trusted-client", "http://anywhere.com/", "read"); authorizeUrl = authorizeUrl + "&user_oauth_approval=true"; - ResponseEntity response = http.postForStatus(authorizeUrl, headers, + ResponseEntity response = http.postForStatus(authorizeUrl, headers, new LinkedMultiValueMap()); assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); } 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 6d7595c85..5b106a9e3 100644 --- a/tests/annotation/common/src/main/java/sparklr/common/HttpTestUtils.java +++ b/tests/annotation/common/src/main/java/sparklr/common/HttpTestUtils.java @@ -142,30 +142,30 @@ public ResponseEntity postForMap(String path, HttpHeaders headers, MultiVal headers), Map.class); } - public ResponseEntity postForStatus(String path, MultiValueMap formData) { + public ResponseEntity postForStatus(String path, MultiValueMap formData) { return postForStatus(this.client, path, formData); } - public ResponseEntity postForStatus(String path, HttpHeaders headers, MultiValueMap formData) { + public ResponseEntity postForStatus(String path, HttpHeaders headers, MultiValueMap formData) { return postForStatus(this.client, path, headers, formData); } - private ResponseEntity postForStatus(RestOperations client, String path, + private ResponseEntity postForStatus(RestOperations client, String path, MultiValueMap formData) { return postForStatus(client, path, new HttpHeaders(), formData); } - private ResponseEntity postForStatus(RestOperations client, String path, HttpHeaders headers, + private ResponseEntity postForStatus(RestOperations client, String path, HttpHeaders headers, MultiValueMap formData) { HttpHeaders actualHeaders = new HttpHeaders(); actualHeaders.putAll(headers); actualHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED); return client.exchange(getUrl(path), HttpMethod.POST, new HttpEntity>(formData, - actualHeaders), (Class) null); + actualHeaders), String.class); } - public ResponseEntity postForRedirect(String path, HttpHeaders headers, MultiValueMap params) { - ResponseEntity exchange = postForStatus(path, headers, params); + public ResponseEntity postForRedirect(String path, HttpHeaders headers, MultiValueMap params) { + ResponseEntity exchange = postForStatus(path, headers, params); if (exchange.getStatusCode() != HttpStatus.FOUND) { throw new IllegalStateException("Expected 302 but server returned status code " + exchange.getStatusCode()); @@ -178,7 +178,7 @@ public ResponseEntity postForRedirect(String path, HttpHeaders headers, Mu String location = exchange.getHeaders().getLocation().toString(); - return client.exchange(location, HttpMethod.GET, new HttpEntity(null, headers), (Class) null); + return client.exchange(location, HttpMethod.GET, new HttpEntity(null, headers), String.class); } public ResponseEntity getForString(String path) { diff --git a/tests/annotation/vanilla/src/main/java/demo/Application.java b/tests/annotation/vanilla/src/main/java/demo/Application.java index d84285bac..31cdf0911 100644 --- a/tests/annotation/vanilla/src/main/java/demo/Application.java +++ b/tests/annotation/vanilla/src/main/java/demo/Application.java @@ -66,7 +66,7 @@ public void configure(ClientDetailsServiceConfigurer clients) throws Exception { .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") .scopes("read", "write", "trust") .resourceIds("oauth2-resource") - .accessTokenValiditySeconds(60) + .accessTokenValiditySeconds(600) .and() .withClient("my-client-with-registered-redirect") .authorizedGrantTypes("authorization_code") diff --git a/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderCookieTests.java b/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderCookieTests.java index 1b6f55475..7b614e004 100644 --- a/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderCookieTests.java +++ b/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderCookieTests.java @@ -36,6 +36,7 @@ public void testPostToProtectedResource() throws Exception { approveAccessTokenGrant("http://anywhere/", true); assertNotNull(context.getAccessToken()); LinkedMultiValueMap form = new LinkedMultiValueMap<>(); + form.set("foo", "bar"); assertEquals(HttpStatus.CREATED, http.postForStatus("/", getAuthenticatedHeaders(), form).getStatusCode()); } diff --git a/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java index beabbc002..49a38d4ab 100755 --- a/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java +++ b/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -37,6 +37,7 @@ public void testPostToProtectedResource() throws Exception { approveAccessTokenGrant("http://anywhere/", true); assertNotNull(context.getAccessToken()); LinkedMultiValueMap form = new LinkedMultiValueMap<>(); + form.set("foo", "bar"); assertEquals(HttpStatus.CREATED, http.postForStatus("/", form).getStatusCode()); } From 3c18f074556908d4d39ecb063ad3b3a8500b9161 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 29 Jan 2015 09:30:57 +0000 Subject: [PATCH 377/831] Fix sparklr2 to show photos in UI --- .../oauth/examples/sparklr/config/OAuth2ServerConfig.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java index 4641b2f1b..04426bee2 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java @@ -26,6 +26,7 @@ import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.oauth.examples.sparklr.oauth.SparklrUserApprovalHandler; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; @@ -65,6 +66,10 @@ public void configure(ResourceServerSecurityConfigurer resources) { public void configure(HttpSecurity http) throws Exception { // @formatter:off http + // Since we want the protected resources to be accessible in the UI as well we need + // session creation to be allowed (it's disabled by default in 2.0.6) + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) + .and() .requestMatchers().antMatchers("/photos/**", "/oauth/users/**", "/oauth/clients/**","/me") .and() .authorizeRequests() From b681a9edf158db33a1ae468d5d9b50656688f70f Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 29 Jan 2015 10:19:31 +0000 Subject: [PATCH 378/831] Fix test for anonymous token --- .../OAuth2AuthenticationProcessingFilterTests.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilterTests.java index bbfb95802..1cae97074 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilterTests.java @@ -91,16 +91,24 @@ public void testDetailsAddedWithForm() throws Exception { @Test public void testStateless() throws Exception { SecurityContextHolder.getContext().setAuthentication( - new AnonymousAuthenticationToken("FOO", "foo", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"))); + new UsernamePasswordAuthenticationToken("FOO", "foo", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"))); filter.doFilter(request, null, chain); assertNull(SecurityContextHolder.getContext().getAuthentication()); } + @Test + public void testStatelessPreservesAnonymous() throws Exception { + SecurityContextHolder.getContext().setAuthentication( + new AnonymousAuthenticationToken("FOO", "foo", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"))); + filter.doFilter(request, null, chain); + assertNotNull(SecurityContextHolder.getContext().getAuthentication()); + } + @Test public void testStateful() throws Exception { filter.setStateless(false); SecurityContextHolder.getContext().setAuthentication( - new AnonymousAuthenticationToken("FOO", "foo", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"))); + new UsernamePasswordAuthenticationToken("FOO", "foo", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"))); filter.doFilter(request, null, chain); assertNotNull(SecurityContextHolder.getContext().getAuthentication()); } From be1a91f9b86fc391abd54abc1435f83e6bf4b960 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 29 Jan 2015 11:06:06 +0000 Subject: [PATCH 379/831] Update to 2.0.7.BUILD-SNAPSHOT --- pom.xml | 2 +- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- tests/annotation/approval/pom.xml | 2 +- tests/annotation/client/pom.xml | 2 +- tests/annotation/common/pom.xml | 2 +- tests/annotation/form/pom.xml | 2 +- tests/annotation/jaxb/pom.xml | 2 +- tests/annotation/jdbc/pom.xml | 2 +- tests/annotation/jwt/pom.xml | 2 +- tests/annotation/mappings/pom.xml | 2 +- tests/annotation/multi/pom.xml | 2 +- tests/annotation/pom.xml | 4 ++-- tests/annotation/resource/pom.xml | 2 +- tests/annotation/vanilla/pom.xml | 2 +- tests/pom.xml | 2 +- tests/xml/approval/pom.xml | 2 +- tests/xml/client/pom.xml | 2 +- tests/xml/common/pom.xml | 2 +- tests/xml/form/pom.xml | 2 +- tests/xml/jdbc/pom.xml | 2 +- tests/xml/jwt/pom.xml | 2 +- tests/xml/mappings/pom.xml | 2 +- tests/xml/pom.xml | 4 ++-- tests/xml/vanilla/pom.xml | 2 +- 30 files changed, 32 insertions(+), 32 deletions(-) diff --git a/pom.xml b/pom.xml index e9a86cc45..53e6c0459 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.6.BUILD-SNAPSHOT + 2.0.7.BUILD-SNAPSHOT http://static.springframework.org/spring-security/oauth diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index da52569d5..353fc56ba 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.6.BUILD-SNAPSHOT + 2.0.7.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index 4bc48e92d..a12403598 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.6.BUILD-SNAPSHOT + 2.0.7.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index ca9fe9323..422365c89 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.6.BUILD-SNAPSHOT + 2.0.7.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index e4df0a71f..8e6b14105 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -5,7 +5,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.6.BUILD-SNAPSHOT + 2.0.7.BUILD-SNAPSHOT ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index c7b9110a6..afd5b8f75 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.6.BUILD-SNAPSHOT + 2.0.7.BUILD-SNAPSHOT spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index 47b9191ad..e1b7615dd 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.6.BUILD-SNAPSHOT + 2.0.7.BUILD-SNAPSHOT spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index f9a2a378a..e134530fc 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.6.BUILD-SNAPSHOT + 2.0.7.BUILD-SNAPSHOT spring-security-oauth2 diff --git a/tests/annotation/approval/pom.xml b/tests/annotation/approval/pom.xml index 9aa0fcdd4..fcb561999 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.6.BUILD-SNAPSHOT + 2.0.7.BUILD-SNAPSHOT diff --git a/tests/annotation/client/pom.xml b/tests/annotation/client/pom.xml index 4d1d24c80..dbcb8397b 100644 --- a/tests/annotation/client/pom.xml +++ b/tests/annotation/client/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.0.6.BUILD-SNAPSHOT + 2.0.7.BUILD-SNAPSHOT diff --git a/tests/annotation/common/pom.xml b/tests/annotation/common/pom.xml index 1010139fb..222b04da1 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.6.BUILD-SNAPSHOT + 2.0.7.BUILD-SNAPSHOT diff --git a/tests/annotation/form/pom.xml b/tests/annotation/form/pom.xml index 984e2ef87..45bb04d62 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.6.BUILD-SNAPSHOT + 2.0.7.BUILD-SNAPSHOT diff --git a/tests/annotation/jaxb/pom.xml b/tests/annotation/jaxb/pom.xml index 64c3c255c..8c0c31a74 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.6.BUILD-SNAPSHOT + 2.0.7.BUILD-SNAPSHOT diff --git a/tests/annotation/jdbc/pom.xml b/tests/annotation/jdbc/pom.xml index 4ede1c2e4..2a6f23d07 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.6.BUILD-SNAPSHOT + 2.0.7.BUILD-SNAPSHOT diff --git a/tests/annotation/jwt/pom.xml b/tests/annotation/jwt/pom.xml index 61fe600d9..2600565b8 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.6.BUILD-SNAPSHOT + 2.0.7.BUILD-SNAPSHOT diff --git a/tests/annotation/mappings/pom.xml b/tests/annotation/mappings/pom.xml index 6bd6274fe..8a8a7b2e0 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.6.BUILD-SNAPSHOT + 2.0.7.BUILD-SNAPSHOT diff --git a/tests/annotation/multi/pom.xml b/tests/annotation/multi/pom.xml index 1d5d9663f..0d8625378 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.6.BUILD-SNAPSHOT + 2.0.7.BUILD-SNAPSHOT diff --git a/tests/annotation/pom.xml b/tests/annotation/pom.xml index 101072570..054da3e49 100644 --- a/tests/annotation/pom.xml +++ b/tests/annotation/pom.xml @@ -4,7 +4,7 @@ org.demo spring-oauth2-tests-parent - 2.0.6.BUILD-SNAPSHOT + 2.0.7.BUILD-SNAPSHOT pom @@ -34,7 +34,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.0.6.BUILD-SNAPSHOT + 2.0.7.BUILD-SNAPSHOT jackson-mapper-asl diff --git a/tests/annotation/resource/pom.xml b/tests/annotation/resource/pom.xml index a10254927..0979417f6 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.6.BUILD-SNAPSHOT + 2.0.7.BUILD-SNAPSHOT diff --git a/tests/annotation/vanilla/pom.xml b/tests/annotation/vanilla/pom.xml index 8109e4c5b..5f041355c 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.6.BUILD-SNAPSHOT + 2.0.7.BUILD-SNAPSHOT diff --git a/tests/pom.xml b/tests/pom.xml index cc00d37fa..5c93f328a 100644 --- a/tests/pom.xml +++ b/tests/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.6.BUILD-SNAPSHOT + 2.0.7.BUILD-SNAPSHOT spring-security-oauth-tests diff --git a/tests/xml/approval/pom.xml b/tests/xml/approval/pom.xml index e67441379..a7590db56 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.6.BUILD-SNAPSHOT + 2.0.7.BUILD-SNAPSHOT diff --git a/tests/xml/client/pom.xml b/tests/xml/client/pom.xml index 7b610be7b..01a448e3e 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.6.BUILD-SNAPSHOT + 2.0.7.BUILD-SNAPSHOT diff --git a/tests/xml/common/pom.xml b/tests/xml/common/pom.xml index f90077eb9..58bec99df 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.6.BUILD-SNAPSHOT + 2.0.7.BUILD-SNAPSHOT diff --git a/tests/xml/form/pom.xml b/tests/xml/form/pom.xml index 986c24bf7..308cf7020 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.6.BUILD-SNAPSHOT + 2.0.7.BUILD-SNAPSHOT diff --git a/tests/xml/jdbc/pom.xml b/tests/xml/jdbc/pom.xml index 614df628e..92274a0bf 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.6.BUILD-SNAPSHOT + 2.0.7.BUILD-SNAPSHOT diff --git a/tests/xml/jwt/pom.xml b/tests/xml/jwt/pom.xml index e17b36054..bd5d7e1ce 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.6.BUILD-SNAPSHOT + 2.0.7.BUILD-SNAPSHOT diff --git a/tests/xml/mappings/pom.xml b/tests/xml/mappings/pom.xml index 127611d01..f51fc0a81 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.6.BUILD-SNAPSHOT + 2.0.7.BUILD-SNAPSHOT diff --git a/tests/xml/pom.xml b/tests/xml/pom.xml index a4a8f8f77..07cce72d0 100644 --- a/tests/xml/pom.xml +++ b/tests/xml/pom.xml @@ -4,7 +4,7 @@ org.demo spring-oauth2-tests-xml-parent - 2.0.6.BUILD-SNAPSHOT + 2.0.7.BUILD-SNAPSHOT pom @@ -32,7 +32,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.0.6.BUILD-SNAPSHOT + 2.0.7.BUILD-SNAPSHOT jackson-mapper-asl diff --git a/tests/xml/vanilla/pom.xml b/tests/xml/vanilla/pom.xml index 40a61a7ea..5603483c5 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.6.BUILD-SNAPSHOT + 2.0.7.BUILD-SNAPSHOT From 5ffe668a6ae3cc8a283caa51d1c0b32ee31102f7 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 6 Feb 2015 09:15:44 +0000 Subject: [PATCH 380/831] Fix tonr2 sample Broken in 2 ways: 1) not using the session scoped OAuth2ClientContext provided by Spring OAuth (non fatal, but dumb). 2) trying to use Jackson2 when Jackson1 is already on the classpath (error in facebook template). --- samples/oauth2/tonr/pom.xml | 6 ---- .../oauth/examples/config/WebMvcConfig.java | 30 ++++++------------- 2 files changed, 9 insertions(+), 27 deletions(-) diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 8e6b14105..ac54a4f11 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -181,12 +181,6 @@ test - - com.fasterxml.jackson.core - jackson-databind - 2.3.2 - - javax.servlet javax.servlet-api diff --git a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/WebMvcConfig.java b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/WebMvcConfig.java index bb3fa08bd..7c56d5917 100644 --- a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/WebMvcConfig.java +++ b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/WebMvcConfig.java @@ -4,21 +4,17 @@ import java.util.Collections; import java.util.List; -import javax.annotation.Resource; - import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; -import org.springframework.context.annotation.Scope; -import org.springframework.context.annotation.ScopedProxyMode; import org.springframework.context.support.ConversionServiceFactoryBean; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; import org.springframework.http.MediaType; import org.springframework.http.converter.BufferedImageHttpMessageConverter; import org.springframework.http.converter.HttpMessageConverter; -import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter; import org.springframework.security.oauth.examples.tonr.SparklrService; import org.springframework.security.oauth.examples.tonr.converter.AccessTokenRequestConverter; import org.springframework.security.oauth.examples.tonr.impl.SparklrServiceImpl; @@ -26,9 +22,9 @@ import org.springframework.security.oauth.examples.tonr.mvc.SparklrController; import org.springframework.security.oauth.examples.tonr.mvc.SparklrRedirectController; import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext; +import org.springframework.security.oauth2.client.OAuth2ClientContext; import org.springframework.security.oauth2.client.OAuth2RestTemplate; import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails; -import org.springframework.security.oauth2.client.token.AccessTokenRequest; import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails; import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails; import org.springframework.security.oauth2.common.AuthenticationScheme; @@ -160,10 +156,6 @@ protected static class ResourceConfiguration { @Value("${userAuthorizationUri}") private String userAuthorizationUri; - @Resource - @Qualifier("accessTokenRequest") - private AccessTokenRequest accessTokenRequest; - @Bean public OAuth2ProtectedResourceDetails sparklr() { AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails(); @@ -214,11 +206,9 @@ public OAuth2ProtectedResourceDetails trusted() { } @Bean - @Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES) - public OAuth2RestTemplate facebookRestTemplate() { - OAuth2RestTemplate template = new OAuth2RestTemplate(facebook(), new DefaultOAuth2ClientContext( - accessTokenRequest)); - MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); + public OAuth2RestTemplate facebookRestTemplate(OAuth2ClientContext clientContext) { + OAuth2RestTemplate template = new OAuth2RestTemplate(facebook(), clientContext); + MappingJacksonHttpMessageConverter converter = new MappingJacksonHttpMessageConverter(); converter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON, MediaType.valueOf("text/javascript"))); template.setMessageConverters(Arrays.> asList(converter)); @@ -226,15 +216,13 @@ public OAuth2RestTemplate facebookRestTemplate() { } @Bean - @Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES) - public OAuth2RestTemplate sparklrRestTemplate() { - return new OAuth2RestTemplate(sparklr(), new DefaultOAuth2ClientContext(accessTokenRequest)); + public OAuth2RestTemplate sparklrRestTemplate(OAuth2ClientContext clientContext) { + return new OAuth2RestTemplate(sparklr(), clientContext); } @Bean - @Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES) - public OAuth2RestTemplate sparklrRedirectRestTemplate() { - return new OAuth2RestTemplate(sparklrRedirect(), new DefaultOAuth2ClientContext(accessTokenRequest)); + public OAuth2RestTemplate sparklrRedirectRestTemplate(OAuth2ClientContext clientContext) { + return new OAuth2RestTemplate(sparklrRedirect(), clientContext); } @Bean From 616b989eacfcec26bfa08ea23e01e9503ed1a5f8 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 9 Feb 2015 10:05:44 +0000 Subject: [PATCH 381/831] Add authentication event publisher to OAuth2AuthenticationProcessingFilter Authentication events are not being published (before this change) because they generally only come from a ProviderManager (and there isn't one). The OAuth2AuthenticationProcessingFilter seems like the most logical place to put this feature (rather than the OAuth2AuthenticationManager, just because we can handle all failures in the same place with the filter). Fixes gh-393 --- .../ResourceServerConfiguration.java | 7 +++ .../ResourceServerSecurityConfigurer.java | 12 +++++ .../OAuth2AuthenticationManager.java | 2 +- .../OAuth2AuthenticationProcessingFilter.java | 28 ++++++++++- .../client/http/OAuth2ErrorHandlerTests.java | 49 +++++++++++++------ ...h2AuthenticationProcessingFilterTests.java | 37 ++++++++++++++ .../src/main/java/demo/Application.java | 22 --------- 7 files changed, 118 insertions(+), 39 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java index eb05826b9..2716641ff 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java @@ -26,6 +26,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import org.springframework.security.authentication.AnonymousAuthenticationProvider; +import org.springframework.security.authentication.AuthenticationEventPublisher; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity.RequestMatcherConfigurer; @@ -49,6 +50,9 @@ public class ResourceServerConfiguration extends WebSecurityConfigurerAdapter im @Autowired(required = false) private TokenStore tokenStore; + @Autowired(required = false) + private AuthenticationEventPublisher eventPublisher; + @Autowired(required = false) private ResourceServerTokenServices[] tokenServices; @@ -130,6 +134,9 @@ else if (endpoints != null) { resources.tokenStore(endpoints.getEndpointsConfigurer().getTokenStore()); } } + if (eventPublisher != null) { + resources.eventPublisher(eventPublisher); + } for (ResourceServerConfigurer configurer : configurers) { configurer.configure(resources); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java index 92f0e5c38..4042ab38b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java @@ -19,6 +19,7 @@ import org.springframework.http.MediaType; import org.springframework.security.access.expression.SecurityExpressionHandler; +import org.springframework.security.authentication.AuthenticationEventPublisher; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.SecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.builders.HttpSecurity; @@ -62,6 +63,8 @@ public final class ResourceServerSecurityConfigurer extends private AuthenticationManager authenticationManager; + private AuthenticationEventPublisher eventPublisher = null; + private ResourceServerTokenServices resourceTokenServices; private TokenStore tokenStore = new InMemoryTokenStore(); @@ -112,6 +115,12 @@ public ResourceServerSecurityConfigurer tokenStore(TokenStore tokenStore) { return this; } + public ResourceServerSecurityConfigurer eventPublisher(AuthenticationEventPublisher eventPublisher) { + Assert.state(eventPublisher != null, "AuthenticationEventPublisher cannot be null"); + this.eventPublisher = eventPublisher; + return this; + } + public ResourceServerSecurityConfigurer expressionHandler( SecurityExpressionHandler expressionHandler) { Assert.state(expressionHandler != null, "SecurityExpressionHandler cannot be null"); @@ -176,6 +185,9 @@ public void configure(HttpSecurity http) throws Exception { resourcesServerFilter = new OAuth2AuthenticationProcessingFilter(); resourcesServerFilter.setAuthenticationEntryPoint(authenticationEntryPoint); resourcesServerFilter.setAuthenticationManager(oauthAuthenticationManager); + if (eventPublisher != null) { + resourcesServerFilter.setAuthenticationEventPublisher(eventPublisher); + } if (tokenExtractor != null) { resourcesServerFilter.setTokenExtractor(tokenExtractor); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java index 27b94da54..e677a57fc 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java @@ -43,7 +43,7 @@ public class OAuth2AuthenticationManager implements AuthenticationManager, Initi private String resourceId; - public void setResourceId(String resourceId) { + public void setResourceId(String resourceId) { this.resourceId = resourceId; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilter.java index 8943a3d75..65278c005 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilter.java @@ -29,14 +29,18 @@ import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.security.authentication.AuthenticationDetailsSource; +import org.springframework.security.authentication.AuthenticationEventPublisher; import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.InsufficientAuthenticationException; import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint; import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken; import org.springframework.util.Assert; /** @@ -59,6 +63,8 @@ public class OAuth2AuthenticationProcessingFilter implements Filter, Initializin private TokenExtractor tokenExtractor = new BearerTokenExtractor(); + private AuthenticationEventPublisher eventPublisher = new NullEventPublisher(); + private boolean stateless = true; /** @@ -93,6 +99,13 @@ public void setTokenExtractor(TokenExtractor tokenExtractor) { this.tokenExtractor = tokenExtractor; } + /** + * @param eventPublisher the event publisher to set + */ + public void setAuthenticationEventPublisher(AuthenticationEventPublisher eventPublisher) { + this.eventPublisher = eventPublisher; + } + /** * @param authenticationDetailsSource The AuthenticationDetailsSource to use */ @@ -116,7 +129,7 @@ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) try { Authentication authentication = tokenExtractor.extract(request); - + if (authentication == null) { if (stateless && isAuthenticated()) { if (debug) { @@ -140,6 +153,7 @@ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) logger.debug("Authentication success: " + authResult); } + eventPublisher.publishAuthenticationSuccess(authResult); SecurityContextHolder.getContext().setAuthentication(authResult); } @@ -150,6 +164,8 @@ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) if (debug) { logger.debug("Authentication request failed: " + failed); } + eventPublisher.publishAuthenticationFailure(new BadCredentialsException(failed.getMessage(), failed), + new PreAuthenticatedAuthenticationToken("access-token", "N/A")); authenticationEntryPoint.commence(request, response, new InsufficientAuthenticationException(failed.getMessage(), failed)); @@ -162,7 +178,7 @@ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) private boolean isAuthenticated() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - if (authentication==null || authentication instanceof AnonymousAuthenticationToken) { + if (authentication == null || authentication instanceof AnonymousAuthenticationToken) { return false; } return true; @@ -174,4 +190,12 @@ public void init(FilterConfig filterConfig) throws ServletException { public void destroy() { } + private static final class NullEventPublisher implements AuthenticationEventPublisher { + public void publishAuthenticationFailure(AuthenticationException exception, Authentication authentication) { + } + + public void publishAuthenticationSuccess(Authentication authentication) { + } + } + } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandlerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandlerTests.java index d079eb6e5..471e48809 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandlerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandlerTests.java @@ -31,6 +31,7 @@ import org.mockito.runners.MockitoJUnitRunner; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.client.ClientHttpResponse; import org.springframework.security.oauth2.client.resource.BaseOAuth2ProtectedResourceDetails; import org.springframework.web.client.HttpClientErrorException; @@ -56,11 +57,13 @@ public class OAuth2ErrorHandlerTests { private final class TestClientHttpResponse implements ClientHttpResponse { private final HttpHeaders headers; + private final HttpStatus status; + private final InputStream body; public TestClientHttpResponse(HttpHeaders headers, int status) { - this(headers,status,new ByteArrayInputStream(new byte[0])); + this(headers, status, new ByteArrayInputStream(new byte[0])); } public TestClientHttpResponse(HttpHeaders headers, int status, InputStream bodyStream) { @@ -84,7 +87,7 @@ public HttpStatus getStatusCode() throws IOException { public String getStatusText() throws IOException { return status.getReasonPhrase(); } - + public int getRawStatusCode() throws IOException { return status.value(); } @@ -103,7 +106,7 @@ public void testHandleErrorClientHttpResponse() throws Exception { HttpHeaders headers = new HttpHeaders(); headers.set("www-authenticate", "Bearer error=foo"); - ClientHttpResponse response = new TestClientHttpResponse(headers,401); + ClientHttpResponse response = new TestClientHttpResponse(headers, 401); expected.expectMessage("foo"); handler.handleError(response); @@ -115,7 +118,7 @@ public void testHandleErrorWithInvalidToken() throws Exception { HttpHeaders headers = new HttpHeaders(); headers.set("www-authenticate", "Bearer error=\"invalid_token\", description=\"foo\""); - ClientHttpResponse response = new TestClientHttpResponse(headers,401); + ClientHttpResponse response = new TestClientHttpResponse(headers, 401); expected.expect(AccessTokenRequiredException.class); expected.expectMessage("OAuth2 access denied"); @@ -138,7 +141,7 @@ public void handleError(ClientHttpResponse response) throws IOException { }, resource); HttpHeaders headers = new HttpHeaders(); - ClientHttpResponse response = new TestClientHttpResponse(headers,401); + ClientHttpResponse response = new TestClientHttpResponse(headers, 401); expected.expectMessage("planned"); handler.handleError(response); @@ -148,7 +151,7 @@ public void handleError(ClientHttpResponse response) throws IOException { @Test public void testHandle500Error() throws Exception { HttpHeaders headers = new HttpHeaders(); - ClientHttpResponse response = new TestClientHttpResponse(headers,500); + ClientHttpResponse response = new TestClientHttpResponse(headers, 500); expected.expect(HttpServerErrorException.class); handler.handleError(response); @@ -157,7 +160,27 @@ public void testHandle500Error() throws Exception { @Test public void testHandleGeneric400Error() throws Exception { HttpHeaders headers = new HttpHeaders(); - ClientHttpResponse response = new TestClientHttpResponse(headers,400); + ClientHttpResponse response = new TestClientHttpResponse(headers, 400); + + expected.expect(HttpClientErrorException.class); + handler.handleError(response); + } + + @Test + public void testHandleGeneric403Error() throws Exception { + HttpHeaders headers = new HttpHeaders(); + ClientHttpResponse response = new TestClientHttpResponse(headers, 403); + + expected.expect(HttpClientErrorException.class); + handler.handleError(response); + } + + @Test + public void testHandleGeneric403ErrorWithBody() throws Exception { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + ClientHttpResponse response = new TestClientHttpResponse(headers, 403, new ByteArrayInputStream( + "{}".getBytes())); expected.expect(HttpClientErrorException.class); handler.handleError(response); @@ -176,17 +199,15 @@ public void handleError(ClientHttpResponse response) throws IOException { byte[] buf = new byte[appSpecificBodyContent.length()]; int readResponse = body.read(buf); Assert.assertEquals(buf.length, readResponse); - Assert.assertEquals(appSpecificBodyContent,new String(buf, "UTF-8")); + Assert.assertEquals(appSpecificBodyContent, new String(buf, "UTF-8")); throw new RuntimeException("planned"); } }, resource); HttpHeaders headers = new HttpHeaders(); - headers.set("Content-Length",""+appSpecificBodyContent.length()); - headers.set("Content-Type","application/json"); - InputStream appSpecificErrorBody = - new ByteArrayInputStream(appSpecificBodyContent.getBytes("UTF-8")); - ClientHttpResponse response = - new TestClientHttpResponse(headers,400,appSpecificErrorBody); + headers.set("Content-Length", "" + appSpecificBodyContent.length()); + headers.set("Content-Type", "application/json"); + InputStream appSpecificErrorBody = new ByteArrayInputStream(appSpecificBodyContent.getBytes("UTF-8")); + ClientHttpResponse response = new TestClientHttpResponse(headers, 400, appSpecificErrorBody); expected.expectMessage("planned"); handler.handleError(response); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilterTests.java index 1cae97074..d3b34b51f 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilterTests.java @@ -23,7 +23,9 @@ import org.junit.Test; import org.mockito.Mockito; import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.security.authentication.AnonymousAuthenticationToken; +import org.springframework.security.authentication.AuthenticationEventPublisher; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; @@ -31,6 +33,7 @@ import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.RequestTokenFactory; @@ -44,6 +47,8 @@ public class OAuth2AuthenticationProcessingFilterTests { private MockHttpServletRequest request = new MockHttpServletRequest(); + private MockHttpServletResponse response = new MockHttpServletResponse(); + private Authentication userAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala"); private OAuth2Authentication authentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request( @@ -55,6 +60,9 @@ public class OAuth2AuthenticationProcessingFilterTests { filter.setAuthenticationManager(new AuthenticationManager() { public Authentication authenticate(Authentication request) throws AuthenticationException { + if ("BAD".equals(request.getPrincipal())) { + throw new InvalidTokenException("Invalid token"); + } authentication.setDetails(request.getDetails()); return authentication; } @@ -113,4 +121,33 @@ public void testStateful() throws Exception { assertNotNull(SecurityContextHolder.getContext().getAuthentication()); } + @Test + public void testNoEventsPublishedWithNoToken() throws Exception { + AuthenticationEventPublisher eventPublisher = Mockito.mock(AuthenticationEventPublisher.class); + filter.setAuthenticationEventPublisher(eventPublisher); + filter.doFilter(request, null, chain); + Mockito.verify(eventPublisher, Mockito.never()).publishAuthenticationFailure(Mockito.any(AuthenticationException.class), Mockito.any(Authentication.class)); + Mockito.verify(eventPublisher, Mockito.never()).publishAuthenticationSuccess(Mockito.any(Authentication.class)); + } + + @Test + public void testSuccessEventsPublishedWithToken() throws Exception { + request.addHeader("Authorization", "Bearer FOO"); + AuthenticationEventPublisher eventPublisher = Mockito.mock(AuthenticationEventPublisher.class); + filter.setAuthenticationEventPublisher(eventPublisher); + filter.doFilter(request, null, chain); + Mockito.verify(eventPublisher, Mockito.never()).publishAuthenticationFailure(Mockito.any(AuthenticationException.class), Mockito.any(Authentication.class)); + Mockito.verify(eventPublisher).publishAuthenticationSuccess(Mockito.any(Authentication.class)); + } + + @Test + public void testFailureEventsPublishedWithBadToken() throws Exception { + request.addHeader("Authorization", "Bearer BAD"); + AuthenticationEventPublisher eventPublisher = Mockito.mock(AuthenticationEventPublisher.class); + filter.setAuthenticationEventPublisher(eventPublisher); + filter.doFilter(request, response, chain); + Mockito.verify(eventPublisher).publishAuthenticationFailure(Mockito.any(AuthenticationException.class), Mockito.any(Authentication.class)); + Mockito.verify(eventPublisher, Mockito.never()).publishAuthenticationSuccess(Mockito.any(Authentication.class)); + } + } diff --git a/tests/annotation/vanilla/src/main/java/demo/Application.java b/tests/annotation/vanilla/src/main/java/demo/Application.java index 31cdf0911..a2be1c356 100644 --- a/tests/annotation/vanilla/src/main/java/demo/Application.java +++ b/tests/annotation/vanilla/src/main/java/demo/Application.java @@ -1,10 +1,5 @@ package demo; -import javax.servlet.http.HttpSessionEvent; -import javax.servlet.http.HttpSessionListener; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; @@ -16,7 +11,6 @@ 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.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; -import org.springframework.stereotype.Component; import org.springframework.util.MultiValueMap; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -86,20 +80,4 @@ public void configure(ClientDetailsServiceConfigurer clients) throws Exception { } - @Component - protected static class SessionListener implements HttpSessionListener { - - private static Log logger = LogFactory.getLog(SessionListener.class); - - @Override - public void sessionCreated(HttpSessionEvent event) { - logger.info("Created: " + event.getSession().getId()); - } - - @Override - public void sessionDestroyed(HttpSessionEvent event) { - logger.info("Destroyed: " + event.getSession().getId()); - } - - } } From 4c4fdc3e625f66c19bffc999765b8a2c51a42fe2 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 10 Feb 2015 08:58:05 +0000 Subject: [PATCH 382/831] Comment out failing test Fixes gh-394 --- .../security/oauth2/client/http/OAuth2ErrorHandlerTests.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandlerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandlerTests.java index 471e48809..ef0ec68a9 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandlerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandlerTests.java @@ -23,6 +23,7 @@ import java.io.InputStream; import org.junit.Assert; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -176,6 +177,7 @@ public void testHandleGeneric403Error() throws Exception { } @Test + @Ignore("See https://github.com/spring-projects/spring-security-oauth/issues/387") public void testHandleGeneric403ErrorWithBody() throws Exception { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); From 8a68cf248186bf41b0cd5611bc7a632508008361 Mon Sep 17 00:00:00 2001 From: Ruslan Forostianov Date: Tue, 3 Feb 2015 16:23:37 +0100 Subject: [PATCH 383/831] UserDetailsService to throw UsernameNotFoundException Without this change it's triggering wrong event listeners by spring security: AuthenticationFailureServiceExceptionEvent instead of AuthenticationFailureBadCredentialsEvent Fixes gh-383 --- .../ClientDetailsUserDetailsService.java | 8 ++- .../ClientDetailsUserDetailsServiceTests.java | 58 +++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/ClientDetailsUserDetailsServiceTests.java diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientDetailsUserDetailsService.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientDetailsUserDetailsService.java index e68757a51..d088c4f64 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientDetailsUserDetailsService.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientDetailsUserDetailsService.java @@ -19,6 +19,7 @@ import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.NoSuchClientException; /** * @author Dave Syer @@ -41,7 +42,12 @@ public void setPasswordEncoder(PasswordEncoder passwordEncoder) { } public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { - ClientDetails clientDetails = clientDetailsService.loadClientByClientId(username); + ClientDetails clientDetails; + try { + clientDetails = clientDetailsService.loadClientByClientId(username); + } catch (NoSuchClientException e) { + throw new UsernameNotFoundException(e.getMessage(), e); + } String clientSecret = clientDetails.getClientSecret(); if (clientSecret== null || clientSecret.trim().length()==0) { clientSecret = emptyPassword; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/ClientDetailsUserDetailsServiceTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/ClientDetailsUserDetailsServiceTests.java new file mode 100644 index 000000000..dcee49682 --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/ClientDetailsUserDetailsServiceTests.java @@ -0,0 +1,58 @@ +/* + * Copyright 2013 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.client; + +import org.junit.Test; +import org.mockito.Mockito; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.ClientRegistrationException; +import org.springframework.security.oauth2.provider.NoSuchClientException; +import org.springframework.security.oauth2.provider.token.UserAuthenticationConverter; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author Ruslan Forostianov + */ +public class ClientDetailsUserDetailsServiceTests { + + @Test(expected = UsernameNotFoundException.class) + public void shouldThrowUsernameNotFoundExceptionWhenNoSuchClient() throws Exception { + + Map map = new HashMap(); + map.put(UserAuthenticationConverter.USERNAME, "test_user"); + + ClientDetailsService clientDetailsService = Mockito.mock(ClientDetailsService.class); + Mockito.when(clientDetailsService.loadClientByClientId("test_user")).thenThrow(NoSuchClientException.class); + ClientDetailsUserDetailsService testee = new ClientDetailsUserDetailsService(clientDetailsService); + + testee.loadUserByUsername("test_user"); + } + + @Test(expected = ClientRegistrationException.class) + public void shouldConductOriginalException() throws Exception { + + Map map = new HashMap(); + map.put(UserAuthenticationConverter.USERNAME, "test_user"); + + ClientDetailsService clientDetailsService = Mockito.mock(ClientDetailsService.class); + Mockito.when(clientDetailsService.loadClientByClientId("test_user")).thenThrow(ClientRegistrationException.class); + ClientDetailsUserDetailsService testee = new ClientDetailsUserDetailsService(clientDetailsService); + + testee.loadUserByUsername("test_user"); + } + +} From ec907a1afdb1c6f086a41a125cebbd6b80f366f5 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 13 Feb 2015 12:18:21 +0000 Subject: [PATCH 384/831] Parse JSON manually (avoid dependency on Jackson) The only JSON we need to parse is the header and that is very simple, so it's probably nicer for users to not depend on any parser. Fixes gh-400 --- spring-security-jwt/pom.xml | 19 +- .../security/jwt/JwtHelper.java | 168 +++++++++--------- 2 files changed, 91 insertions(+), 96 deletions(-) diff --git a/spring-security-jwt/pom.xml b/spring-security-jwt/pom.xml index 639ed71e3..e1e7b2503 100755 --- a/spring-security-jwt/pom.xml +++ b/spring-security-jwt/pom.xml @@ -5,7 +5,7 @@ org.springframework.security spring-security-jwt - 1.0.3.BUILD-SNAPSHOT + 1.0.3.RELEASE jar Spring Security JWT Library @@ -26,12 +26,6 @@ - - org.codehaus.jackson - jackson-mapper-asl - 1.9.13 - - org.bouncycastle bcpkix-jdk15on @@ -74,7 +68,8 @@ **/*Tests.java - + @@ -134,15 +129,15 @@ - springframework-release + repo.spring.io Spring Release Repository - s3://maven.springframework.org/release + https://repo.spring.io/libs-release-local - springframework-snapshot + repo.spring.io Spring Snapshot Repository - s3://maven.springframework.org/snapshot + https://repo.spring.io/libs-snapshot-local diff --git a/spring-security-jwt/src/main/java/org/springframework/security/jwt/JwtHelper.java b/spring-security-jwt/src/main/java/org/springframework/security/jwt/JwtHelper.java index 4ebd7bc26..810352b24 100644 --- a/spring-security-jwt/src/main/java/org/springframework/security/jwt/JwtHelper.java +++ b/spring-security-jwt/src/main/java/org/springframework/security/jwt/JwtHelper.java @@ -19,19 +19,16 @@ import static org.springframework.security.jwt.codec.Codecs.utf8Decode; import static org.springframework.security.jwt.codec.Codecs.utf8Encode; -import java.io.ByteArrayOutputStream; -import java.io.IOException; import java.nio.CharBuffer; +import java.util.LinkedHashMap; +import java.util.Map; -import org.codehaus.jackson.JsonFactory; -import org.codehaus.jackson.JsonGenerator; -import org.codehaus.jackson.JsonParser; -import org.codehaus.jackson.JsonToken; import org.springframework.security.jwt.crypto.sign.SignatureVerifier; import org.springframework.security.jwt.crypto.sign.Signer; /** * @author Luke Taylor + * @author Dave Syer */ public class JwtHelper { static byte[] PERIOD = utf8Encode("."); @@ -45,7 +42,7 @@ public static Jwt decode(String token) { int firstPeriod = token.indexOf('.'); int lastPeriod = token.lastIndexOf('.'); - if (firstPeriod <=0 || lastPeriod <= firstPeriod) { + if (firstPeriod <= 0 || lastPeriod <= firstPeriod) { throw new IllegalArgumentException("JWT must have 3 tokens"); } CharBuffer buffer = CharBuffer.wrap(token, 0, firstPeriod); @@ -63,7 +60,8 @@ public static Jwt decode(String token) { throw new IllegalArgumentException("Signed or encrypted token must have non-empty crypto segment"); } crypto = new byte[0]; - } else { + } + else { buffer.limit(token.length()).position(lastPeriod + 1); crypto = b64UrlDecode(buffer); } @@ -91,14 +89,12 @@ public static Jwt encode(CharSequence content, Signer signer) { * Handles the JSON parsing and serialization. */ class JwtHeaderHelper { - private static final JsonFactory f = new JsonFactory(); static JwtHeader create(String header) { byte[] bytes = b64UrlDecode(header); return new JwtHeader(bytes, parseParams(bytes)); } - static JwtHeader create(Signer signer) { HeaderParameters p = new HeaderParameters(sigAlg(signer.algorithm()), null, null); return new JwtHeader(serializeParams(p), p); @@ -110,84 +106,81 @@ static JwtHeader create(String alg, String enc, byte[] iv) { } static HeaderParameters parseParams(byte[] header) { - JsonParser jp = null; - try { - jp = f.createJsonParser(header); - String alg = null, enc = null, iv = null; - jp.nextToken(); - while (jp.nextToken() != JsonToken.END_OBJECT) { - String fieldname = jp.getCurrentName(); - jp.nextToken(); - if (!JsonToken.VALUE_STRING.equals(jp.getCurrentToken())) { - throw new IllegalArgumentException("Header fields must be strings"); - } - String value = jp.getText(); - if ("alg".equals(fieldname)) { - if (alg != null) { - throw new IllegalArgumentException("Duplicate 'alg' field"); - } - alg = value; - } else if ("enc".equals(fieldname)) { - if (enc != null) { - throw new IllegalArgumentException("Duplicate 'enc' field"); - } - enc = value; - } if ("iv".equals(fieldname)) { - if (iv != null) { - throw new IllegalArgumentException("Duplicate 'iv' field"); - } - iv = jp.nextToken().asString(); - } else if ("typ".equals(fieldname)) { - if (!"JWT".equalsIgnoreCase(value)) { - throw new IllegalArgumentException("typ is not \"JWT\""); - } - } - } + Map map = parseMap(utf8Decode(header)); + String alg = map.get("alg"), enc = map.get("enc"), iv = map.get("iv"), typ = map.get("typ"); + if (typ != null && !"JWT".equalsIgnoreCase(typ)) { + throw new IllegalArgumentException("typ is not \"JWT\""); + } + return new HeaderParameters(alg, enc, iv); + } - return new HeaderParameters(alg, enc, iv); - } catch (IOException io) { - throw new RuntimeException(io); - } finally { - if (jp != null) { - try { - jp.close(); - } catch (IOException ignore) { - } + private static Map parseMap(String json) { + if (json != null) { + json = json.trim(); + if (json.startsWith("{")) { + return parseMapInternal(json); + } + else if (json.equals("")) { + return new LinkedHashMap(); } } + throw new IllegalArgumentException("Invalid JSON (null)"); } - private static byte[] serializeParams(HeaderParameters params) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - JsonGenerator g = null; - - try { - g = f.createJsonGenerator(baos); - g.writeStartObject(); - g.writeStringField("alg", params.alg); - if (params.enc != null) { - g.writeStringField("enc", params.enc); + private static Map parseMapInternal(String json) { + Map map = new LinkedHashMap(); + json = trimLeadingCharacter(trimTrailingCharacter(json, '}'), '{'); + for (String pair : json.split(",")) { + String[] values = pair.split(":"); + String key = strip(values[0], '"'); + String value = null; + if (values.length > 0) { + value = strip(values[1], '"'); } - if (params.iv != null) { - g.writeStringField("iv", params.iv); + if (map.containsKey(key)) { + throw new IllegalArgumentException("Duplicate '" + key + "' field"); } - g.writeEndObject(); - g.flush(); + map.put(key, value); + } + return map; + } + + private static String strip(String string, char c) { + return trimLeadingCharacter(trimTrailingCharacter(string.trim(), c), c); + } - return baos.toByteArray(); + private static String trimTrailingCharacter(String string, char c) { + if (string.length() >= 0 && string.charAt(string.length() - 1) == c) { + return string.substring(0, string.length() - 1); } - catch (IOException io) { - throw new RuntimeException(io); - } finally { - if (g != null) { - try { - g.close(); - } catch (IOException ignore) { - } - } + return string; + } + + private static String trimLeadingCharacter(String string, char c) { + if (string.length() >= 0 && string.charAt(0) == c) { + return string.substring(1); + } + return string; + } + + private static byte[] serializeParams(HeaderParameters params) { + StringBuilder builder = new StringBuilder("{"); + + appendField(builder, "alg", params.alg); + if (params.enc != null) { + appendField(builder, "enc", params.enc); + } + if (params.iv != null) { + appendField(builder, "iv", params.iv); } + builder.append("}"); + return utf8Encode(builder.toString()); } + + private static void appendField(StringBuilder builder, String name, String value) { + builder.append("\"").append(name).append("\":\"").append(value).append("\""); + } } /** @@ -196,6 +189,7 @@ private static byte[] serializeParams(HeaderParameters params) { */ class JwtHeader implements BinaryFormat { private final byte[] bytes; + final HeaderParameters parameters; /** @@ -219,7 +213,9 @@ public String toString() { class HeaderParameters { final String alg; + final String enc; + final String iv; HeaderParameters(String alg) { @@ -239,8 +235,11 @@ class HeaderParameters { class JwtImpl implements Jwt { private final JwtHeader header; + private final byte[] content; + private final byte[] crypto; + private String claims; /** @@ -262,19 +261,20 @@ class JwtImpl implements Jwt { */ public void verifySignature(SignatureVerifier verifier) { verifier.verify(signingInput(), crypto); - } + } private byte[] signingInput() { return concat(b64UrlEncode(header.bytes()), JwtHelper.PERIOD, b64UrlEncode(content)); } - /** - * Allows retrieval of the full token. - * - * @return the encoded header, claims and crypto segments concatenated with "." characters - */ + /** + * Allows retrieval of the full token. + * + * @return the encoded header, claims and crypto segments concatenated with "." characters + */ public byte[] bytes() { - return concat(b64UrlEncode(header.bytes()), JwtHelper.PERIOD, b64UrlEncode(content), JwtHelper.PERIOD, b64UrlEncode(crypto)); + return concat(b64UrlEncode(header.bytes()), JwtHelper.PERIOD, b64UrlEncode(content), JwtHelper.PERIOD, + b64UrlEncode(crypto)); } public String getClaims() { @@ -287,6 +287,6 @@ public String getEncoded() { @Override public String toString() { - return header + " " + claims + " ["+ crypto.length + " crypto bytes]"; + return header + " " + claims + " [" + crypto.length + " crypto bytes]"; } } From cc47a488385b16c3946d43f5583b038d4aecd559 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 13 Feb 2015 12:23:52 +0000 Subject: [PATCH 385/831] Bump JWT to snapshot --- spring-security-jwt/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-security-jwt/pom.xml b/spring-security-jwt/pom.xml index e1e7b2503..904b0e0cd 100755 --- a/spring-security-jwt/pom.xml +++ b/spring-security-jwt/pom.xml @@ -5,7 +5,7 @@ org.springframework.security spring-security-jwt - 1.0.3.RELEASE + 1.0.4.BUILD-SNAPSHOT jar Spring Security JWT Library From befb023a5cd7ce6e4ee16c1eeab414895d01ab92 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 16 Feb 2015 16:43:56 +0000 Subject: [PATCH 386/831] Add includeGrantType flag in DefaultAccessTokenConverter Defaults to false (preserving existing behaviour and keeping JWT length to a minimum), but can be set to true and injected into a JwtTokenEnhancer to provide the original grant type when a token is decoded. See gh-405. --- .../provider/token/AccessTokenConverter.java | 2 ++ .../token/DefaultAccessTokenConverter.java | 18 ++++++++++++++++++ .../token/store/JwtAccessTokenConverter.java | 1 + .../token/store/JwtTokenStoreTests.java | 16 ++++++++++++++-- 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AccessTokenConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AccessTokenConverter.java index faa4c2eef..e981b6d1d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AccessTokenConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AccessTokenConverter.java @@ -32,6 +32,8 @@ public interface AccessTokenConverter { final String EXP = "exp"; final String JTI = "jti"; + + final String GRANT_TYPE = "grant_type"; final String ATI = "ati"; diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java index b6800eb3b..2ea5b0496 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java @@ -38,6 +38,8 @@ public class DefaultAccessTokenConverter implements AccessTokenConverter { private UserAuthenticationConverter userTokenConverter = new DefaultUserAuthenticationConverter(); + private boolean includeGrantType; + /** * Converter for the part of the data in the token representing a user. * @@ -47,6 +49,15 @@ public void setUserTokenConverter(UserAuthenticationConverter userTokenConverter this.userTokenConverter = userTokenConverter; } + /** + * Flag to indicate the the grant type should be included in the converted token. + * + * @param includeGrantType the flag value (default false) + */ + public void setIncludeGrantType(boolean includeGrantType) { + this.includeGrantType = includeGrantType; + } + public Map convertAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) { Map response = new HashMap(); OAuth2Request clientToken = authentication.getOAuth2Request(); @@ -70,6 +81,10 @@ public void setUserTokenConverter(UserAuthenticationConverter userTokenConverter if (token.getExpiration() != null) { response.put(EXP, token.getExpiration().getTime() / 1000); } + + if (includeGrantType && authentication.getOAuth2Request().getGrantType()!=null) { + response.put(GRANT_TYPE, authentication.getOAuth2Request().getGrantType()); + } response.putAll(token.getAdditionalInformation()); @@ -110,6 +125,9 @@ public OAuth2Authentication extractAuthentication(Map map) { Authentication user = userTokenConverter.extractAuthentication(map); String clientId = (String) map.get(CLIENT_ID); parameters.put(CLIENT_ID, clientId); + if (includeGrantType && map.containsKey(GRANT_TYPE)) { + parameters.put(GRANT_TYPE, (String) map.get(GRANT_TYPE)); + } @SuppressWarnings("unchecked") Set resourceIds = new LinkedHashSet(map.containsKey(AUD) ? (Collection) map.get(AUD) : Collections.emptySet()); diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java index a525f82a2..d9906f67d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java @@ -277,4 +277,5 @@ else if (verifier instanceof MacSigner){ } this.verifier = verifier; } + } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStoreTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStoreTests.java index e8b6b030b..228986496 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStoreTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStoreTests.java @@ -27,6 +27,7 @@ import org.springframework.security.oauth2.provider.approval.Approval.ApprovalStatus; import org.springframework.security.oauth2.provider.approval.InMemoryApprovalStore; import org.springframework.security.oauth2.provider.token.AccessTokenConverter; +import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter; /** * @author Dave Syer @@ -43,8 +44,9 @@ public class JwtTokenStoreTests { private InMemoryApprovalStore approvalStore = new InMemoryApprovalStore(); - private OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request(null, "id", null, true, - Collections.singleton("read"), null, null, null, null); + private OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request( + Collections.singletonMap("grant_type", "password"), "id", null, true, Collections.singleton("read"), null, + null, null, null); private OAuth2Authentication expectedAuthentication = new OAuth2Authentication(storedOAuth2Request, new TestAuthentication("test", true)); @@ -143,6 +145,16 @@ public void testReadAuthenticationFromString() throws Exception { tokenStore.readAuthentication(expectedOAuth2AccessToken.getValue())); } + @Test + public void testAuthenticationPreservesGrantType() throws Exception { + DefaultAccessTokenConverter delegate = new DefaultAccessTokenConverter(); + delegate.setIncludeGrantType(true); + enhancer.setAccessTokenConverter(delegate); + expectedOAuth2AccessToken = enhancer.enhance(new DefaultOAuth2AccessToken("FOO"), expectedAuthentication); + OAuth2Authentication authentication = tokenStore.readAuthentication(expectedOAuth2AccessToken.getValue()); + assertEquals("password", authentication.getOAuth2Request().getGrantType()); + } + @Test public void testReadAuthenticationForRefreshToken() throws Exception { checkAuthentications(expectedAuthentication, From 27a2b2513635a98642f62599677f9e9480507f26 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 16 Feb 2015 17:22:38 +0000 Subject: [PATCH 387/831] New public methods in OAuth2Request identify a refresh token request Provided you use a DefaultTokenServices then the TokenEnhancer can now be certain that it is enhancing a token that was refreshed. There's a boolean method isRefresh() and full access to the TokenRequest in case there's anything useful in there as well (e.g. the requested scopes). Fixes gh-405 --- .../oauth2/provider/OAuth2Request.java | 36 +++++++++++++++++-- .../provider/token/DefaultTokenServices.java | 14 ++++---- .../AbstractDefaultTokenServicesTests.java | 26 +++++++++++--- 3 files changed, 64 insertions(+), 12 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java index fd6eff9c7..2678ce5b9 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Request.java @@ -39,6 +39,12 @@ public class OAuth2Request extends BaseRequest implements Serializable { */ private boolean approved = false; + /** + * Will be non-null if the request is for a token to be refreshed (the original grant type might still be available + * via {@link #getGrantType()}). + */ + private TokenRequest refresh = null; + /** * The resolved redirect URI of this request. A URI may be present in the original request, in the * authorizationParameters, or it may not be provided, in which case it will be defaulted (by processing classes) to @@ -138,8 +144,34 @@ public OAuth2Request createOAuth2Request(Map parameters) { * @return a new request with the narrowed scope */ public OAuth2Request narrowScope(Set scope) { - return new OAuth2Request(getRequestParameters(), getClientId(), authorities, approved, scope, resourceIds, - redirectUri, responseTypes, extensions); + OAuth2Request request = new OAuth2Request(getRequestParameters(), getClientId(), authorities, approved, scope, + resourceIds, redirectUri, responseTypes, extensions); + request.refresh = this.refresh; + return request; + } + + public OAuth2Request refresh(TokenRequest tokenRequest) { + OAuth2Request request = new OAuth2Request(getRequestParameters(), getClientId(), authorities, approved, + getScope(), resourceIds, redirectUri, responseTypes, extensions); + request.refresh = tokenRequest; + return request; + } + + /** + * @return true if this request is known to be for a token to be refreshed + */ + public boolean isRefresh() { + return refresh != null; + } + + /** + * If this request was for an access token to be refreshed, then the {@link TokenRequest} that led to the refresh + * may be available here if it is known. + * + * @return the refresh token request (may be null) + */ + public TokenRequest getRefreshTokenRequest() { + return refresh; } /** diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java index d19093b48..2e1956c2b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java @@ -151,7 +151,7 @@ public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, TokenReque throw new InvalidTokenException("Invalid refresh token (expired): " + refreshToken); } - authentication = createRefreshedAuthentication(authentication, tokenRequest.getScope()); + authentication = createRefreshedAuthentication(authentication, tokenRequest); if (!reuseRefreshToken) { tokenStore.removeRefreshToken(refreshToken); @@ -178,20 +178,21 @@ public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) { * @return The refreshed authentication. * @throws InvalidScopeException If the scope requested is invalid or wider than the original scope. */ - private OAuth2Authentication createRefreshedAuthentication(OAuth2Authentication authentication, Set scope) { + private OAuth2Authentication createRefreshedAuthentication(OAuth2Authentication authentication, TokenRequest request) { OAuth2Authentication narrowed = authentication; + Set scope = request.getScope(); + OAuth2Request clientAuth = authentication.getOAuth2Request().refresh(request); if (scope != null && !scope.isEmpty()) { - OAuth2Request clientAuth = authentication.getOAuth2Request(); Set originalScope = clientAuth.getScope(); if (originalScope == null || !originalScope.containsAll(scope)) { throw new InvalidScopeException("Unable to narrow the scope of the client authentication to " + scope + ".", originalScope); } else { - narrowed = new OAuth2Authentication(clientAuth.narrowScope(scope), - authentication.getUserAuthentication()); + clientAuth = clientAuth.narrowScope(scope); } } + narrowed = new OAuth2Authentication(clientAuth, authentication.getUserAuthentication()); return narrowed; } @@ -340,7 +341,8 @@ public void setTokenEnhancer(TokenEnhancer accessTokenEnhancer) { } /** - * The validity (in seconds) of the refresh token. If less than or equal to zero then the tokens will be non-expiring. + * The validity (in seconds) of the refresh token. If less than or equal to zero then the tokens will be + * non-expiring. * * @param refreshTokenValiditySeconds The validity (in seconds) of the refresh token. */ diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractDefaultTokenServicesTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractDefaultTokenServicesTests.java index 40207ea5f..3f10b428a 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractDefaultTokenServicesTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractDefaultTokenServicesTests.java @@ -91,8 +91,7 @@ public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exceptio return client; } }); - OAuth2AccessToken token = getTokenServices() - .createAccessToken(createAuthentication()); + OAuth2AccessToken token = getTokenServices().createAccessToken(createAuthentication()); deleted.set(true); OAuth2Authentication authentication = getTokenServices().loadAuthentication(token.getValue()); assertNotNull(authentication.getOAuth2Request()); @@ -120,6 +119,25 @@ public void testRefreshedTokenHasNarrowedScopes() throws Exception { assertEquals("[read]", refreshedAccessToken.getScope().toString()); } + @Test + public void testRefreshTokenRequestHasRefreshFlag() throws Exception { + ExpiringOAuth2RefreshToken expectedExpiringRefreshToken = (ExpiringOAuth2RefreshToken) getTokenServices() + .createAccessToken(createAuthentication()).getRefreshToken(); + TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap("client_id", "id"), "id", + Collections.singleton("read"), null); + final AtomicBoolean called = new AtomicBoolean(false); + getTokenServices().setTokenEnhancer(new TokenEnhancer() { + @Override + public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { + assertTrue(authentication.getOAuth2Request().isRefresh()); + called.set(true); + return accessToken; + } + }); + getTokenServices().refreshAccessToken(expectedExpiringRefreshToken.getValue(), tokenRequest); + assertTrue(called.get()); + } + @Test public void testTokenRevoked() throws Exception { OAuth2Authentication authentication = createAuthentication(); @@ -170,8 +188,8 @@ public void testRefreshedTokenHasScopes() throws Exception { @Test public void testRefreshedTokenNotExpiring() throws Exception { getTokenServices().setRefreshTokenValiditySeconds(0); - OAuth2RefreshToken expectedExpiringRefreshToken = getTokenServices() - .createAccessToken(createAuthentication()).getRefreshToken(); + OAuth2RefreshToken expectedExpiringRefreshToken = getTokenServices().createAccessToken(createAuthentication()) + .getRefreshToken(); assertFalse(expectedExpiringRefreshToken instanceof DefaultExpiringOAuth2RefreshToken); } From 2d9e43e226d18ef91cfbb5cab6c2b7291b5ee166 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 17 Feb 2015 08:48:58 +0000 Subject: [PATCH 388/831] Use seconds internally instead of milliseconds Since Calender.add() takes int parameters we need to deal in seconds not milliseconds in order to support long expiry (beyond Integer.MAX_VALUE seconds). Fixes gh-341 --- .../approval/ApprovalStoreUserApprovalHandler.java | 8 ++++---- .../ApprovalStoreUserApprovalHandlerTests.java | 13 ++++++++++--- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java index 63b423370..2de20cb9e 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java @@ -52,7 +52,7 @@ public class ApprovalStoreUserApprovalHandler implements UserApprovalHandler, In private ApprovalStore approvalStore; - private int approvalExpiryInMillis = -1; + private int approvalExpirySeconds = -1; private ClientDetailsService clientDetailsService; @@ -88,7 +88,7 @@ public void setRequestFactory(OAuth2RequestFactory requestFactory) { } public void setApprovalExpiryInSeconds(int approvalExpirySeconds) { - this.approvalExpiryInMillis = approvalExpirySeconds * 1000; + this.approvalExpirySeconds = approvalExpirySeconds; } public void afterPropertiesSet() { @@ -166,11 +166,11 @@ public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizati private Date computeExpiry() { Calendar expiresAt = Calendar.getInstance(); - if (approvalExpiryInMillis == -1) { // use default of 1 month + if (approvalExpirySeconds == -1) { // use default of 1 month expiresAt.add(Calendar.MONTH, 1); } else { - expiresAt.add(Calendar.MILLISECOND, approvalExpiryInMillis); + expiresAt.add(Calendar.SECOND, approvalExpirySeconds); } return expiresAt.getTime(); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandlerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandlerTests.java index 6129a203b..c4ff4dfcb 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandlerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandlerTests.java @@ -1,8 +1,6 @@ package org.springframework.security.oauth2.provider.approval; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; import java.util.Arrays; import java.util.Collection; @@ -44,6 +42,15 @@ public void init() { userAuthentication = new UsernamePasswordAuthenticationToken("user", "N/A", AuthorityUtils.commaSeparatedStringToAuthorityList("USER")); } + + @Test + public void testApprovalLongExpiry() throws Exception { + handler.setApprovalExpiryInSeconds(365*24*60*60); + AuthorizationRequest authorizationRequest = new AuthorizationRequest("client", Arrays.asList("read")); + authorizationRequest.setApprovalParameters(Collections.singletonMap("scope.read", "approved")); + AuthorizationRequest result = handler.updateAfterApproval(authorizationRequest, userAuthentication); + assertTrue(handler.isApproved(result, userAuthentication)); + } @Test public void testExplicitlyApprovedScopes() { From d2097aaebf96fce13ecac03a3fc8218f791955c2 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 18 Feb 2015 10:25:02 +0000 Subject: [PATCH 389/831] Update tests to Spring Boot 1.2.1 Fixes gh-406 --- .../common/AbstractProtectedResourceTests.java | 16 +++++++++------- .../mappings/src/main/java/demo/Application.java | 4 ++-- tests/annotation/pom.xml | 2 +- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/tests/annotation/common/src/main/java/sparklr/common/AbstractProtectedResourceTests.java b/tests/annotation/common/src/main/java/sparklr/common/AbstractProtectedResourceTests.java index 2e28fff86..7e37f24d9 100644 --- a/tests/annotation/common/src/main/java/sparklr/common/AbstractProtectedResourceTests.java +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractProtectedResourceTests.java @@ -30,22 +30,24 @@ public abstract class AbstractProtectedResourceTests extends AbstractIntegration public void testHomePageIsProtected() throws Exception { ResponseEntity response = http.getForString("/"); assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); - assertTrue("Wrong header: " + response.getHeaders(), response.getHeaders().getFirst("WWW-Authenticate") - .startsWith("Bearer realm=")); + assertTrue("Wrong header: " + response.getHeaders(), response.getHeaders() + .getFirst("WWW-Authenticate").startsWith("Bearer realm=")); } @Test public void testBeansResourceIsProtected() throws Exception { ResponseEntity response = http.getForString("/admin/beans"); assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); - assertTrue("Wrong header: " + response.getHeaders(), response.getHeaders().getFirst("WWW-Authenticate") - .startsWith("Bearer realm=")); + assertTrue("Wrong header: " + response.getHeaders(), response.getHeaders() + .getFirst("WWW-Authenticate").startsWith("Bearer realm=")); } @Test - public void testHealthResourceIsOpen() throws Exception { - assertEquals(HttpStatus.OK, http.getStatusCode("/admin/health")); + public void testHealthResourceIsSecure() throws Exception { + // In Spring Boot 1.2 the /health endpoint is not open by default, but does allow + // anonymous access. When we add the OAuth2 layer we don't know about Boot + // endpoints, so the default has to be a 401. + assertEquals(HttpStatus.UNAUTHORIZED, http.getStatusCode("/admin/health")); } - } diff --git a/tests/annotation/mappings/src/main/java/demo/Application.java b/tests/annotation/mappings/src/main/java/demo/Application.java index b004a55ad..d7addad6b 100644 --- a/tests/annotation/mappings/src/main/java/demo/Application.java +++ b/tests/annotation/mappings/src/main/java/demo/Application.java @@ -43,8 +43,8 @@ protected static class ResourceServer extends ResourceServerConfigurerAdapter { public void configure(HttpSecurity http) throws Exception { // @formatter:off http - // Just for laughs, apply OAuth protection to only 2 resources - .requestMatchers().antMatchers("/","/admin/beans") + // Just for laughs, apply OAuth protection to only 3 resources + .requestMatchers().antMatchers("/","/admin/beans","/admin/health") .and() .authorizeRequests() .anyRequest().access("#oauth2.hasScope('read')"); diff --git a/tests/annotation/pom.xml b/tests/annotation/pom.xml index 054da3e49..bd631bb36 100644 --- a/tests/annotation/pom.xml +++ b/tests/annotation/pom.xml @@ -26,7 +26,7 @@ org.springframework.boot spring-boot-starter-parent - 1.1.9.RELEASE + 1.2.1.RELEASE From 82ca381dbccdb8bb12df1d31d53105c88ff3dbd8 Mon Sep 17 00:00:00 2001 From: Holger Schmeisky Date: Wed, 11 Feb 2015 09:32:23 +0100 Subject: [PATCH 390/831] Use less aggressive check for existing beans to prevent early factory bean instantiation Fixes gh-398, fixes gh-384 --- .../AuthorizationServerEndpointsConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 163edd923..89ffb22bd 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 @@ -198,7 +198,7 @@ protected static class TokenKeyEndpointRegistrar implements BeanDefinitionRegist @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { String[] names = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, - JwtAccessTokenConverter.class); + JwtAccessTokenConverter.class, false, false); if (names.length > 0) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(TokenKeyEndpoint.class); builder.addConstructorArgReference(names[0]); From c1b5aff623de328f30ca13749c6acc303cf17531 Mon Sep 17 00:00:00 2001 From: linuschien Date: Mon, 16 Feb 2015 12:26:48 +0800 Subject: [PATCH 391/831] Duplicated query parameters cause invalid signature Fixes gh-403 --- .../oauth/consumer/client/OAuthClientHttpRequestFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/client/OAuthClientHttpRequestFactory.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/client/OAuthClientHttpRequestFactory.java index 1ee398580..16fe430f2 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/client/OAuthClientHttpRequestFactory.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/client/OAuthClientHttpRequestFactory.java @@ -52,7 +52,7 @@ public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IO if (!useAuthHeader) { String queryString = this.support.getOAuthQueryString(this.resource, accessToken, uri.toURL(), httpMethod.name(), this.additionalOAuthParameters); String uriValue = String.valueOf(uri); - uri = URI.create(uriValue.contains("?") ? uriValue + "&" + queryString : uriValue + "?" + queryString); + uri = URI.create((uriValue.contains("?") ? uriValue.substring(0, uriValue.indexOf('?')) : uriValue) + "?" + queryString); } ClientHttpRequest req = delegate.createRequest(uri, httpMethod); From e2149951aef158a2c0eccba5f4af2a41ed510fad Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 18 Feb 2015 11:43:50 +0000 Subject: [PATCH 392/831] Suppress compiler warnings --- .../provider/client/ClientDetailsUserDetailsServiceTests.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/ClientDetailsUserDetailsServiceTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/ClientDetailsUserDetailsServiceTests.java index dcee49682..ede103a46 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/ClientDetailsUserDetailsServiceTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/ClientDetailsUserDetailsServiceTests.java @@ -29,6 +29,7 @@ */ public class ClientDetailsUserDetailsServiceTests { + @SuppressWarnings("unchecked") @Test(expected = UsernameNotFoundException.class) public void shouldThrowUsernameNotFoundExceptionWhenNoSuchClient() throws Exception { @@ -42,6 +43,7 @@ public void shouldThrowUsernameNotFoundExceptionWhenNoSuchClient() throws Except testee.loadUserByUsername("test_user"); } + @SuppressWarnings("unchecked") @Test(expected = ClientRegistrationException.class) public void shouldConductOriginalException() throws Exception { From e303652a911cf0168b5be68383ac120c23ec63b3 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 19 Feb 2015 10:51:25 +0000 Subject: [PATCH 393/831] Add AuthenticationManager to default token services So that it can be used to check user account changes in a refresh token grant. If a global UserDetailsService is available it will be used as a default (e.g. if user has a GlobalAuthenticationConfigurer). It works by constructing a PreAuthenticationAuthenticationProvider and using that the authenticate the user in DefaultTokenServices. To customize that process, users can create their own DefaultTokenServices and inject an AuthenticationManager. Fixes gh-401 --- docs/oauth2.md | 1 + ...horizationServerSecurityConfiguration.java | 5 ++ ...uthorizationServerEndpointsConfigurer.java | 49 ++++++++++++++++++- .../provider/refresh/RefreshTokenGranter.java | 2 +- .../provider/token/DefaultTokenServices.java | 24 +++++++++ ...AuthorizationServerConfigurationTests.java | 36 ++++++++++++++ ...DefaultTokenServicesWithInMemoryTests.java | 23 +++++++++ tests/annotation/pom.xml | 2 +- .../src/main/java/demo/Application.java | 8 +-- tests/xml/pom.xml | 2 +- 10 files changed, 143 insertions(+), 9 deletions(-) diff --git a/docs/oauth2.md b/docs/oauth2.md index a97d830d2..fea6aee9d 100644 --- a/docs/oauth2.md +++ b/docs/oauth2.md @@ -85,6 +85,7 @@ all grant types are supported except password (see below for details of how to s following properties affect grant types: * `authenticationManager`: password grants are switched on by injecting an `AuthenticationManager`. +* `userDetailsService`: if you inject a `UserDetailsService` or if one is configured globally anyway (e.g. in a `GlobalAuthenticationManagerConfigurer`) then a refresh token grant will contain a check on the user details, to ensure that the account is still active * `authorizationCodeServices`: defines the authorization code services (instance of `AuthorizationCodeServices`) for the auth code grant. * `implicitGrantService`: manages state during the imlpicit grant. * `tokenGranter`: the `TokenGranter` (taking full control of the granting and ignoring the other properties above) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java index 7c996de17..02fcedd67 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java @@ -25,6 +25,7 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.oauth2.config.annotation.configuration.ClientDetailsServiceConfiguration; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; @@ -67,6 +68,10 @@ protected void configure(HttpSecurity http) throws Exception { String tokenEndpointPath = handlerMapping.getServletPath("/oauth/token"); String tokenKeyPath = handlerMapping.getServletPath("/oauth/token_key"); String checkTokenPath = handlerMapping.getServletPath("/oauth/check_token"); + if (!endpoints.getEndpointsConfigurer().isUserDetailsServiceOverride()) { + UserDetailsService userDetailsService = http.getSharedObject(UserDetailsService.class); + endpoints.getEndpointsConfigurer().userDetailsService(userDetailsService); + } // @formatter:off http .authorizeRequests() 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 3f92e9388..efc166ec3 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,10 +15,21 @@ */ package org.springframework.security.oauth2.config.annotation.web.configurers; -import java.util.*; +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.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.authentication.ProviderManager; +import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper; +import org.springframework.security.core.userdetails.UserDetailsService; 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; @@ -55,6 +66,8 @@ 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; +import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider; +import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken; import org.springframework.web.context.request.WebRequestInterceptor; import org.springframework.web.servlet.HandlerInterceptor; @@ -109,8 +122,12 @@ public final class AuthorizationServerEndpointsConfigurer { private DefaultTokenServices defaultTokenServices; + private UserDetailsService userDetailsService; + private boolean tokenServicesOverride = false; + private boolean userDetailsServiceOverride = false; + private boolean reuseRefreshToken = true; private WebResponseExceptionTranslator exceptionTranslator; @@ -173,13 +190,19 @@ public AuthorizationServerEndpointsConfigurer accessTokenConverter(AccessTokenCo public AuthorizationServerEndpointsConfigurer tokenServices(AuthorizationServerTokenServices tokenServices) { this.tokenServices = tokenServices; - this.tokenServicesOverride = true; + if (tokenServices!=null) { + this.tokenServicesOverride = true; + } return this; } public boolean isTokenServicesOverride() { return tokenServicesOverride; } + + public boolean isUserDetailsServiceOverride() { + return userDetailsServiceOverride; + } public AuthorizationServerEndpointsConfigurer userApprovalHandler(UserApprovalHandler approvalHandler) { this.userApprovalHandler = approvalHandler; @@ -269,6 +292,14 @@ public AuthorizationServerEndpointsConfigurer allowedTokenEndpointRequestMethods return this; } + public AuthorizationServerEndpointsConfigurer userDetailsService(UserDetailsService userDetailsService) { + if (userDetailsService != null) { + this.userDetailsService = userDetailsService; + this.userDetailsServiceOverride = true; + } + return this; + } + public ConsumerTokenServices getConsumerTokenServices() { return consumerTokenServices(); } @@ -352,6 +383,7 @@ private DefaultTokenServices createDefaultTokenServices() { tokenServices.setReuseRefreshToken(reuseRefreshToken); tokenServices.setClientDetailsService(clientDetailsService()); tokenServices.setTokenEnhancer(tokenEnhancer()); + addUserDetailsService(tokenServices, this.userDetailsService); return tokenServices; } @@ -398,9 +430,22 @@ private ClientDetailsService clientDetailsService() { if (clientDetailsService == null) { this.clientDetailsService = new InMemoryClientDetailsService(); } + if (this.defaultTokenServices != null) { + addUserDetailsService(defaultTokenServices, userDetailsService); + } return this.clientDetailsService; } + private void addUserDetailsService(DefaultTokenServices tokenServices, UserDetailsService userDetailsService) { + if (userDetailsService != null) { + PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider(); + provider.setPreAuthenticatedUserDetailsService(new UserDetailsByNameServiceWrapper( + userDetailsService)); + tokenServices.setAuthenticationManager( + new ProviderManager(Arrays. asList(provider))); + } + } + private UserApprovalHandler userApprovalHandler() { if (userApprovalHandler == null) { if (approvalStore() != null) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/refresh/RefreshTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/refresh/RefreshTokenGranter.java index 4ea82a4e5..f9ee74347 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/refresh/RefreshTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/refresh/RefreshTokenGranter.java @@ -41,5 +41,5 @@ protected OAuth2AccessToken getAccessToken(ClientDetails client, TokenRequest to String refreshToken = tokenRequest.getRequestParameters().get("refresh_token"); return getTokenServices().refreshAccessToken(refreshToken, tokenRequest); } - + } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java index 2e1956c2b..69d3eb2be 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java @@ -18,6 +18,8 @@ import java.util.UUID; import org.springframework.beans.factory.InitializingBean; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.oauth2.common.DefaultExpiringOAuth2RefreshToken; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; @@ -34,6 +36,7 @@ import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.TokenRequest; +import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.Assert; @@ -67,6 +70,8 @@ public class DefaultTokenServices implements AuthorizationServerTokenServices, R private TokenEnhancer accessTokenEnhancer; + private AuthenticationManager authenticationManager; + /** * Initialize these token services. If no random generator is set, one will be created. */ @@ -137,6 +142,15 @@ public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, TokenReque } OAuth2Authentication authentication = tokenStore.readAuthenticationForRefreshToken(refreshToken); + if (this.authenticationManager != null && !authentication.isClientOnly()) { + // The client has already been authenticated, but the user authentication might be old now, so give it a + // chance to re-authenticate. + Authentication user = new PreAuthenticatedAuthenticationToken(authentication.getUserAuthentication(), "", authentication.getAuthorities()); + user = authenticationManager.authenticate(user); + Object details = authentication.getDetails(); + authentication = new OAuth2Authentication(authentication.getOAuth2Request(), user); + authentication.setDetails(details); + } String clientId = authentication.getOAuth2Request().getClientId(); if (clientId == null || !clientId.equals(tokenRequest.getClientId())) { throw new InvalidGrantException("Wrong client for this refresh token: " + refreshTokenValue); @@ -388,6 +402,16 @@ public void setTokenStore(TokenStore tokenStore) { this.tokenStore = tokenStore; } + /** + * An authentication manager that will be used (if provided) to check the user authentication when a token is + * refreshed. + * + * @param authenticationManager the authenticationManager to set + */ + public void setAuthenticationManager(AuthenticationManager authenticationManager) { + this.authenticationManager = authenticationManager; + } + /** * The client details service to use for looking up clients (if necessary). Optional if the access token expiry is * set globally via {@link #setAccessTokenValiditySeconds(int)}. diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java index c193ccae1..e657875c9 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java @@ -41,6 +41,11 @@ import org.springframework.mock.web.MockServletContext; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; @@ -593,4 +598,35 @@ public void run() { } + @Configuration + @EnableWebMvcSecurity + @EnableAuthorizationServer + protected static class AuthorizationServerCustomUserDetails extends AuthorizationServerConfigurerAdapter + implements Runnable { + + @Autowired + private ApplicationContext context; + + @Override + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + endpoints.userDetailsService(userDetailsService()); + } + + private UserDetailsService userDetailsService() { + return new UserDetailsService() { + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + return new User(username, "", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); + } + }; + } + + @Override + public void run() { + assertNotNull(context.getBean(UserDetailsService.class)); + } + + } + } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithInMemoryTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithInMemoryTests.java index 18f4e8feb..4a292594d 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithInMemoryTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithInMemoryTests.java @@ -13,6 +13,10 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.springframework.security.authentication.AccountExpiredException; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; @@ -70,6 +74,25 @@ public void testExpiredRefreshToken() throws Exception { getTokenServices().refreshAccessToken(firstAccessToken.getRefreshToken().getValue(), tokenRequest); } + @Test + public void testRefreshTokenWithUnauthenticatedUser() throws Exception { + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request( + "id", false, Collections.singleton("read")), new TestAuthentication("test2", false)); + getTokenServices().setAuthenticationManager(new AuthenticationManager() { + + @Override + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + throw new AccountExpiredException("Not valid"); + } + }); + DefaultOAuth2AccessToken firstAccessToken = (DefaultOAuth2AccessToken) getTokenServices().createAccessToken( + expectedAuthentication); + assertNotNull(firstAccessToken.getRefreshToken()); + expected.expect(AccountExpiredException.class); + TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap("client_id", "id"), "id", null, null); + getTokenServices().refreshAccessToken(firstAccessToken.getRefreshToken().getValue(), tokenRequest); + } + @Test public void testExpiredRefreshTokenIsRenewedWithNewAccessToken() throws Exception { OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request( diff --git a/tests/annotation/pom.xml b/tests/annotation/pom.xml index bd631bb36..7c3f71694 100644 --- a/tests/annotation/pom.xml +++ b/tests/annotation/pom.xml @@ -26,7 +26,7 @@ org.springframework.boot spring-boot-starter-parent - 1.2.1.RELEASE + 1.2.2.BUILD-SNAPSHOT diff --git a/tests/annotation/vanilla/src/main/java/demo/Application.java b/tests/annotation/vanilla/src/main/java/demo/Application.java index a2be1c356..891e601fb 100644 --- a/tests/annotation/vanilla/src/main/java/demo/Application.java +++ b/tests/annotation/vanilla/src/main/java/demo/Application.java @@ -33,9 +33,9 @@ public String home() { return "Hello World"; } - @RequestMapping(value="/", method=RequestMethod.POST) + @RequestMapping(value = "/", method = RequestMethod.POST) @ResponseStatus(HttpStatus.CREATED) - public String create(@RequestBody MultiValueMap map) { + public String create(@RequestBody MultiValueMap map) { return "OK"; } @@ -45,12 +45,12 @@ protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter @Autowired private AuthenticationManager authenticationManager; - + @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.authenticationManager(authenticationManager); } - + @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { // @formatter:off diff --git a/tests/xml/pom.xml b/tests/xml/pom.xml index 07cce72d0..beff5eddd 100644 --- a/tests/xml/pom.xml +++ b/tests/xml/pom.xml @@ -24,7 +24,7 @@ org.springframework.boot spring-boot-starter-parent - 1.1.9.RELEASE + 1.2.2.BUILD-SNAPSHOT From 6620619b5f1e7a61c10c0de19af9d2634ebdaace Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 19 Feb 2015 13:22:07 +0000 Subject: [PATCH 394/831] Add JsonParser utility interface so that JWT can choose one At runtime Jackson (1) might not be available on the classpath and up to now the JwtAccessTokenConverter relied on it coming from spring-security-jwt transitively. The latest version of that library no longer requires an external JSON parser, so we need a way to choose a converter/parser at runtime. Fixes gh-391 --- .../common/util/Jackson2JsonParser.java | 51 +++++++++++++++++++ .../oauth2/common/util/JacksonJsonParser.java | 49 ++++++++++++++++++ .../oauth2/common/util/JsonParser.java | 38 ++++++++++++++ .../oauth2/common/util/JsonParserFactory.java | 34 +++++++++++++ .../token/store/JwtAccessTokenConverter.java | 10 ++-- tests/annotation/pom.xml | 2 +- tests/xml/pom.xml | 2 +- 7 files changed, 179 insertions(+), 7 deletions(-) create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/Jackson2JsonParser.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JacksonJsonParser.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JsonParser.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JsonParserFactory.java diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/Jackson2JsonParser.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/Jackson2JsonParser.java new file mode 100644 index 000000000..e755a9bdf --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/Jackson2JsonParser.java @@ -0,0 +1,51 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.springframework.security.oauth2.common.util; + +import java.util.Map; + +import com.fasterxml.jackson.databind.ObjectMapper; + + + +/** + * @author Dave Syer + * + */ +public class Jackson2JsonParser implements JsonParser { + + private ObjectMapper mapper = new ObjectMapper(); + + @SuppressWarnings("unchecked") + @Override + public Map parseMap(String json) { + try { + return mapper.readValue(json, Map.class); + } + catch (Exception e) { + throw new IllegalArgumentException("Cannot parse json", e); + } + } + + @Override + public String formatMap(Map map) { + try { + return mapper.writeValueAsString(map); + } + catch (Exception e) { + throw new IllegalArgumentException("Cannot format json", e); + } + } + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JacksonJsonParser.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JacksonJsonParser.java new file mode 100644 index 000000000..de8605c17 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JacksonJsonParser.java @@ -0,0 +1,49 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.springframework.security.oauth2.common.util; + +import java.util.Map; + +import org.codehaus.jackson.map.ObjectMapper; + +/** + * @author Dave Syer + * + */ +public class JacksonJsonParser implements JsonParser { + + private ObjectMapper mapper = new ObjectMapper(); + + @SuppressWarnings("unchecked") + @Override + public Map parseMap(String json) { + try { + return mapper.readValue(json, Map.class); + } + catch (Exception e) { + throw new IllegalArgumentException("Cannot parse json", e); + } + } + + @Override + public String formatMap(Map map) { + try { + return mapper.writeValueAsString(map); + } + catch (Exception e) { + throw new IllegalArgumentException("Cannot format json", e); + } + } + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JsonParser.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JsonParser.java new file mode 100644 index 000000000..386cefd72 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JsonParser.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.springframework.security.oauth2.common.util; + +import java.util.Map; + +/** + * @author Dave Syer + * + */ +public interface JsonParser { + + /** + * Parse the specified JSON string into a Map. + * @param json the JSON to parse + * @return the parsed JSON as a map + */ + Map parseMap(String json); + + /** + * Convert the Map to JSON + * @param map a map to format + * @return a JSON representation of the map + */ + String formatMap(Map map); + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JsonParserFactory.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JsonParserFactory.java new file mode 100644 index 000000000..775a84379 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JsonParserFactory.java @@ -0,0 +1,34 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.springframework.security.oauth2.common.util; + +import org.springframework.util.ClassUtils; + +/** + * @author Dave Syer + * + */ +public class JsonParserFactory { + + public static JsonParser create() { + if (ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", null)) { + return new Jackson2JsonParser(); + } + if (ClassUtils.isPresent("org.codehaus.jackson.map.ObjectMapper", null)) { + return new JacksonJsonParser(); + } + throw new IllegalStateException("No Jackson parser found. Please add Jackson to your classpath."); + } + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java index d9906f67d..9f792d700 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java @@ -22,7 +22,6 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.codehaus.jackson.map.ObjectMapper; import org.springframework.beans.factory.InitializingBean; import org.springframework.security.crypto.codec.Base64; import org.springframework.security.jwt.Jwt; @@ -40,6 +39,8 @@ import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2RefreshToken; 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.common.util.RandomValueStringGenerator; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.token.AccessTokenConverter; @@ -73,7 +74,7 @@ public class JwtAccessTokenConverter implements TokenEnhancer, AccessTokenConver private AccessTokenConverter tokenConverter = new DefaultAccessTokenConverter(); - private ObjectMapper objectMapper = new ObjectMapper(); + private JsonParser objectMapper = JsonParserFactory.create(); private String verifierKey = new RandomValueStringGenerator().generate(); @@ -225,7 +226,7 @@ public boolean isRefreshToken(OAuth2AccessToken token) { protected String encode(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { String content; try { - content = objectMapper.writeValueAsString(tokenConverter.convertAccessToken(accessToken, authentication)); + content = objectMapper.formatMap(tokenConverter.convertAccessToken(accessToken, authentication)); } catch (Exception e) { throw new IllegalStateException("Cannot convert access token to JSON", e); @@ -238,8 +239,7 @@ protected Map decode(String token) { try { Jwt jwt = JwtHelper.decodeAndVerify(token, verifier); String content = jwt.getClaims(); - @SuppressWarnings("unchecked") - Map map = objectMapper.readValue(content, Map.class); + Map map = objectMapper.parseMap(content); if (map.containsKey(EXP) && map.get(EXP) instanceof Integer) { Integer intValue = (Integer) map.get(EXP); map.put(EXP, new Long(intValue)); diff --git a/tests/annotation/pom.xml b/tests/annotation/pom.xml index 7c3f71694..2e1e0ee1d 100644 --- a/tests/annotation/pom.xml +++ b/tests/annotation/pom.xml @@ -45,7 +45,7 @@ org.springframework.security spring-security-jwt - 1.0.2.RELEASE + 1.0.3.RELEASE diff --git a/tests/xml/pom.xml b/tests/xml/pom.xml index beff5eddd..4e3d67043 100644 --- a/tests/xml/pom.xml +++ b/tests/xml/pom.xml @@ -43,7 +43,7 @@ org.springframework.security spring-security-jwt - 1.0.2.RELEASE + 1.0.3.RELEASE From 02c8afd65f04879204577a052f3ee760e5449416 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 19 Feb 2015 14:13:28 +0000 Subject: [PATCH 395/831] Move @Transactional down to method level in DefaultTokenServices It didn't make sense for all methods, and for the refresh token case you also need to set different rollback rules to avoid the data being unchanged after a failed grant. Fixes gh-399 --- .../security/oauth2/provider/token/DefaultTokenServices.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java index 69d3eb2be..9faf6d6e8 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java @@ -52,7 +52,6 @@ * @author Luke Taylor * @author Dave Syer */ -@Transactional public class DefaultTokenServices implements AuthorizationServerTokenServices, ResourceServerTokenServices, ConsumerTokenServices, InitializingBean { @@ -79,6 +78,7 @@ public void afterPropertiesSet() throws Exception { Assert.notNull(tokenStore, "tokenStore must be set"); } + @Transactional public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication) throws AuthenticationException { OAuth2AccessToken existingAccessToken = tokenStore.getAccessToken(authentication); @@ -129,6 +129,7 @@ else if (refreshToken instanceof ExpiringOAuth2RefreshToken) { } + @Transactional(noRollbackFor={InvalidTokenException.class, InvalidGrantException.class}) public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, TokenRequest tokenRequest) throws AuthenticationException { From b6e901244678825f2e0b220d9aeb016118f2282d Mon Sep 17 00:00:00 2001 From: Lars Vonk Date: Tue, 10 Feb 2015 15:53:13 +0100 Subject: [PATCH 396/831] Tutorial fixes in README Fixes gh-395. Sample apps use tomcat7 plugin, corrected links to sample apps. --- docs/tutorial.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/tutorial.md b/docs/tutorial.md index c8b01b6d3..a342d94f3 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -52,10 +52,10 @@ You'll also notice the Spring Security filter chain in `applicationContext.xml` {% highlight text %} mvn install cd samples/oauth(2)/sparklr - mvn tomcat:run + mvn tomcat7:run {% endhighlight %} -Sparklr should be started on port 8080. Go ahead and browse to [http;//localhost:8080/sparklr](http;//localhost:8080/sparklr). Note the basic +Sparklr should be started on port 8080. Go ahead and browse to [http://localhost:8080/sparklr](http://localhost:8080/sparklr). Note the basic login page and the page that can be used to browse Marissa's photos. Logout to ensure Marissa's session is no longer valid. (Of course, the logout isn't mandatory; an active Sparklr session will simply bypass the step that prompts for Marissa's credentials before confirming authorization for Marissa's protected resources.) @@ -67,7 +67,7 @@ Shutdown sparklr (it will be launched in the same container when tonr runs), the {% highlight text %} mvn install cd samples/oauth(2)/tonr - mvn tomcat:run + mvn tomcat7:run {% endhighlight %} Tonr should be started on port 8080. Browse to [http://localhost:8080/tonr(2)](http://localhost:8080/tonr). Note Tonr's home page has a '2' on the end if it is the oauth2 version. From 05192c2d22634500d6707ad6e16ebe93c0700ac0 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 23 Feb 2015 12:03:00 +0000 Subject: [PATCH 397/831] More tinkering with encoded query in redirect URI We needed to add another special treatment for query params to only encode the ones coming from the authorization endpoint (unless they were registered as a redirect with special characters). The output is slightly different but the URLs are more correct than before. Fixes gh-404 --- .../endpoint/AuthorizationEndpoint.java | 46 +++++++++---------- .../endpoint/AuthorizationEndpointTests.java | 24 ++++++++-- 2 files changed, 43 insertions(+), 27 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java index 1d88ba5fe..4b2beaee4 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java @@ -65,6 +65,7 @@ import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.View; import org.springframework.web.servlet.view.RedirectView; +import org.springframework.web.util.UriComponents; import org.springframework.web.util.UriComponentsBuilder; /** @@ -406,50 +407,47 @@ private String append(String base, Map query, Map key catch (Exception e) { // ... but allow client registrations to contain hard-coded non-encoded values redirectUri = builder.build().toUri(); + builder = UriComponentsBuilder.fromUri(redirectUri); } template.scheme(redirectUri.getScheme()).port(redirectUri.getPort()).host(redirectUri.getHost()) .userInfo(redirectUri.getUserInfo()).path(redirectUri.getPath()); - StringBuilder values = new StringBuilder(); - for (String key : query.keySet()) { - if (values.length() > 0) { - values.append("&"); - } - String name = key; - if (keys != null && keys.containsKey(key)) { - name = keys.get(key); - } - values.append(name + "={" + key + "}"); - } - if (fragment) { + StringBuilder values = new StringBuilder(); if (redirectUri.getFragment() != null) { String append = redirectUri.getFragment(); + values.append(append); + } + for (String key : query.keySet()) { if (values.length() > 0) { - append = append + "&"; + values.append("&"); + } + String name = key; + if (keys != null && keys.containsKey(key)) { + name = keys.get(key); } - values.insert(0, append); + values.append(name + "={" + key + "}"); } if (values.length() > 0) { template.fragment(values.toString()); } - template.query(redirectUri.getQuery()); + UriComponents encoded = template.build().expand(query).encode(); + builder.fragment(encoded.getFragment()); } else { - if (redirectUri.getQuery() != null) { - String append = redirectUri.getQuery(); - if (values.length() > 0) { - append = append + "&"; + for (String key : query.keySet()) { + String name = key; + if (keys != null && keys.containsKey(key)) { + name = keys.get(key); } - values.insert(0, append); - } - if (values.length() > 0) { - template.query(values.toString()); + template.queryParam(name, "{" + key + "}"); } template.fragment(redirectUri.getFragment()); + UriComponents encoded = template.build().expand(query).encode(); + builder.query(encoded.getQuery()); } - return template.build().expand(query).encode().toUriString(); + return builder.build().toUriString(); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java index ff065ebd5..85a0a6cd6 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java @@ -48,10 +48,12 @@ import org.springframework.security.oauth2.provider.approval.InMemoryApprovalStore; import org.springframework.security.oauth2.provider.client.BaseClientDetails; import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; +import org.springframework.util.MultiValueMap; import org.springframework.web.bind.support.SimpleSessionStatus; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.View; import org.springframework.web.servlet.view.RedirectView; +import org.springframework.web.util.UriComponentsBuilder; /** * @author Dave Syer @@ -199,7 +201,11 @@ public void testAuthorizationCodeWithTrickyQueryParams() throws Exception { Collections.singleton("code"))); View result = endpoint.approveOrDeny(Collections.singletonMap(OAuth2Utils.USER_OAUTH_APPROVAL, "true"), model, sessionStatus, principal); - assertEquals("http://anywhere.com/?foo=b%20%3D&bar=f%20http://anywhere.com?foo=b%20%3D&bar=f%20$&code=thecodecode=thecode", ((RedirectView) result).getUrl()); + String url = ((RedirectView) result).getUrl(); + assertEquals("http://anywhere.com/?foo=b%20=&bar=f%20http://anywhere.com?foo=b%20=&bar=f%20$&code=thecodecode=thecode", url); + MultiValueMap params = UriComponentsBuilder.fromHttpUrl(url).build().getQueryParams(); + assertEquals("[b%20=]", params.get("foo").toString()); + assertEquals("[f%20$]", params.get("bar").toString()); } @Test @@ -214,6 +220,18 @@ public void testAuthorizationCodeWithTrickyEncodedQueryParams() throws Exception assertEquals("http://anywhere.com/path?foo=b%20%3D&bar=f%20http://anywhere.com/path?foo=b%20%3D&bar=f%20$&code=thecodecode=thecode", ((RedirectView) result).getUrl()); } + @Test + public void testAuthorizationCodeWithMoreTrickyEncodedQueryParams() throws Exception { + endpoint.setAuthorizationCodeServices(new StubAuthorizationCodeServices()); + model.put( + "authorizationRequest", + getAuthorizationRequest("foo", "http://anywhere/?t=a%3Db%26ep%3Dtest%2540test.me", null, null, + Collections.singleton("code"))); + View result = endpoint.approveOrDeny(Collections.singletonMap(OAuth2Utils.USER_OAUTH_APPROVAL, "true"), model, + sessionStatus, principal); + assertEquals("http://anywhere/?t=a%3Db%26ep%3Dtest%2540test.me&code=thecode", ((RedirectView) result).getUrl()); + } + @Test public void testAuthorizationCodeError() throws Exception { endpoint.setUserApprovalHandler(new DefaultUserApprovalHandler() { @@ -363,8 +381,8 @@ public boolean isApproved(AuthorizationRequest authorizationRequest, Authenticat return true; } }); - AuthorizationRequest authorizationRequest = getAuthorizationRequest("foo", "http://anywhere.com/", - "mystate", "myscope", Collections.singleton("token")); + AuthorizationRequest authorizationRequest = getAuthorizationRequest("foo", "http://anywhere.com/", "mystate", + "myscope", Collections.singleton("token")); ModelAndView result = endpoint.authorize(model, authorizationRequest.getRequestParameters(), sessionStatus, principal); String url = ((RedirectView) result.getView()).getUrl(); From 2682654022fd1c7ba8b12b28c9cd2a0d04a4b000 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 23 Feb 2015 12:40:32 +0000 Subject: [PATCH 398/831] Clarify a few things in the auth server configuration --- docs/oauth2.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/oauth2.md b/docs/oauth2.md index fea6aee9d..a90370fb5 100644 --- a/docs/oauth2.md +++ b/docs/oauth2.md @@ -115,13 +115,19 @@ N.B. the Authorization endpoint `/oauth/authorize` (or its mapped alternative) s } ``` +> Note: if your Authorization Server is also a Resource Server then there is another security filter chain with lower priority controlling the API resources. Fo those requests to be protected by access tokens you need their paths *not* to be matched by the ones in the main user-facing filter chain, so be sure to include a request matcher that picks out only non-API resources in the `WebSecurityConfigurer` above. + The token endpoint is protected for you by default by Spring OAuth in the `@Configuration` support using HTTP Basic authentication of the client secret. This is not the case in XML (so it should be protected explicitly). In XML the `` element has some attributes that can be used to change the default endpoint URLs in a similar way. +## Customizing the UI + +Most of the Authorization Server endpoints are used primarily by machines, but there are a couple of resource that need a UI and those are the GET for `/oauth/confirm_access` and the HTML response from `/oauth/error`. They are provided using whitelabel implementations in the framework, so most real-world instances of the Authorization Server will want to provide their own so they can control the styling and content. All you need to do is provide a Spring MVC controller with `@RequestMappings` for those endpoints, and the framework defaults will take a lower priority in the dispatcher. In the `/oauth/confirm_access` endpoint you can expect an `AuthorizationRequest` bound to the session carrying all the data needed to seek approval from the user (the default implementation is `WhitelabelApprovalEndpoint` so look there for a starting point to copy). + ## Customizing the Error Handling -Error handling in an Authorization Server uses standard Spring MVC features, namely `@ExceptionHandler` methods in the endpoints themselves. Users can also provide a `WebResponseExceptionTranslator` to the endpoints themselves which is the best way to change the content of the responses as opposed to the way they are rendered. The rendering of exceptions delegates to `HttpMesssageConverters` (which can be added to the MVC configuration) in the case of token endpoint and to the OAuth error view (`/oauth/error`) in the case of teh authorization endpoint. A whitelabel error endpoint is provided, but users probably need to provide a custom implementation (e.g. just add a `@Controller` with `@RequestMapping("/oauth/error")`). +Error handling in an Authorization Server uses standard Spring MVC features, namely `@ExceptionHandler` methods in the endpoints themselves. Users can also provide a `WebResponseExceptionTranslator` to the endpoints themselves which is the best way to change the content of the responses as opposed to the way they are rendered. The rendering of exceptions delegates to `HttpMesssageConverters` (which can be added to the MVC configuration) in the case of token endpoint and to the OAuth error view (`/oauth/error`) in the case of teh authorization endpoint. The whitelabel error endpoint is provided for HTML responses, but users probably need to provide a custom implementation (e.g. just add a `@Controller` with `@RequestMapping("/oauth/error")`). ## Resource Server Configuration From 0f2b6b61f81d652c251edca77056b291df9c5402 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 25 Feb 2015 15:33:50 +0000 Subject: [PATCH 399/831] Can't use application.xml in Spring Boot 1.2 --- tests/xml/approval/src/main/java/demo/Application.java | 2 +- .../src/main/resources/{application.xml => context.xml} | 0 .../xml/client/src/main/java/client/ClientApplication.java | 2 +- .../src/main/resources/{application.xml => context.xml} | 0 .../sparklr/common/AbstractProtectedResourceTests.java | 7 +++++-- tests/xml/form/src/main/java/demo/Application.java | 2 +- .../src/main/resources/{application.xml => context.xml} | 0 tests/xml/jdbc/src/main/java/demo/Application.java | 2 +- .../src/main/resources/{application.xml => context.xml} | 0 tests/xml/jwt/src/main/java/demo/Application.java | 2 +- .../src/main/resources/{application.xml => context.xml} | 0 tests/xml/mappings/src/main/java/demo/Application.java | 2 +- .../src/main/resources/{application.xml => context.xml} | 0 tests/xml/vanilla/src/main/java/demo/Application.java | 2 +- .../src/main/resources/{application.xml => context.xml} | 0 15 files changed, 12 insertions(+), 9 deletions(-) rename tests/xml/approval/src/main/resources/{application.xml => context.xml} (100%) rename tests/xml/client/src/main/resources/{application.xml => context.xml} (100%) rename tests/xml/form/src/main/resources/{application.xml => context.xml} (100%) rename tests/xml/jdbc/src/main/resources/{application.xml => context.xml} (100%) rename tests/xml/jwt/src/main/resources/{application.xml => context.xml} (100%) rename tests/xml/mappings/src/main/resources/{application.xml => context.xml} (100%) rename tests/xml/vanilla/src/main/resources/{application.xml => context.xml} (100%) diff --git a/tests/xml/approval/src/main/java/demo/Application.java b/tests/xml/approval/src/main/java/demo/Application.java index 21372fc31..33c3b0932 100644 --- a/tests/xml/approval/src/main/java/demo/Application.java +++ b/tests/xml/approval/src/main/java/demo/Application.java @@ -45,7 +45,7 @@ @ComponentScan @EnableAutoConfiguration @RestController -@ImportResource("classpath:/application.xml") +@ImportResource("classpath:/context.xml") public class Application { public static void main(String[] args) { diff --git a/tests/xml/approval/src/main/resources/application.xml b/tests/xml/approval/src/main/resources/context.xml similarity index 100% rename from tests/xml/approval/src/main/resources/application.xml rename to tests/xml/approval/src/main/resources/context.xml diff --git a/tests/xml/client/src/main/java/client/ClientApplication.java b/tests/xml/client/src/main/java/client/ClientApplication.java index 202177911..c4ed8d9f8 100644 --- a/tests/xml/client/src/main/java/client/ClientApplication.java +++ b/tests/xml/client/src/main/java/client/ClientApplication.java @@ -18,7 +18,7 @@ @EnableAutoConfiguration @EnableOAuth2Client @RestController -@ImportResource("classpath:/application.xml") +@ImportResource("classpath:/context.xml") public class ClientApplication { public static void main(String[] args) { diff --git a/tests/xml/client/src/main/resources/application.xml b/tests/xml/client/src/main/resources/context.xml similarity index 100% rename from tests/xml/client/src/main/resources/application.xml rename to tests/xml/client/src/main/resources/context.xml diff --git a/tests/xml/common/src/main/java/sparklr/common/AbstractProtectedResourceTests.java b/tests/xml/common/src/main/java/sparklr/common/AbstractProtectedResourceTests.java index 2e28fff86..e267f4430 100644 --- a/tests/xml/common/src/main/java/sparklr/common/AbstractProtectedResourceTests.java +++ b/tests/xml/common/src/main/java/sparklr/common/AbstractProtectedResourceTests.java @@ -43,8 +43,11 @@ public void testBeansResourceIsProtected() throws Exception { } @Test - public void testHealthResourceIsOpen() throws Exception { - assertEquals(HttpStatus.OK, http.getStatusCode("/admin/health")); + public void testHealthResourceIsSecure() throws Exception { + // In Spring Boot 1.2 the /health endpoint is not open by default, but does allow + // anonymous access. When we add the OAuth2 layer we don't know about Boot + // endpoints, so the default has to be a 401. + assertEquals(HttpStatus.UNAUTHORIZED, http.getStatusCode("/admin/health")); } diff --git a/tests/xml/form/src/main/java/demo/Application.java b/tests/xml/form/src/main/java/demo/Application.java index a4beff6fb..321ce8ae3 100644 --- a/tests/xml/form/src/main/java/demo/Application.java +++ b/tests/xml/form/src/main/java/demo/Application.java @@ -40,7 +40,7 @@ @Configuration @ComponentScan @EnableAutoConfiguration -@ImportResource("classpath:/application.xml") +@ImportResource("classpath:/context.xml") @RestController public class Application { diff --git a/tests/xml/form/src/main/resources/application.xml b/tests/xml/form/src/main/resources/context.xml similarity index 100% rename from tests/xml/form/src/main/resources/application.xml rename to tests/xml/form/src/main/resources/context.xml diff --git a/tests/xml/jdbc/src/main/java/demo/Application.java b/tests/xml/jdbc/src/main/java/demo/Application.java index 644912f9f..c6d0dd26b 100644 --- a/tests/xml/jdbc/src/main/java/demo/Application.java +++ b/tests/xml/jdbc/src/main/java/demo/Application.java @@ -45,7 +45,7 @@ @Configuration @EnableAutoConfiguration @RestController -@ImportResource("classpath:/application.xml") +@ImportResource("classpath:/context.xml") public class Application { public static void main(String[] args) { diff --git a/tests/xml/jdbc/src/main/resources/application.xml b/tests/xml/jdbc/src/main/resources/context.xml similarity index 100% rename from tests/xml/jdbc/src/main/resources/application.xml rename to tests/xml/jdbc/src/main/resources/context.xml diff --git a/tests/xml/jwt/src/main/java/demo/Application.java b/tests/xml/jwt/src/main/java/demo/Application.java index 8f3ded927..29be6be8d 100644 --- a/tests/xml/jwt/src/main/java/demo/Application.java +++ b/tests/xml/jwt/src/main/java/demo/Application.java @@ -39,7 +39,7 @@ @Configuration @ComponentScan @EnableAutoConfiguration -@ImportResource("classpath:/application.xml") +@ImportResource("classpath:/context.xml") @RestController public class Application { diff --git a/tests/xml/jwt/src/main/resources/application.xml b/tests/xml/jwt/src/main/resources/context.xml similarity index 100% rename from tests/xml/jwt/src/main/resources/application.xml rename to tests/xml/jwt/src/main/resources/context.xml diff --git a/tests/xml/mappings/src/main/java/demo/Application.java b/tests/xml/mappings/src/main/java/demo/Application.java index d467e4c06..eb1d98d49 100644 --- a/tests/xml/mappings/src/main/java/demo/Application.java +++ b/tests/xml/mappings/src/main/java/demo/Application.java @@ -38,7 +38,7 @@ @ComponentScan @EnableAutoConfiguration @RestController -@ImportResource("classpath:/application.xml") +@ImportResource("classpath:/context.xml") public class Application { public static void main(String[] args) { diff --git a/tests/xml/mappings/src/main/resources/application.xml b/tests/xml/mappings/src/main/resources/context.xml similarity index 100% rename from tests/xml/mappings/src/main/resources/application.xml rename to tests/xml/mappings/src/main/resources/context.xml diff --git a/tests/xml/vanilla/src/main/java/demo/Application.java b/tests/xml/vanilla/src/main/java/demo/Application.java index 64c1a39ec..b70fa3857 100644 --- a/tests/xml/vanilla/src/main/java/demo/Application.java +++ b/tests/xml/vanilla/src/main/java/demo/Application.java @@ -39,7 +39,7 @@ @ComponentScan @EnableAutoConfiguration @RestController -@ImportResource("classpath:/application.xml") +@ImportResource("classpath:/context.xml") public class Application { public static void main(String[] args) { diff --git a/tests/xml/vanilla/src/main/resources/application.xml b/tests/xml/vanilla/src/main/resources/context.xml similarity index 100% rename from tests/xml/vanilla/src/main/resources/application.xml rename to tests/xml/vanilla/src/main/resources/context.xml From 6ae6b0f68dd2ef4447735be2ab6653f7f6356091 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 25 Feb 2015 17:16:30 +0000 Subject: [PATCH 400/831] Use custom error handler if status doesn't match The basic motivation for this is that OAuth2RestTemplate should throw HttpClientException more often (so it behaves more like a regular RestTemplate). There are some OAuth2 specific responses that can be handled internally, but by and large those are already handled by the token granters and the client context filter. --- .../sparklr/config/SecurityConfiguration.java | 22 +++++----- .../WEB-INF/jsp/access_confirmation.jsp | 2 + .../oauth2/sparklr/src/main/webapp/index.jsp | 4 +- .../oauth2/sparklr/src/main/webapp/login.jsp | 6 +-- .../AuthorizationCodeProviderTests.java | 6 +-- .../provider/ImplicitProviderTests.java | 10 +++-- .../oauth/examples/config/SecurityConfig.java | 5 +-- samples/oauth2/tonr/src/main/webapp/login.jsp | 10 ++--- .../tonr/AuthorizationCodeGrantTests.java | 18 ++++---- .../security/samples/config/AdHocTests.java | 41 ++++++++++++++++++ .../samples/config/SecurityConfigTests.java | 2 + .../client/http/OAuth2ErrorHandler.java | 42 +++++++++++-------- .../client/test/OAuth2ContextSetup.java | 3 ++ ...uthorizationServerEndpointsConfigurer.java | 15 +++++-- .../client/http/OAuth2ErrorHandlerTests.java | 14 ++++--- .../jdbc/src/main/java/demo/Application.java | 13 +----- tests/annotation/pom.xml | 2 +- .../src/main/java/demo/Application.java | 4 +- tests/xml/pom.xml | 2 +- 19 files changed, 138 insertions(+), 83 deletions(-) create mode 100644 samples/oauth2/tonr/src/test/java/org/springframework/security/samples/config/AdHocTests.java diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/SecurityConfiguration.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/SecurityConfiguration.java index cc845418f..09845f2af 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/SecurityConfiguration.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/SecurityConfiguration.java @@ -1,5 +1,6 @@ package org.springframework.security.oauth.examples.sparklr.config; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; @@ -14,8 +15,8 @@ @EnableWebSecurity public class SecurityConfiguration extends WebSecurityConfigurerAdapter { - @Override - protected void configure(AuthenticationManagerBuilder auth) throws Exception { + @Autowired + public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().withUser("marissa").password("koala").roles("USER").and().withUser("paul") .password("emu").roles("USER"); } @@ -35,8 +36,8 @@ public AuthenticationManager authenticationManagerBean() throws Exception { protected void configure(HttpSecurity http) throws Exception { // @formatter:off http - .authorizeRequests().antMatchers("/login.jsp").permitAll().and() .authorizeRequests() + .antMatchers("/login.jsp").permitAll() .anyRequest().hasRole("USER") .and() .exceptionHandling() @@ -44,17 +45,16 @@ protected void configure(HttpSecurity http) throws Exception { .and() // TODO: put CSRF protection back into this endpoint .csrf() - .requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/authorize")).disable() + .requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/authorize")) + .disable() .logout() - .logoutSuccessUrl("/index.jsp") - .logoutUrl("/logout.do") + .logoutUrl("/logout") + .logoutSuccessUrl("/login.jsp") .and() .formLogin() - .usernameParameter("j_username") - .passwordParameter("j_password") - .failureUrl("/login.jsp?authentication_error=true") - .loginPage("/login.jsp") - .loginProcessingUrl("/login.do"); + .loginProcessingUrl("/login") + .failureUrl("/login.jsp?authentication_error=true") + .loginPage("/login.jsp"); // @formatter:on } } diff --git a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/jsp/access_confirmation.jsp b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/jsp/access_confirmation.jsp index 6cc9ed96f..dc68b3123 100644 --- a/samples/oauth2/sparklr/src/main/webapp/WEB-INF/jsp/access_confirmation.jsp +++ b/samples/oauth2/sparklr/src/main/webapp/WEB-INF/jsp/access_confirmation.jsp @@ -74,6 +74,8 @@ + diff --git a/samples/oauth2/sparklr/src/main/webapp/index.jsp b/samples/oauth2/sparklr/src/main/webapp/index.jsp index 9ebf47f02..3e96a2a2e 100644 --- a/samples/oauth2/sparklr/src/main/webapp/index.jsp +++ b/samples/oauth2/sparklr/src/main/webapp/index.jsp @@ -39,7 +39,9 @@

    -
    " role="form"> + " role="form" method="post"> +
    diff --git a/samples/oauth2/sparklr/src/main/webapp/login.jsp b/samples/oauth2/sparklr/src/main/webapp/login.jsp index 843b0c750..e1bc1091e 100644 --- a/samples/oauth2/sparklr/src/main/webapp/login.jsp +++ b/samples/oauth2/sparklr/src/main/webapp/login.jsp @@ -33,19 +33,19 @@

    We've got a grand total of 2 users: marissa and paul. Go ahead and log in. Marissa's password is "koala" and Paul's password is "emu".

    -
    " method="post" role="form"> + " method="post" role="form">

    Login

    + class="form-control" type='text' name='password' value="koala" />
    formData; formData = new LinkedMultiValueMap(); - formData.add("j_username", "marissa"); - formData.add("j_password", "koala"); + formData.add("username", "marissa"); + formData.add("password", "koala"); if (matcher.matches()) { formData.add("_csrf", matcher.group(1)); } - String location = "/sparklr2/login.do"; + String location = "/sparklr2/login"; HttpHeaders headers = new HttpHeaders(); headers.set("Cookie", cookie); headers.setAccept(Arrays.asList(MediaType.TEXT_HTML)); diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ImplicitProviderTests.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ImplicitProviderTests.java index 1a91c05e1..73fdfa552 100644 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ImplicitProviderTests.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/ImplicitProviderTests.java @@ -50,18 +50,20 @@ public void loginAndExtractCookie() { ResponseEntity page = serverRunning.getForString("/sparklr2/login.jsp"); String cookie = page.getHeaders().getFirst("Set-Cookie"); + HttpHeaders headers = new HttpHeaders(); + headers.set("Cookie", cookie); Matcher matcher = Pattern.compile("(?s).*name=\"_csrf\".*?value=\"([^\"]+).*").matcher(page.getBody()); MultiValueMap formData; formData = new LinkedMultiValueMap(); - formData.add("j_username", "marissa"); - formData.add("j_password", "koala"); + formData.add("username", "marissa"); + formData.add("password", "koala"); if (matcher.matches()) { formData.add("_csrf", matcher.group(1)); } - String location = "/sparklr2/login.do"; - ResponseEntity result = serverRunning.postForStatus(location, formData); + String location = "/sparklr2/login"; + ResponseEntity result = serverRunning.postForStatus(location, headers, formData); assertEquals(HttpStatus.FOUND, result.getStatusCode()); cookie = result.getHeaders().getFirst("Set-Cookie"); diff --git a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/SecurityConfig.java b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/SecurityConfig.java index 6e2b3c5fe..4ab10a75f 100644 --- a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/SecurityConfig.java +++ b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/SecurityConfig.java @@ -31,15 +31,12 @@ protected void configure(HttpSecurity http) throws Exception { .and() .logout() .logoutSuccessUrl("/login.jsp") - .logoutUrl("/logout.do") .permitAll() .and() .formLogin() + .loginProcessingUrl("/login") .loginPage("/login.jsp") - .loginProcessingUrl("/login.do") .failureUrl("/login.jsp?authentication_error=true") - .usernameParameter("j_username") - .passwordParameter("j_password") .permitAll(); // @formatter:on } diff --git a/samples/oauth2/tonr/src/main/webapp/login.jsp b/samples/oauth2/tonr/src/main/webapp/login.jsp index b92324b27..32280ee05 100644 --- a/samples/oauth2/tonr/src/main/webapp/login.jsp +++ b/samples/oauth2/tonr/src/main/webapp/login.jsp @@ -53,18 +53,18 @@ for "marissa" is password is "wombat" and for "sam" is password is "kangaroo".

    - +

    Login

    - +
    - +
    form; form = new LinkedMultiValueMap(); - form.add("j_username", "marissa"); - form.add("j_password", "wombat"); + form.add("username", "marissa"); + form.add("password", "wombat"); if (matcher.matches()) { form.add("_csrf", matcher.group(1)); } - ResponseEntity response = serverRunning.postForStatus("/tonr2/login.do", headers, + ResponseEntity response = serverRunning.postForStatus("/tonr2/login", headers, form); cookie = response.getHeaders().getFirst("Set-Cookie"); @@ -125,12 +125,12 @@ public void testTokenAcquisitionWithRegisteredRedirect() throws Exception { MultiValueMap form; form = new LinkedMultiValueMap(); - form.add("j_username", "marissa"); - form.add("j_password", "wombat"); + form.add("username", "marissa"); + form.add("password", "wombat"); if (matcher.matches()) { form.add("_csrf", matcher.group(1)); } - ResponseEntity response = serverRunning.postForStatus("/tonr2/login.do", headers, + ResponseEntity response = serverRunning.postForStatus("/tonr2/login", headers, form); cookie = response.getHeaders().getFirst("Set-Cookie"); @@ -157,14 +157,14 @@ private String authenticateAndApprove(String location) { MultiValueMap form; form = new LinkedMultiValueMap(); - form.add("j_username", "marissa"); - form.add("j_password", "koala"); + form.add("username", "marissa"); + form.add("password", "koala"); if (matcher.matches()) { form.add("_csrf", matcher.group(1)); } HttpHeaders response = serverRunning.postForHeaders( - "/sparklr2/login.do", form); + "/sparklr2/login", form); cookie = response.getFirst("Set-Cookie"); HttpHeaders headers = new HttpHeaders(); diff --git a/samples/oauth2/tonr/src/test/java/org/springframework/security/samples/config/AdHocTests.java b/samples/oauth2/tonr/src/test/java/org/springframework/security/samples/config/AdHocTests.java new file mode 100644 index 000000000..f9fd93b8b --- /dev/null +++ b/samples/oauth2/tonr/src/test/java/org/springframework/security/samples/config/AdHocTests.java @@ -0,0 +1,41 @@ +/* + * Copyright 20013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.springframework.security.samples.config; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; +import org.springframework.security.oauth.examples.tonr.AuthorizationCodeGrantTests; +import org.springframework.security.oauth.examples.tonr.ClientCredentialsGrantTests; +import org.springframework.security.oauth.examples.tonr.RefreshTokenGrantTests; +import org.springframework.security.oauth.examples.tonr.ResourceOwnerPasswordGrantTests; + +/** + * @author Dave Syer + * + */ +@RunWith(Suite.class) +// @formatter:off +@SuiteClasses({ + SecurityConfigTests.class, + ClientCredentialsGrantTests.class, + RefreshTokenGrantTests.class, + ResourceOwnerPasswordGrantTests.class, + AuthorizationCodeGrantTests.class, + }) +// @formatter:on +// @Ignore("Test suite for tracking order dependencies") +public class AdHocTests { + +} diff --git a/samples/oauth2/tonr/src/test/java/org/springframework/security/samples/config/SecurityConfigTests.java b/samples/oauth2/tonr/src/test/java/org/springframework/security/samples/config/SecurityConfigTests.java index 8109d3a50..3b68447f1 100644 --- a/samples/oauth2/tonr/src/test/java/org/springframework/security/samples/config/SecurityConfigTests.java +++ b/samples/oauth2/tonr/src/test/java/org/springframework/security/samples/config/SecurityConfigTests.java @@ -21,6 +21,7 @@ import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.security.web.FilterChainProxy; +import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; @@ -32,6 +33,7 @@ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration @WebAppConfiguration +@DirtiesContext public class SecurityConfigTests { @Configuration @ComponentScan(basePackages = "org.springframework.security.oauth.examples.config") diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandler.java index ea0cfb23a..eb7907682 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandler.java @@ -16,15 +16,15 @@ package org.springframework.security.oauth2.client.http; import java.io.ByteArrayInputStream; -import java.io.InputStream; import java.io.IOException; +import java.io.InputStream; import java.util.List; import java.util.Map; -import org.springframework.http.client.ClientHttpResponse; -import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.http.converter.HttpMessageConverter; import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; @@ -52,7 +52,8 @@ public class OAuth2ErrorHandler implements ResponseErrorHandler { * Construct an error handler that can deal with OAuth2 concerns before handling the error in the default fashion. */ public OAuth2ErrorHandler(OAuth2ProtectedResourceDetails resource) { - this(new DefaultResponseErrorHandler(), resource); + this.resource = resource; + this.errorHandler = new DefaultResponseErrorHandler(); } /** @@ -73,16 +74,17 @@ public OAuth2ErrorHandler(ResponseErrorHandler errorHandler, OAuth2ProtectedReso } public boolean hasError(ClientHttpResponse response) throws IOException { - return HttpStatus.Series.CLIENT_ERROR.equals(response.getStatusCode().series()) || - this.errorHandler.hasError(response); + return HttpStatus.Series.CLIENT_ERROR.equals(response.getStatusCode().series()) + || this.errorHandler.hasError(response); } public void handleError(final ClientHttpResponse response) throws IOException { - if (! HttpStatus.Series.CLIENT_ERROR.equals(response.getStatusCode().series())) { + if (!HttpStatus.Series.CLIENT_ERROR.equals(response.getStatusCode().series())) { // We should only care about 400 level errors. Ex: A 500 server error shouldn't // be an oauth related error. errorHandler.handleError(response); - } else { + } + else { // Need to use buffered response because input stream may need to be consumed multiple times. ClientHttpResponse bufferedResponse = new ClientHttpResponse() { private byte[] lazyBody; @@ -96,7 +98,8 @@ public synchronized InputStream getBody() throws IOException { InputStream bodyStream = response.getBody(); if (bodyStream != null) { lazyBody = FileCopyUtils.copyToByteArray(bodyStream); - } else { + } + else { lazyBody = new byte[0]; } } @@ -126,8 +129,8 @@ public int getRawStatusCode() throws IOException { try { OAuth2Exception body = extractor.extractData(bufferedResponse); if (body != null) { - // If we can get an OAuth2Exception already from the body, it is likely to have more information than - // the header does, so just re-throw it here. + // If we can get an OAuth2Exception already from the body, it is likely to have more information + // than the header does, so just re-throw it here. throw body; } } @@ -147,16 +150,19 @@ public int getRawStatusCode() throws IOException { // then delegate to the custom handler errorHandler.handleError(bufferedResponse); } + catch (InvalidTokenException ex) { + // Special case: an invalid token can be renewed so tell the caller what to do + throw new AccessTokenRequiredException(resource); + } catch (OAuth2Exception ex) { - if (bufferedResponse.getRawStatusCode() == 403 || bufferedResponse.getRawStatusCode() == 401 || ! ex.getClass().equals(OAuth2Exception.class)) { - // Status code 401 should always mean that we need a legitimate token. - // Caught a specific, derived class so this is not just some generic error + if (!ex.getClass().equals(OAuth2Exception.class)) { + // There is more information here than the caller would get from an HttpClientErrorException so + // rethrow throw ex; - } else { - // This is not an exception that is really understood, so allow our delegate - // to handle it in a non-oauth way - errorHandler.handleError(bufferedResponse); } + // This is not an exception that is really understood, so allow our delegate + // to handle it in a non-oauth way + errorHandler.handleError(bufferedResponse); } } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/OAuth2ContextSetup.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/OAuth2ContextSetup.java index ee68b3995..6e442c35b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/OAuth2ContextSetup.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/OAuth2ContextSetup.java @@ -310,6 +310,9 @@ public void evaluate() { catch (RuntimeException e) { throw e; } + catch (AssertionError e) { + throw e; + } catch (Throwable e) { logger.debug("Exception in befores", e); Assert.assertThat(e, CoreMatchers.not(CoreMatchers.anything())); 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 efc166ec3..29d34952d 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 @@ -190,7 +190,7 @@ public AuthorizationServerEndpointsConfigurer accessTokenConverter(AccessTokenCo public AuthorizationServerEndpointsConfigurer tokenServices(AuthorizationServerTokenServices tokenServices) { this.tokenServices = tokenServices; - if (tokenServices!=null) { + if (tokenServices != null) { this.tokenServicesOverride = true; } return this; @@ -199,7 +199,7 @@ public AuthorizationServerEndpointsConfigurer tokenServices(AuthorizationServerT public boolean isTokenServicesOverride() { return tokenServicesOverride; } - + public boolean isUserDetailsServiceOverride() { return userDetailsServiceOverride; } @@ -217,6 +217,13 @@ public AuthorizationServerEndpointsConfigurer approvalStore(ApprovalStore approv return this; } + /** + * 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() { this.approvalStoreDisabled = true; return this; @@ -441,8 +448,8 @@ private void addUserDetailsService(DefaultTokenServices tokenServices, UserDetai PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider(); provider.setPreAuthenticatedUserDetailsService(new UserDetailsByNameServiceWrapper( userDetailsService)); - tokenServices.setAuthenticationManager( - new ProviderManager(Arrays. asList(provider))); + tokenServices + .setAuthenticationManager(new ProviderManager(Arrays. asList(provider))); } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandlerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandlerTests.java index ef0ec68a9..891bad74c 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandlerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandlerTests.java @@ -23,7 +23,6 @@ import java.io.InputStream; import org.junit.Assert; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -35,6 +34,7 @@ import org.springframework.http.MediaType; import org.springframework.http.client.ClientHttpResponse; import org.springframework.security.oauth2.client.resource.BaseOAuth2ProtectedResourceDetails; +import org.springframework.web.client.DefaultResponseErrorHandler; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.ResponseErrorHandler; @@ -109,7 +109,9 @@ public void testHandleErrorClientHttpResponse() throws Exception { headers.set("www-authenticate", "Bearer error=foo"); ClientHttpResponse response = new TestClientHttpResponse(headers, 401); - expected.expectMessage("foo"); + // We lose the www-authenticate content in a nested exception (but it's still available) through the + // HttpClientErrorException + expected.expectMessage("401 Unauthorized"); handler.handleError(response); } @@ -177,13 +179,13 @@ public void testHandleGeneric403Error() throws Exception { } @Test - @Ignore("See https://github.com/spring-projects/spring-security-oauth/issues/387") + // See https://github.com/spring-projects/spring-security-oauth/issues/387 public void testHandleGeneric403ErrorWithBody() throws Exception { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); - ClientHttpResponse response = new TestClientHttpResponse(headers, 403, new ByteArrayInputStream( - "{}".getBytes())); - + ClientHttpResponse response = new TestClientHttpResponse(headers, 403, + new ByteArrayInputStream("{}".getBytes())); + handler = new OAuth2ErrorHandler(new DefaultResponseErrorHandler(), resource); expected.expect(HttpClientErrorException.class); handler.handleError(response); } diff --git a/tests/annotation/jdbc/src/main/java/demo/Application.java b/tests/annotation/jdbc/src/main/java/demo/Application.java index 603aae242..f3a8a4f23 100644 --- a/tests/annotation/jdbc/src/main/java/demo/Application.java +++ b/tests/annotation/jdbc/src/main/java/demo/Application.java @@ -11,8 +11,6 @@ import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter; import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.AuthenticationException; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; @@ -67,7 +65,7 @@ public void configure(HttpSecurity http) throws Exception { protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter { @Autowired - private AuthenticationManagerBuilder auth; + private AuthenticationManager auth; @Autowired private DataSource dataSource; @@ -92,14 +90,7 @@ public void configure(AuthorizationServerSecurityConfigurer security) throws Exc @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.authorizationCodeServices(authorizationCodeServices()) - .authenticationManager(new AuthenticationManager() { - // TODO: unwind this workaround for Spring Boot issue (when 1.1.9 is out) - @Override - public Authentication authenticate(Authentication authentication) - throws AuthenticationException { - return auth.getOrBuild().authenticate(authentication); - } - }).tokenStore(tokenStore()).approvalStoreDisabled(); + .authenticationManager(auth).tokenStore(tokenStore()).approvalStoreDisabled(); } @Override diff --git a/tests/annotation/pom.xml b/tests/annotation/pom.xml index 2e1e0ee1d..71e737fc8 100644 --- a/tests/annotation/pom.xml +++ b/tests/annotation/pom.xml @@ -26,7 +26,7 @@ org.springframework.boot spring-boot-starter-parent - 1.2.2.BUILD-SNAPSHOT + 1.2.2.RELEASE diff --git a/tests/xml/mappings/src/main/java/demo/Application.java b/tests/xml/mappings/src/main/java/demo/Application.java index eb1d98d49..3c19cb241 100644 --- a/tests/xml/mappings/src/main/java/demo/Application.java +++ b/tests/xml/mappings/src/main/java/demo/Application.java @@ -96,8 +96,8 @@ public FilterRegistrationBean resourceFilterRegistration() { protected void configure(HttpSecurity http) throws Exception { // @formatter:off http.addFilterBefore(resourceFilter, AbstractPreAuthenticatedProcessingFilter.class) - // Just for laughs, apply OAuth protection to only 2 resources - .requestMatchers().antMatchers("/","/admin/beans") + // Just for laughs, apply OAuth protection to only 3 resources + .requestMatchers().antMatchers("/","/admin/beans","/admin/health") .and() .authorizeRequests() .anyRequest().access("#oauth2.hasScope('read')").expressionHandler(new OAuth2WebSecurityExpressionHandler()) diff --git a/tests/xml/pom.xml b/tests/xml/pom.xml index 4e3d67043..7aa391705 100644 --- a/tests/xml/pom.xml +++ b/tests/xml/pom.xml @@ -24,7 +24,7 @@ org.springframework.boot spring-boot-starter-parent - 1.2.2.BUILD-SNAPSHOT + 1.2.2.RELEASE From 331976064b229296acbf1b226ab44b657a9d951c Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 12 Mar 2015 12:16:38 +0000 Subject: [PATCH 401/831] Add test for custom TokenGranter See gh-422 --- ...AuthorizationServerConfigurationTests.java | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java index e657875c9..95640c99c 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java @@ -105,7 +105,8 @@ public static List parameters() { new Object[] { null, new Class[] { AuthorizationServerCustomClientDetails.class } }, new Object[] { null, new Class[] { AuthorizationServerAllowsSpecificRequestMethods.class} }, new Object[] { null, new Class[] { AuthorizationServerAllowsOnlyPost.class} }, - new Object[] { BeanCreationException.class, new Class[] { AuthorizationServerTypes.class } } + new Object[] { BeanCreationException.class, new Class[] { AuthorizationServerTypes.class } }, + new Object[] { null, new Class[] { AuthorizationServerCustomGranter.class } } // @formatter:on ); } @@ -558,6 +559,33 @@ public void run() { @Configuration @EnableWebMvcSecurity + @EnableAuthorizationServer + protected static class AuthorizationServerCustomGranter extends + AuthorizationServerConfigurerAdapter implements Runnable { + + @Autowired + private ApplicationContext context; + + @Override + public void configure(AuthorizationServerEndpointsConfigurer endpoints) + throws Exception { + endpoints.tokenGranter(new ClientCredentialsTokenGranter(endpoints + .getDefaultAuthorizationServerTokenServices(), endpoints + .getClientDetailsService(), endpoints.getOAuth2RequestFactory())); + } + + @Override + public void run() { + assertTrue(ReflectionTestUtils.getField( + context.getBean(TokenEndpoint.class), "tokenGranter") instanceof ClientCredentialsTokenGranter); + } + + } + + @Configuration + @EnableWebMvcSecurity + @EnableAuthorizationServer + // Stuff that can't be autowired protected static class AuthorizationServerTypes extends AuthorizationServerConfigurerAdapter { @Autowired @@ -571,8 +599,6 @@ protected static class AuthorizationServerTypes extends AuthorizationServerConfi @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { - endpoints.tokenGranter(new ClientCredentialsTokenGranter(tokenServices, clientDetailsService, - requestFactory)); } } From 39f605590856ccdd59f21a77f097331f098ea5c4 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 12 Mar 2015 12:58:59 +0000 Subject: [PATCH 402/831] Explicit handler methods for POST and GET Replacing the single method binding to HttpMethod (which breaks in older versions of Spring). I can't see why anyone would be using anything other than GET and POST, so we only really need 2 methods. Fixes gh-413 --- .../provider/endpoint/TokenEndpoint.java | 22 ++++++++++++++----- .../provider/endpoint/TokenEndpointTests.java | 18 ++++++++------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java index 9d15b6f10..bf559c8ee 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java @@ -17,7 +17,11 @@ package org.springframework.security.oauth2.provider.endpoint; import java.security.Principal; -import java.util.*; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; @@ -43,6 +47,7 @@ import org.springframework.web.HttpRequestMethodNotSupportedException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; /** @@ -69,13 +74,18 @@ public class TokenEndpoint extends AbstractEndpoint { private Set allowedRequestMethods = new HashSet(Arrays.asList(HttpMethod.POST)); - @RequestMapping(value = "/oauth/token") + @RequestMapping(value = "/oauth/token", method=RequestMethod.GET) public ResponseEntity getAccessToken(Principal principal, @RequestParam - Map parameters, HttpMethod requestMethod) throws HttpRequestMethodNotSupportedException { - - if (!allowedRequestMethods.contains(requestMethod)) { - throw new HttpRequestMethodNotSupportedException(requestMethod.toString()); + Map parameters) throws HttpRequestMethodNotSupportedException { + if (!allowedRequestMethods.contains(HttpMethod.GET)) { + throw new HttpRequestMethodNotSupportedException("GET"); } + return postAccessToken(principal, parameters); + } + + @RequestMapping(value = "/oauth/token", method=RequestMethod.POST) + public ResponseEntity postAccessToken(Principal principal, @RequestParam + Map parameters) throws HttpRequestMethodNotSupportedException { if (!(principal instanceof Authentication)) { throw new InsufficientAuthenticationException( diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointTests.java index bbf0bdc2f..8a2c40ba8 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointTests.java @@ -22,7 +22,11 @@ import static org.mockito.Mockito.when; import java.security.Principal; -import java.util.*; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; import org.junit.Before; import org.junit.Test; @@ -104,8 +108,7 @@ public void testGetAccessTokenWithNoClientId() throws HttpRequestMethodNotSuppor clientAuthentication = new UsernamePasswordAuthenticationToken(null, null, Collections.singleton(new SimpleGrantedAuthority("ROLE_CLIENT"))); - ResponseEntity response = endpoint.getAccessToken(clientAuthentication, parameters, - HttpMethod.POST); + ResponseEntity response = endpoint.postAccessToken(clientAuthentication, parameters); assertNotNull(response); assertEquals(HttpStatus.OK, response.getStatusCode()); @@ -134,8 +137,7 @@ public void testGetAccessTokenWithScope() throws HttpRequestMethodNotSupportedEx when(authorizationRequestFactory.createTokenRequest(anyMap, Mockito.eq(clientDetails))).thenReturn( createFromParameters(parameters)); - ResponseEntity response = endpoint.getAccessToken(clientAuthentication, parameters, - HttpMethod.POST); + ResponseEntity response = endpoint.postAccessToken(clientAuthentication, parameters); assertNotNull(response); assertEquals(HttpStatus.OK, response.getStatusCode()); @@ -147,7 +149,7 @@ public void testGetAccessTokenWithScope() throws HttpRequestMethodNotSupportedEx @Test(expected = HttpRequestMethodNotSupportedException.class) public void testGetAccessTokenWithUnsupportedRequestParameters() throws HttpRequestMethodNotSupportedException { - endpoint.getAccessToken(clientAuthentication, new HashMap(), HttpMethod.GET); + endpoint.getAccessToken(clientAuthentication, new HashMap()); } @Test @@ -167,7 +169,7 @@ public void testGetAccessTokenWithSupportedRequestParametersNotPost() throws Htt when(authorizationRequestFactory.createTokenRequest(anyMap, Mockito.any(ClientDetails.class))).thenReturn( createFromParameters(parameters)); - ResponseEntity response = endpoint.getAccessToken(clientAuthentication, parameters, HttpMethod.GET); + ResponseEntity response = endpoint.getAccessToken(clientAuthentication, parameters); assertNotNull(response); assertEquals(HttpStatus.OK, response.getStatusCode()); OAuth2AccessToken body = response.getBody(); @@ -186,6 +188,6 @@ public void testImplicitGrant() throws HttpRequestMethodNotSupportedException { when(authorizationRequestFactory.createTokenRequest(anyMap, Mockito.eq(clientDetails))).thenReturn( createFromParameters(parameters)); when(clientDetailsService.loadClientByClientId(clientId)).thenReturn(clientDetails); - endpoint.getAccessToken(clientAuthentication, parameters, HttpMethod.POST); + endpoint.postAccessToken(clientAuthentication, parameters); } } From e6841d230349c731c956cf1e5725ea4b5901ab96 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 12 Mar 2015 14:21:46 +0000 Subject: [PATCH 403/831] Fix client app integration test (Boot regression) --- .../test/java/client/CombinedApplication.java | 35 +++++++++++++++++++ .../resources/application-combined.properties | 3 +- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/tests/annotation/client/src/test/java/client/CombinedApplication.java b/tests/annotation/client/src/test/java/client/CombinedApplication.java index 9c612f760..4b0892c17 100644 --- a/tests/annotation/client/src/test/java/client/CombinedApplication.java +++ b/tests/annotation/client/src/test/java/client/CombinedApplication.java @@ -14,11 +14,20 @@ import java.util.Arrays; import java.util.Collections; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Set; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.security.SecurityProperties; +import org.springframework.boot.autoconfigure.security.SecurityProperties.User; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; @@ -90,4 +99,30 @@ public void configure(HttpSecurity http) throws Exception { } + @Configuration + protected static class AuthenticationConfigurerAdapter extends + GlobalAuthenticationConfigurerAdapter { + + private static Log logger = LogFactory + .getLog(AuthenticationConfigurerAdapter.class); + + @Autowired + private SecurityProperties security; + + @Override + public void init(AuthenticationManagerBuilder auth) throws Exception { + User user = this.security.getUser(); + if (user.isDefaultPassword()) { + logger.info("\n\nUsing default security password: " + user.getPassword() + + "\n"); + } + + Set roles = new LinkedHashSet(user.getRole()); + auth.inMemoryAuthentication().withUser(user.getName()) + .password(user.getPassword()) + .roles(roles.toArray(new String[roles.size()])); + } + + } + } diff --git a/tests/annotation/client/src/test/resources/application-combined.properties b/tests/annotation/client/src/test/resources/application-combined.properties index c44bd0a7a..1522a6e47 100644 --- a/tests/annotation/client/src/test/resources/application-combined.properties +++ b/tests/annotation/client/src/test/resources/application-combined.properties @@ -2,4 +2,5 @@ server.port: 8080 server.context_path: security.basic.enabled: true security.user.password: password -security.ignored: /,/admin/info \ No newline at end of file +security.ignored: /,/admin/info +# logging.level.org.springframework.security: DEBUG \ No newline at end of file From 4697d771a39d15f714997d8291250d7d66107d76 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 12 Mar 2015 15:42:18 +0000 Subject: [PATCH 404/831] Compare AOP targets instead of proxy to resolve token services The logic to detect an existing default ResourceServerTokenServices was flawed in the case that the two default ones were proxied (e.g. as is the case with @EnableGlobalMethodSecurity. It has proved rather difficult to find a test that breaks on this one, but the sample project from gh-342 is fixed with this change. Fixes gh-342 --- .../ResourceServerConfiguration.java | 102 ++++++++----- .../ResourceServerConfigurationTests.java | 141 ++++++++++++++---- .../java/demo/GlobalMethodSecurityTests.java | 29 ++++ 3 files changed, 205 insertions(+), 67 deletions(-) create mode 100644 tests/annotation/vanilla/src/test/java/demo/GlobalMethodSecurityTests.java diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java index 2716641ff..3fb246c42 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java @@ -16,11 +16,13 @@ package org.springframework.security.oauth2.config.annotation.web.configuration; import java.util.Collections; +import java.util.Iterator; import java.util.List; +import java.util.Map; import javax.servlet.http.HttpServletRequest; -import org.springframework.beans.factory.BeanCreationException; +import org.springframework.aop.framework.Advised; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Configuration; @@ -37,13 +39,15 @@ import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.web.util.matcher.RequestMatcher; +import org.springframework.util.ReflectionUtils; /** * @author Dave Syer * */ @Configuration -public class ResourceServerConfiguration extends WebSecurityConfigurerAdapter implements Ordered { +public class ResourceServerConfiguration extends WebSecurityConfigurerAdapter + implements Ordered { private int order = 3; @@ -54,12 +58,13 @@ public class ResourceServerConfiguration extends WebSecurityConfigurerAdapter im private AuthenticationEventPublisher eventPublisher; @Autowired(required = false) - private ResourceServerTokenServices[] tokenServices; + private Map tokenServices; @Autowired private ApplicationContext context; - private List configurers = Collections.emptyList(); + private List configurers = Collections + .emptyList(); @Autowired(required = false) private AuthorizationServerEndpointsConfiguration endpoints; @@ -74,7 +79,8 @@ public void setOrder(int order) { } /** - * @param configurers the configurers to set + * @param configurers + * the configurers to set */ @Autowired(required = false) public void setConfigurers(List configurers) { @@ -115,7 +121,8 @@ private String getRequestPath(HttpServletRequest request) { @Autowired protected void init(AuthenticationManagerBuilder builder) { if (!builder.isConfigured()) { - builder.authenticationProvider(new AnonymousAuthenticationProvider("default")); + builder.authenticationProvider(new AnonymousAuthenticationProvider( + "default")); } } @@ -125,13 +132,12 @@ protected void configure(HttpSecurity http) throws Exception { ResourceServerTokenServices services = resolveTokenServices(); if (services != null) { resources.tokenServices(services); - } - else { + } else { if (tokenStore != null) { resources.tokenStore(tokenStore); - } - else if (endpoints != null) { - resources.tokenStore(endpoints.getEndpointsConfigurer().getTokenStore()); + } else if (endpoints != null) { + resources.tokenStore(endpoints.getEndpointsConfigurer() + .getTokenStore()); } } if (eventPublisher != null) { @@ -140,56 +146,76 @@ else if (endpoints != null) { for (ResourceServerConfigurer configurer : configurers) { configurer.configure(resources); } - // @formatter:off + // @formatter:off http - // N.B. exceptionHandling is duplicated in resources.configure() so that it works - .exceptionHandling().accessDeniedHandler(resources.getAccessDeniedHandler()) - .and() - .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) - .and() - .csrf().disable(); + // N.B. exceptionHandling is duplicated in resources.configure() so that + // it works + .exceptionHandling() + .accessDeniedHandler(resources.getAccessDeniedHandler()).and() + .sessionManagement() + .sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() + .csrf().disable(); // @formatter:on http.apply(resources); RequestMatcherConfigurer requests = http.requestMatchers(); if (endpoints != null) { // Assume we are in an Authorization Server - requests.requestMatchers(new NotOAuthRequestMatcher(endpoints.oauth2EndpointHandlerMapping())); + requests.requestMatchers(new NotOAuthRequestMatcher(endpoints + .oauth2EndpointHandlerMapping())); } for (ResourceServerConfigurer configurer : configurers) { // Delegates can add authorizeRequests() here configurer.configure(http); } if (configurers.isEmpty()) { - // Add anyRequest() last as a fall back. Spring Security would replace an existing anyRequest() matcher - // with this one, so to avoid that we only add it if the user hasn't configured anything. + // Add anyRequest() last as a fall back. Spring Security would + // replace an existing anyRequest() matcher + // with this one, so to avoid that we only add it if the user hasn't + // configured anything. http.authorizeRequests().anyRequest().authenticated(); } } private ResourceServerTokenServices resolveTokenServices() { - if (tokenServices == null || tokenServices.length == 0) { + if (tokenServices == null || tokenServices.size() == 0) { return null; } - if (tokenServices.length == 1) { - return tokenServices[0]; - } - if (tokenServices.length == 2 && tokenServices[0] == tokenServices[1]) { - return tokenServices[0]; - } - try { - TokenServicesConfiguration bean = context.getAutowireCapableBeanFactory().createBean( - TokenServicesConfiguration.class); - return bean.services; + if (tokenServices.size() == 1) { + return tokenServices.values().iterator().next(); + } + if (tokenServices.size() == 2) { + // Maybe they are the ones provided natively + Iterator iter = tokenServices.values() + .iterator(); + ResourceServerTokenServices one = iter.next(); + ResourceServerTokenServices two = iter.next(); + if (elementsEqual(one, two)) { + return one; + } } - catch (BeanCreationException e) { - throw new IllegalStateException( - "Could not wire ResourceServerTokenServices: please create a bean definition and mark it as @Primary."); + return context.getBean(ResourceServerTokenServices.class); + } + + private boolean elementsEqual(Object one, Object two) { + // They might just be equal + if (one == two) { + return true; } + Object targetOne = findTarget(one); + Object targetTwo = findTarget(two); + return targetOne == targetTwo; } - private static class TokenServicesConfiguration { - @Autowired - private ResourceServerTokenServices services; + private Object findTarget(Object item) { + Object current = item; + while (current instanceof Advised) { + try { + current = ((Advised) current).getTargetSource().getTarget(); + } catch (Exception e) { + ReflectionUtils.rethrowRuntimeException(e); + } + } + return current; } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java index 497e05105..d464f09af 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java @@ -24,11 +24,14 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.mock.web.MockServletContext; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; @@ -64,16 +67,19 @@ public class ResourceServerConfigurationTests { private OAuth2AccessToken token; private OAuth2Authentication authentication; - + @Rule public ExpectedException expected = ExpectedException.none(); @Before public void init() { token = new DefaultOAuth2AccessToken("FOO"); - ClientDetails client = new BaseClientDetails("client", null, "read", "client_credentials", "ROLE_CLIENT"); + ClientDetails client = new BaseClientDetails("client", null, "read", + "client_credentials", "ROLE_CLIENT"); authentication = new OAuth2Authentication( - new TokenRequest(null, "client", null, "client_credentials").createOAuth2Request(client), null); + new TokenRequest(null, "client", null, "client_credentials") + .createOAuth2Request(client), + null); tokenStore.clear(); } @@ -84,15 +90,39 @@ public void testDefaults() throws Exception { context.setServletContext(new MockServletContext()); context.register(ResourceServerContext.class); context.refresh(); - MockMvc mvc = MockMvcBuilders.webAppContextSetup(context) - .addFilters(new DelegatingFilterProxy(context.getBean("springSecurityFilterChain", Filter.class))) + MockMvc mvc = MockMvcBuilders + .webAppContextSetup(context) + .addFilters( + new DelegatingFilterProxy(context.getBean( + "springSecurityFilterChain", Filter.class))) .build(); - mvc.perform(MockMvcRequestBuilders.get("/")).andExpect(MockMvcResultMatchers.status().isUnauthorized()); - mvc.perform(MockMvcRequestBuilders.get("/").header("Authorization", "Bearer FOO")).andExpect( + mvc.perform(MockMvcRequestBuilders.get("/")).andExpect( + MockMvcResultMatchers.status().isUnauthorized()); + mvc.perform( + MockMvcRequestBuilders.get("/").header("Authorization", + "Bearer FOO")).andExpect( MockMvcResultMatchers.status().isNotFound()); context.close(); } + @Test + public void testWithAuthServer() throws Exception { + AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); + context.setServletContext(new MockServletContext()); + context.register(ResourceServerAndAuthorizationServerContext.class); + context.refresh(); + context.close(); + } + + @Test + public void testWithAuthServerAndGlobalMethodSecurity() throws Exception { + AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); + context.setServletContext(new MockServletContext()); + context.register(ResourceServerAndAuthorizationServerContextAndGlobalMethodSecurity.class); + context.refresh(); + context.close(); + } + @Test public void testCustomTokenServices() throws Exception { tokenStore.storeAccessToken(token, authentication); @@ -100,11 +130,17 @@ public void testCustomTokenServices() throws Exception { context.setServletContext(new MockServletContext()); context.register(TokenServicesContext.class); context.refresh(); - MockMvc mvc = MockMvcBuilders.webAppContextSetup(context) - .addFilters(new DelegatingFilterProxy(context.getBean("springSecurityFilterChain", Filter.class))) + MockMvc mvc = MockMvcBuilders + .webAppContextSetup(context) + .addFilters( + new DelegatingFilterProxy(context.getBean( + "springSecurityFilterChain", Filter.class))) .build(); - mvc.perform(MockMvcRequestBuilders.get("/")).andExpect(MockMvcResultMatchers.status().isUnauthorized()); - mvc.perform(MockMvcRequestBuilders.get("/").header("Authorization", "Bearer FOO")).andExpect( + mvc.perform(MockMvcRequestBuilders.get("/")).andExpect( + MockMvcResultMatchers.status().isUnauthorized()); + mvc.perform( + MockMvcRequestBuilders.get("/").header("Authorization", + "Bearer FOO")).andExpect( MockMvcResultMatchers.status().isNotFound()); context.close(); } @@ -116,10 +152,15 @@ public void testCustomTokenExtractor() throws Exception { context.setServletContext(new MockServletContext()); context.register(TokenExtractorContext.class); context.refresh(); - MockMvc mvc = MockMvcBuilders.webAppContextSetup(context) - .addFilters(new DelegatingFilterProxy(context.getBean("springSecurityFilterChain", Filter.class))) + MockMvc mvc = MockMvcBuilders + .webAppContextSetup(context) + .addFilters( + new DelegatingFilterProxy(context.getBean( + "springSecurityFilterChain", Filter.class))) .build(); - mvc.perform(MockMvcRequestBuilders.get("/").header("Authorization", "Bearer BAR")).andExpect( + mvc.perform( + MockMvcRequestBuilders.get("/").header("Authorization", + "Bearer BAR")).andExpect( MockMvcResultMatchers.status().isNotFound()); context.close(); } @@ -131,12 +172,17 @@ public void testCustomExpressionHandler() throws Exception { context.setServletContext(new MockServletContext()); context.register(ExpressionHandlerContext.class); context.refresh(); - MockMvc mvc = MockMvcBuilders.webAppContextSetup(context) - .addFilters(new DelegatingFilterProxy(context.getBean("springSecurityFilterChain", Filter.class))) + MockMvc mvc = MockMvcBuilders + .webAppContextSetup(context) + .addFilters( + new DelegatingFilterProxy(context.getBean( + "springSecurityFilterChain", Filter.class))) .build(); expected.expect(IllegalArgumentException.class); expected.expectMessage("#oauth2"); - mvc.perform(MockMvcRequestBuilders.get("/").header("Authorization", "Bearer FOO")).andExpect( + mvc.perform( + MockMvcRequestBuilders.get("/").header("Authorization", + "Bearer FOO")).andExpect( MockMvcResultMatchers.status().isUnauthorized()); context.close(); } @@ -148,10 +194,15 @@ public void testCustomAuthenticationEntryPoint() throws Exception { context.setServletContext(new MockServletContext()); context.register(AuthenticationEntryPointContext.class); context.refresh(); - MockMvc mvc = MockMvcBuilders.webAppContextSetup(context) - .addFilters(new DelegatingFilterProxy(context.getBean("springSecurityFilterChain", Filter.class))) + MockMvc mvc = MockMvcBuilders + .webAppContextSetup(context) + .addFilters( + new DelegatingFilterProxy(context.getBean( + "springSecurityFilterChain", Filter.class))) .build(); - mvc.perform(MockMvcRequestBuilders.get("/").header("Authorization", "Bearer FOO")).andExpect( + mvc.perform( + MockMvcRequestBuilders.get("/").header("Authorization", + "Bearer FOO")).andExpect( MockMvcResultMatchers.status().isFound()); context.close(); } @@ -169,7 +220,33 @@ public TokenStore tokenStore() { @Configuration @EnableResourceServer @EnableWebSecurity - protected static class AuthenticationEntryPointContext extends ResourceServerConfigurerAdapter { + protected static class ResourceServerAndAuthorizationServerContext extends + AuthorizationServerConfigurerAdapter { + @Override + public void configure(ClientDetailsServiceConfigurer clients) + throws Exception { + clients.inMemory(); + } + } + + @Configuration + @EnableResourceServer + @EnableWebSecurity + @EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true) + protected static class ResourceServerAndAuthorizationServerContextAndGlobalMethodSecurity + extends AuthorizationServerConfigurerAdapter { + @Override + public void configure(ClientDetailsServiceConfigurer clients) + throws Exception { + clients.inMemory(); + } + } + + @Configuration + @EnableResourceServer + @EnableWebSecurity + protected static class AuthenticationEntryPointContext extends + ResourceServerConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { @@ -177,7 +254,8 @@ public void configure(HttpSecurity http) throws Exception { } @Override - public void configure(ResourceServerSecurityConfigurer resources) throws Exception { + public void configure(ResourceServerSecurityConfigurer resources) + throws Exception { resources.authenticationEntryPoint(authenticationEntryPoint()); } @@ -190,9 +268,11 @@ private AuthenticationEntryPoint authenticationEntryPoint() { @Configuration @EnableResourceServer @EnableWebSecurity - protected static class TokenExtractorContext extends ResourceServerConfigurerAdapter { + protected static class TokenExtractorContext extends + ResourceServerConfigurerAdapter { @Override - public void configure(ResourceServerSecurityConfigurer resources) throws Exception { + public void configure(ResourceServerSecurityConfigurer resources) + throws Exception { resources.tokenExtractor(new TokenExtractor() { @Override @@ -216,10 +296,13 @@ public TokenStore tokenStore() { @Configuration @EnableResourceServer @EnableWebSecurity - protected static class ExpressionHandlerContext extends ResourceServerConfigurerAdapter { + protected static class ExpressionHandlerContext extends + ResourceServerConfigurerAdapter { @Override - public void configure(ResourceServerSecurityConfigurer resources) throws Exception { - resources.expressionHandler(new DefaultWebSecurityExpressionHandler()); + public void configure(ResourceServerSecurityConfigurer resources) + throws Exception { + resources + .expressionHandler(new DefaultWebSecurityExpressionHandler()); } @Override @@ -241,8 +324,8 @@ protected static class TokenServicesContext { @Bean protected ClientDetailsService clientDetailsService() { InMemoryClientDetailsService service = new InMemoryClientDetailsService(); - service.setClientDetailsStore(Collections.singletonMap("client", new BaseClientDetails("client", null, - null, null, null))); + service.setClientDetailsStore(Collections.singletonMap("client", + new BaseClientDetails("client", null, null, null, null))); return service; } diff --git a/tests/annotation/vanilla/src/test/java/demo/GlobalMethodSecurityTests.java b/tests/annotation/vanilla/src/test/java/demo/GlobalMethodSecurityTests.java new file mode 100644 index 000000000..5977d393d --- /dev/null +++ b/tests/annotation/vanilla/src/test/java/demo/GlobalMethodSecurityTests.java @@ -0,0 +1,29 @@ +package demo; + +import org.springframework.boot.test.SpringApplicationConfiguration; +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; + +@SpringApplicationConfiguration(classes = { Application.class, + GlobalSecurityConfiguration.class }) +public class GlobalMethodSecurityTests extends AbstractProtectedResourceTests { + + @Configuration + @EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true) + protected static class GlobalSecurityConfiguration extends + GlobalMethodSecurityConfiguration { + + @Override + protected MethodSecurityExpressionHandler createExpressionHandler() { + return new OAuth2MethodSecurityExpressionHandler(); + } + + } + +} From f51e5a028806c4b367769e69776a38974f3ce431 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 12 Mar 2015 16:18:12 +0000 Subject: [PATCH 405/831] Switch off Boot default authentication manager To fix gh-401 we added some smart stuff to the configuration of a DefaultTokenServices so that in a refresh grant there is a UserDetailsService available if one has been configured globally. Unfortunately when Spring Boot autconfig is on, it creates one that seems to take precedence over one created by the user. To switch that off we need to add a @Bean of type AuthenticationManager. --- .../jdbc/src/main/java/demo/Application.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/annotation/jdbc/src/main/java/demo/Application.java b/tests/annotation/jdbc/src/main/java/demo/Application.java index f3a8a4f23..aa748605a 100644 --- a/tests/annotation/jdbc/src/main/java/demo/Application.java +++ b/tests/annotation/jdbc/src/main/java/demo/Application.java @@ -7,6 +7,9 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Lazy; +import org.springframework.context.annotation.Scope; +import org.springframework.context.annotation.ScopedProxyMode; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter; @@ -139,6 +142,14 @@ public void init(AuthenticationManagerBuilder auth) throws Exception { .roles("USER"); // @formatter:on } + + // Force Spring Boot to switch off the default authentication manager: + @Bean + @Lazy + @Scope(proxyMode=ScopedProxyMode.TARGET_CLASS) + public AuthenticationManager authenticationManager(AuthenticationManagerBuilder auth) { + return auth.getOrBuild(); + } } From 04bf544d54b5dac9abc2dddf3e84dd4286880d43 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 12 Mar 2015 17:13:22 +0000 Subject: [PATCH 406/831] Neater solution to the JDBC authentication problem --- .../jdbc/src/main/java/demo/Application.java | 76 +++++++++---------- .../jdbc/src/main/resources/application.yml | 3 - 2 files changed, 36 insertions(+), 43 deletions(-) diff --git a/tests/annotation/jdbc/src/main/java/demo/Application.java b/tests/annotation/jdbc/src/main/java/demo/Application.java index aa748605a..b587d8331 100644 --- a/tests/annotation/jdbc/src/main/java/demo/Application.java +++ b/tests/annotation/jdbc/src/main/java/demo/Application.java @@ -7,9 +7,8 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Lazy; -import org.springframework.context.annotation.Scope; -import org.springframework.context.annotation.ScopedProxyMode; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter; @@ -46,13 +45,15 @@ public String home() { @Configuration @EnableResourceServer - protected static class ResourceServer extends ResourceServerConfigurerAdapter { + protected static class ResourceServer extends + ResourceServerConfigurerAdapter { @Autowired private TokenStore tokenStore; @Override - public void configure(ResourceServerSecurityConfigurer resources) throws Exception { + public void configure(ResourceServerSecurityConfigurer resources) + throws Exception { resources.tokenStore(tokenStore); } @@ -65,7 +66,8 @@ public void configure(HttpSecurity http) throws Exception { @Configuration @EnableAuthorizationServer - protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter { + protected static class OAuth2Config extends + AuthorizationServerConfigurerAdapter { @Autowired private AuthenticationManager auth; @@ -84,50 +86,55 @@ public JdbcTokenStore tokenStore() { protected AuthorizationCodeServices authorizationCodeServices() { return new JdbcAuthorizationCodeServices(dataSource); } - + @Override - public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { + public void configure(AuthorizationServerSecurityConfigurer security) + throws Exception { security.passwordEncoder(passwordEncoder); } @Override - public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + public void configure(AuthorizationServerEndpointsConfigurer endpoints) + throws Exception { endpoints.authorizationCodeServices(authorizationCodeServices()) - .authenticationManager(auth).tokenStore(tokenStore()).approvalStoreDisabled(); + .authenticationManager(auth).tokenStore(tokenStore()) + .approvalStoreDisabled(); } @Override - public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + public void configure(ClientDetailsServiceConfigurer clients) + throws Exception { // @formatter:off clients.jdbc(dataSource) - .passwordEncoder(passwordEncoder) - .withClient("my-trusted-client") - .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit") + .passwordEncoder(passwordEncoder) + .withClient("my-trusted-client") + .authorizedGrantTypes("password", "authorization_code", + "refresh_token", "implicit") .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") .scopes("read", "write", "trust") .resourceIds("oauth2-resource") - .accessTokenValiditySeconds(60) - .and() - .withClient("my-client-with-registered-redirect") + .accessTokenValiditySeconds(60).and() + .withClient("my-client-with-registered-redirect") .authorizedGrantTypes("authorization_code") - .authorities("ROLE_CLIENT") - .scopes("read", "trust") + .authorities("ROLE_CLIENT").scopes("read", "trust") .resourceIds("oauth2-resource") - .redirectUris("http://anywhere/?key=value") - .and() - .withClient("my-client-with-secret") + .redirectUris("http://anywhere/?key=value").and() + .withClient("my-client-with-secret") .authorizedGrantTypes("client_credentials", "password") - .authorities("ROLE_CLIENT") - .scopes("read") - .resourceIds("oauth2-resource") - .secret("secret"); + .authorities("ROLE_CLIENT").scopes("read") + .resourceIds("oauth2-resource").secret("secret"); // @formatter:on } } + // Global authentication configuration ordered *after* the one in Spring + // Boot (so the settings here overwrite the ones in Boot). The explicit + // order is not needed in Spring Boot 1.2.3 or greater. @Configuration - protected static class AuthenticationManagerConfiguration extends GlobalAuthenticationConfigurerAdapter { + @Order(Ordered.LOWEST_PRECEDENCE - 20) + protected static class AuthenticationManagerConfiguration extends + GlobalAuthenticationConfigurerAdapter { @Autowired private DataSource dataSource; @@ -135,21 +142,10 @@ protected static class AuthenticationManagerConfiguration extends GlobalAuthenti @Override public void init(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off - auth - .jdbcAuthentication().dataSource(dataSource) - .withUser("dave") - .password("secret") - .roles("USER"); + auth.jdbcAuthentication().dataSource(dataSource).withUser("dave") + .password("secret").roles("USER"); // @formatter:on } - - // Force Spring Boot to switch off the default authentication manager: - @Bean - @Lazy - @Scope(proxyMode=ScopedProxyMode.TARGET_CLASS) - public AuthenticationManager authenticationManager(AuthenticationManagerBuilder auth) { - return auth.getOrBuild(); - } } diff --git a/tests/annotation/jdbc/src/main/resources/application.yml b/tests/annotation/jdbc/src/main/resources/application.yml index df9f757f7..2817b5703 100644 --- a/tests/annotation/jdbc/src/main/resources/application.yml +++ b/tests/annotation/jdbc/src/main/resources/application.yml @@ -3,9 +3,6 @@ spring: name: jdbc management: context_path: /admin -security: - user: - password: password logging: level: org.springframework.security: DEBUG From cbe00d2512ca9c07c54dd081ccd18168e363f11c Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 13 Mar 2015 13:51:25 +0000 Subject: [PATCH 407/831] Add more comments about Boot 1.2.3 --- tests/annotation/jdbc/src/main/java/demo/Application.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/annotation/jdbc/src/main/java/demo/Application.java b/tests/annotation/jdbc/src/main/java/demo/Application.java index b587d8331..25de4cd05 100644 --- a/tests/annotation/jdbc/src/main/java/demo/Application.java +++ b/tests/annotation/jdbc/src/main/java/demo/Application.java @@ -130,7 +130,9 @@ public void configure(ClientDetailsServiceConfigurer clients) // Global authentication configuration ordered *after* the one in Spring // Boot (so the settings here overwrite the ones in Boot). The explicit - // order is not needed in Spring Boot 1.2.3 or greater. + // order is not needed in Spring Boot 1.2.3 or greater. (Actually with Boot + // 1.2.3 you don't need this inner class at all and you can just @Autowired + // the AuthenticationManagerBuilder). @Configuration @Order(Ordered.LOWEST_PRECEDENCE - 20) protected static class AuthenticationManagerConfiguration extends From 847e6ffde23e84b4f3e9de5940b892cd6f077a38 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 13 Mar 2015 17:50:17 +0000 Subject: [PATCH 408/831] Add explicit handler for HttpRequestMethodNotSupportedException Fixes gh-408 --- .../security/oauth2/provider/endpoint/TokenEndpoint.java | 6 ++++++ tests/annotation/jwt/src/main/resources/application.yml | 3 +++ tests/annotation/jwt/src/main/resources/logback.xml | 8 -------- 3 files changed, 9 insertions(+), 8 deletions(-) delete mode 100644 tests/annotation/jwt/src/main/resources/logback.xml diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java index bf559c8ee..4a802ee00 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java @@ -155,6 +155,12 @@ protected String getClientId(Principal principal) { return clientId; } + @ExceptionHandler(HttpRequestMethodNotSupportedException.class) + public void handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) throws Exception { + logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage()); + throw e; + } + @ExceptionHandler(Exception.class) public ResponseEntity handleException(Exception e) throws Exception { logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage()); diff --git a/tests/annotation/jwt/src/main/resources/application.yml b/tests/annotation/jwt/src/main/resources/application.yml index a9c0149f0..a7c74036e 100644 --- a/tests/annotation/jwt/src/main/resources/application.yml +++ b/tests/annotation/jwt/src/main/resources/application.yml @@ -6,3 +6,6 @@ management: security: user: password: password +logging: + level: + org.springframework.security: DEBUG \ No newline at end of file diff --git a/tests/annotation/jwt/src/main/resources/logback.xml b/tests/annotation/jwt/src/main/resources/logback.xml deleted file mode 100644 index 8ddbd55bf..000000000 --- a/tests/annotation/jwt/src/main/resources/logback.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - From 10e2c915982c8d48cded8379e6e3cf6fc2376b72 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 16 Mar 2015 13:28:09 +0000 Subject: [PATCH 409/831] Us UriComponentsBuilder instead of UrlEncoder Fixes gh-430 --- .../filter/OAuth2ClientContextFilter.java | 84 ++++++++++--------- .../OAuth2ClientContextFilterTests.java | 64 ++++++++++++-- 2 files changed, 102 insertions(+), 46 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilter.java index 8bb345548..f89706865 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilter.java @@ -2,7 +2,6 @@ import java.io.IOException; import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; import java.util.Map; import javax.servlet.Filter; @@ -24,6 +23,7 @@ import org.springframework.web.servlet.support.ServletUriComponentsBuilder; import org.springframework.web.util.NestedServletException; import org.springframework.web.util.UriComponents; +import org.springframework.web.util.UriComponentsBuilder; /** * Security filter for an OAuth2 client. @@ -34,8 +34,9 @@ public class OAuth2ClientContextFilter implements Filter, InitializingBean { /** - * Key in request attributes for the current URI in case it is needed by rest client code that needs to send a - * redirect URI to an authorization server. + * Key in request attributes for the current URI in case it is needed by + * rest client code that needs to send a redirect URI to an authorization + * server. */ public static final String CURRENT_URI = "currentUri"; @@ -44,10 +45,12 @@ public class OAuth2ClientContextFilter implements Filter, InitializingBean { private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); public void afterPropertiesSet() throws Exception { - Assert.notNull(redirectStrategy, "A redirect strategy must be supplied."); + Assert.notNull(redirectStrategy, + "A redirect strategy must be supplied."); } - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) + public void doFilter(ServletRequest servletRequest, + ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; @@ -55,19 +58,17 @@ public void doFilter(ServletRequest servletRequest, ServletResponse servletRespo try { chain.doFilter(servletRequest, servletResponse); - } - catch (IOException ex) { + } catch (IOException ex) { throw ex; - } - catch (Exception ex) { + } catch (Exception ex) { // Try to extract a SpringSecurityException from the stacktrace Throwable[] causeChain = throwableAnalyzer.determineCauseChain(ex); UserRedirectRequiredException redirect = (UserRedirectRequiredException) throwableAnalyzer - .getFirstThrowableOfType(UserRedirectRequiredException.class, causeChain); + .getFirstThrowableOfType( + UserRedirectRequiredException.class, causeChain); if (redirect != null) { redirectUser(redirect, request, response); - } - else { + } else { if (ex instanceof ServletException) { throw (ServletException) ex; } @@ -83,44 +84,44 @@ public void doFilter(ServletRequest servletRequest, ServletResponse servletRespo * Redirect the user according to the specified exception. * * @param resourceThatNeedsAuthorization - * @param e The user redirect exception. - * @param request The request. - * @param response The response. + * @param e + * The user redirect exception. + * @param request + * The request. + * @param response + * The response. */ - protected void redirectUser(UserRedirectRequiredException e, HttpServletRequest request, - HttpServletResponse response) throws IOException { + protected void redirectUser(UserRedirectRequiredException e, + HttpServletRequest request, HttpServletResponse response) + throws IOException { String redirectUri = e.getRedirectUri(); - StringBuilder builder = new StringBuilder(redirectUri); + UriComponentsBuilder builder = UriComponentsBuilder + .fromHttpUrl(redirectUri); Map requestParams = e.getRequestParams(); - char appendChar = redirectUri.indexOf('?') < 0 ? '?' : '&'; for (Map.Entry param : requestParams.entrySet()) { - try { - builder.append(appendChar).append(param.getKey()).append('=') - .append(URLEncoder.encode(param.getValue(), "UTF-8")); - } - catch (UnsupportedEncodingException uee) { - throw new IllegalStateException(uee); - } - appendChar = '&'; + builder.queryParam(param.getKey(), param.getValue()); } if (e.getStateKey() != null) { - builder.append(appendChar).append("state").append('=').append(e.getStateKey()); + builder.queryParam("state", e.getStateKey()); } - this.redirectStrategy.sendRedirect(request, response, builder.toString()); - + this.redirectStrategy.sendRedirect(request, response, builder.build() + .toUriString()); } /** * Calculate the current URI given the request. * - * @param request The request. + * @param request + * The request. * @return The current uri. */ - protected String calculateCurrentUri(HttpServletRequest request) throws UnsupportedEncodingException { - ServletUriComponentsBuilder builder = ServletUriComponentsBuilder.fromRequest(request); + protected String calculateCurrentUri(HttpServletRequest request) + throws UnsupportedEncodingException { + ServletUriComponentsBuilder builder = ServletUriComponentsBuilder + .fromRequest(request); // Now work around SPR-10172... String queryString = request.getQueryString(); boolean legalSpaces = queryString != null && queryString.contains("+"); @@ -128,18 +129,19 @@ protected String calculateCurrentUri(HttpServletRequest request) throws Unsuppor builder.replaceQuery(queryString.replace("+", "%20")); } UriComponents uri = null; - try { - uri = builder.replaceQueryParam("code").build(true); - } catch (IllegalArgumentException ex) { - // ignore failures to parse the url (including query string). does't make sense - // for redirection purposes anyway. - return null; - } + try { + uri = builder.replaceQueryParam("code").build(true); + } catch (IllegalArgumentException ex) { + // ignore failures to parse the url (including query string). does't + // make sense for redirection purposes anyway. + return null; + } String query = uri.getQuery(); if (legalSpaces) { query = query.replace("%20", "+"); } - return ServletUriComponentsBuilder.fromUri(uri.toUri()).replaceQuery(query).build().toString(); + return ServletUriComponentsBuilder.fromUri(uri.toUri()) + .replaceQuery(query).build().toString(); } public void init(FilterConfig filterConfig) throws ServletException { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilterTests.java index 1959a5dfa..2049a8592 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilterTests.java @@ -2,20 +2,70 @@ import static org.junit.Assert.assertEquals; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; + import org.junit.Test; +import org.mockito.Mockito; import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.security.oauth2.client.resource.UserRedirectRequiredException; +import org.springframework.security.web.RedirectStrategy; /** * @author Ryan Heaton + * @author Dave Syer */ public class OAuth2ClientContextFilterTests { + @Test + public void testVanillaRedirectUri() throws Exception { + String redirect = "http://example.com/authorize"; + Map params = new LinkedHashMap(); + params.put("foo", "bar"); + params.put("scope", "spam"); + testRedirectUri(redirect, params, redirect + "?foo=bar&scope=spam"); + } + + @Test + public void testRedirectUriWithUrlInParams() throws Exception { + String redirect = "http://example.com/authorize"; + Map params = Collections.singletonMap("redirect", + "http://foo/bar"); + testRedirectUri(redirect, params, redirect + "?redirect=http://foo/bar"); + } + + @Test + public void testRedirectUriWithQuery() throws Exception { + String redirect = "http://example.com/authorize?foo=bar"; + Map params = Collections.singletonMap("spam", + "bucket"); + testRedirectUri(redirect, params, redirect + "&spam=bucket"); + } + + public void testRedirectUri(String redirect, Map params, + String result) throws Exception { + OAuth2ClientContextFilter filter = new OAuth2ClientContextFilter(); + RedirectStrategy redirectStrategy = Mockito + .mock(RedirectStrategy.class); + filter.setRedirectStrategy(redirectStrategy); + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + UserRedirectRequiredException exception = new UserRedirectRequiredException( + redirect, params); + filter.redirectUser(exception, request, response); + Mockito.verify(redirectStrategy) + .sendRedirect(request, response, result); + } + @Test public void testVanillaCurrentUri() throws Exception { OAuth2ClientContextFilter filter = new OAuth2ClientContextFilter(); MockHttpServletRequest request = new MockHttpServletRequest(); request.setQueryString("foo=bar"); - assertEquals("http://localhost/?foo=bar", filter.calculateCurrentUri(request)); + assertEquals("http://localhost/?foo=bar", + filter.calculateCurrentUri(request)); } @Test @@ -23,7 +73,8 @@ public void testCurrentUriWithLegalSpaces() throws Exception { OAuth2ClientContextFilter filter = new OAuth2ClientContextFilter(); MockHttpServletRequest request = new MockHttpServletRequest(); request.setQueryString("foo=bar%20spam"); - assertEquals("http://localhost/?foo=bar%20spam", filter.calculateCurrentUri(request)); + assertEquals("http://localhost/?foo=bar%20spam", + filter.calculateCurrentUri(request)); } @Test @@ -38,7 +89,8 @@ public void testCurrentUriWithIllegalSpaces() throws Exception { OAuth2ClientContextFilter filter = new OAuth2ClientContextFilter(); MockHttpServletRequest request = new MockHttpServletRequest(); request.setQueryString("foo=bar+spam"); - assertEquals("http://localhost/?foo=bar+spam", filter.calculateCurrentUri(request)); + assertEquals("http://localhost/?foo=bar+spam", + filter.calculateCurrentUri(request)); } @Test @@ -46,7 +98,8 @@ public void testCurrentUriRemovingCode() throws Exception { OAuth2ClientContextFilter filter = new OAuth2ClientContextFilter(); MockHttpServletRequest request = new MockHttpServletRequest(); request.setQueryString("code=XXXX&foo=bar"); - assertEquals("http://localhost/?foo=bar", filter.calculateCurrentUri(request)); + assertEquals("http://localhost/?foo=bar", + filter.calculateCurrentUri(request)); } @Test @@ -54,7 +107,8 @@ public void testCurrentUriRemovingCodeInSecond() throws Exception { OAuth2ClientContextFilter filter = new OAuth2ClientContextFilter(); MockHttpServletRequest request = new MockHttpServletRequest(); request.setQueryString("foo=bar&code=XXXX"); - assertEquals("http://localhost/?foo=bar", filter.calculateCurrentUri(request)); + assertEquals("http://localhost/?foo=bar", + filter.calculateCurrentUri(request)); } @Test From 59f4c1ac7ca50b5749c21213416c93bc1eab8ece Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 16 Mar 2015 13:57:20 +0000 Subject: [PATCH 410/831] Bump Spring and Security patch versions --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 53e6c0459..388eec446 100644 --- a/pom.xml +++ b/pom.xml @@ -17,8 +17,8 @@ UTF-8 - 4.0.8.RELEASE - 3.2.5.RELEASE + 4.0.9.RELEASE + 3.2.6.RELEASE 1.6 @@ -67,7 +67,7 @@ spring4 - 4.1.0.BUILD-SNAPSHOT + 4.2.0.BUILD-SNAPSHOT From 4ef028fe142877a081ef1c6032f94c6b4ba7925a Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 16 Mar 2015 13:57:48 +0000 Subject: [PATCH 411/831] Add @EnableAuthorizationServer to tests that required them --- .../config/annotation/ResourceServerConfigurationTests.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java index d464f09af..3fc6257f3 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java @@ -32,6 +32,7 @@ import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; 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.config.annotation.web.configuration.ResourceServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; @@ -219,6 +220,7 @@ public TokenStore tokenStore() { @Configuration @EnableResourceServer + @EnableAuthorizationServer @EnableWebSecurity protected static class ResourceServerAndAuthorizationServerContext extends AuthorizationServerConfigurerAdapter { @@ -231,6 +233,7 @@ public void configure(ClientDetailsServiceConfigurer clients) @Configuration @EnableResourceServer + @EnableAuthorizationServer @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true) protected static class ResourceServerAndAuthorizationServerContextAndGlobalMethodSecurity From 8a1fb1349d9f9822b0231913e9484478d31aab0b Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 17 Mar 2015 11:29:44 +0000 Subject: [PATCH 412/831] Use existing JTI if there is one as ATI in a refresh token When a token is refreshed the access token itself is re-enhanced and so you have to pick out the derived fields from additionalInfo if there are any. Fixes gh-429 --- .../token/store/JwtAccessTokenConverter.java | 84 ++++++++++----- .../DefaultTokenServicesWithJwtTests.java | 61 ++++++++++- .../store/JwtAccessTokenConverterTests.java | 100 ++++++++++++------ 3 files changed, 185 insertions(+), 60 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java index 9f792d700..dda4fe913 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverter.java @@ -49,8 +49,9 @@ import org.springframework.util.Assert; /** - * Helper that translates between JWT encoded token values and OAuth authentication information (in both directions). - * Also acts as a {@link TokenEnhancer} when tokens are granted. + * Helper that translates between JWT encoded token values and OAuth authentication + * information (in both directions). Also acts as a {@link TokenEnhancer} when tokens are + * granted. * * @see TokenEnhancer * @see AccessTokenConverter @@ -58,7 +59,8 @@ * @author Dave Syer * @author Luke Taylor */ -public class JwtAccessTokenConverter implements TokenEnhancer, AccessTokenConverter, InitializingBean { +public class JwtAccessTokenConverter implements TokenEnhancer, AccessTokenConverter, + InitializingBean { /** * Field name for token id. @@ -99,7 +101,8 @@ public AccessTokenConverter getAccessTokenConverter() { } @Override - public Map convertAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) { + public Map convertAccessToken(OAuth2AccessToken token, + OAuth2Authentication authentication) { return tokenConverter.convertAccessToken(token, authentication); } @@ -124,19 +127,21 @@ public Map getKey() { result.put("value", verifierKey); return result; } - + public void setKeyPair(KeyPair keyPair) { PrivateKey privateKey = keyPair.getPrivate(); Assert.state(privateKey instanceof RSAPrivateKey, "KeyPair must be an RSA "); signer = new RsaSigner((RSAPrivateKey) privateKey); RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); verifier = new RsaVerifier(publicKey); - verifierKey = "-----BEGIN PUBLIC KEY-----\n" + new String(Base64.encode(publicKey.getEncoded())) + "\n-----END PUBLIC KEY-----"; + verifierKey = "-----BEGIN PUBLIC KEY-----\n" + + new String(Base64.encode(publicKey.getEncoded())) + + "\n-----END PUBLIC KEY-----"; } /** - * Sets the JWT signing key. It can be either a simple MAC key or an RSA key. RSA keys should be in OpenSSH format, - * as produced by ssh-keygen. + * Sets the JWT signing key. It can be either a simple MAC key or an RSA key. RSA keys + * should be in OpenSSH format, as produced by ssh-keygen. * * @param key the key to be used for signing JWTs. */ @@ -163,7 +168,7 @@ public void setSigningKey(String key) { private boolean isPublic(String key) { return key.startsWith("-----BEGIN"); } - + /** * @return true if the signing key is a public key */ @@ -172,11 +177,12 @@ public boolean isPublic() { } /** - * The key used for verifying signatures produced by this class. This is not used but is returned from the endpoint - * to allow resource servers to obtain the key. + * The key used for verifying signatures produced by this class. This is not used but + * is returned from the endpoint to allow resource servers to obtain the key. * - * For an HMAC key it will be the same value as the signing key and does not need to be set. For and RSA key, it - * should be set to the String representation of the public key, in a standard format (e.g. OpenSSH keys) + * For an HMAC key it will be the same value as the signing key and does not need to + * be set. For and RSA key, it should be set to the String representation of the + * public key, in a standard format (e.g. OpenSSH keys) * * @param key the signature verification key (typically an RSA public key) */ @@ -184,49 +190,71 @@ public void setVerifierKey(String key) { this.verifierKey = key; try { new RsaSigner(verifierKey); - throw new IllegalArgumentException("Private key cannot be set as verifierKey property"); + throw new IllegalArgumentException( + "Private key cannot be set as verifierKey property"); } catch (Exception expected) { // Expected } } - public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { + public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, + OAuth2Authentication authentication) { DefaultOAuth2AccessToken result = new DefaultOAuth2AccessToken(accessToken); - Map info = new LinkedHashMap(accessToken.getAdditionalInformation()); + Map info = new LinkedHashMap( + accessToken.getAdditionalInformation()); String tokenId = result.getValue(); if (!info.containsKey(TOKEN_ID)) { info.put(TOKEN_ID, tokenId); } + else { + tokenId = (String) info.get(TOKEN_ID); + } result.setAdditionalInformation(info); result.setValue(encode(result, authentication)); OAuth2RefreshToken refreshToken = result.getRefreshToken(); if (refreshToken != null) { - DefaultOAuth2AccessToken encodedRefreshToken = new DefaultOAuth2AccessToken(accessToken); + DefaultOAuth2AccessToken encodedRefreshToken = new DefaultOAuth2AccessToken( + accessToken); encodedRefreshToken.setValue(refreshToken.getValue()); - Map refreshTokenInfo = new LinkedHashMap(accessToken.getAdditionalInformation()); + try { + Map claims = objectMapper.parseMap(JwtHelper.decode( + refreshToken.getValue()).getClaims()); + if (claims.containsKey(TOKEN_ID)) { + encodedRefreshToken.setValue(claims.get(TOKEN_ID).toString()); + } + } + catch (IllegalArgumentException e) { + } + Map refreshTokenInfo = new LinkedHashMap( + accessToken.getAdditionalInformation()); refreshTokenInfo.put(TOKEN_ID, encodedRefreshToken.getValue()); refreshTokenInfo.put(ACCESS_TOKEN_ID, tokenId); encodedRefreshToken.setAdditionalInformation(refreshTokenInfo); - DefaultOAuth2RefreshToken token = new DefaultOAuth2RefreshToken(encode(encodedRefreshToken, authentication)); + DefaultOAuth2RefreshToken token = new DefaultOAuth2RefreshToken(encode( + encodedRefreshToken, authentication)); if (refreshToken instanceof ExpiringOAuth2RefreshToken) { - Date expiration = ((ExpiringOAuth2RefreshToken) refreshToken).getExpiration(); + Date expiration = ((ExpiringOAuth2RefreshToken) refreshToken) + .getExpiration(); encodedRefreshToken.setExpiration(expiration); - token = new DefaultExpiringOAuth2RefreshToken(encode(encodedRefreshToken, authentication), expiration); + token = new DefaultExpiringOAuth2RefreshToken(encode(encodedRefreshToken, + authentication), expiration); } result.setRefreshToken(token); } return result; } - + public boolean isRefreshToken(OAuth2AccessToken token) { return token.getAdditionalInformation().containsKey(ACCESS_TOKEN_ID); } - protected String encode(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { + protected String encode(OAuth2AccessToken accessToken, + OAuth2Authentication authentication) { String content; try { - content = objectMapper.formatMap(tokenConverter.convertAccessToken(accessToken, authentication)); + content = objectMapper.formatMap(tokenConverter.convertAccessToken( + accessToken, authentication)); } catch (Exception e) { throw new IllegalStateException("Cannot convert access token to JSON", e); @@ -270,9 +298,11 @@ public void afterPropertiesSet() throws Exception { logger.error("Signing and verification RSA keys do not match"); } } - else if (verifier instanceof MacSigner){ - // Avoid a race condition where setters are called in the wrong order. Use of == is intentional. - Assert.state(this.signingKey == this.verifierKey, + else if (verifier instanceof MacSigner) { + // Avoid a race condition where setters are called in the wrong order. Use of + // == is intentional. + Assert.state( + this.signingKey == this.verifierKey, "For MAC signing you do not need to specify the verifier key separately, and if you do it must match the signing key"); } this.verifier = verifier; diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithJwtTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithJwtTests.java index 9cdcb5323..b7753f9b8 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithJwtTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesWithJwtTests.java @@ -1,9 +1,22 @@ package org.springframework.security.oauth2.provider.token; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotSame; + +import java.util.Collections; +import java.util.Map; + +import org.junit.Test; +import org.springframework.security.jwt.JwtHelper; +import org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +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.TokenRequest; import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; - /** * @author Ryan Heaton * @author Dave Syer @@ -19,7 +32,7 @@ protected TokenStore createTokenStore() { tokenStore = new JwtTokenStore(enhancer); return tokenStore; } - + @Override protected void configureTokenServices(DefaultTokenServices services) throws Exception { enhancer.afterPropertiesSet(); @@ -27,4 +40,48 @@ protected void configureTokenServices(DefaultTokenServices services) throws Exce super.configureTokenServices(services); } + @Test + public void testRefreshedTokenHasIdThatMatchesAccessToken() throws Exception { + JsonParser parser = JsonParserFactory.create(); + OAuth2Authentication authentication = createAuthentication(); + OAuth2AccessToken initialToken = getTokenServices().createAccessToken( + authentication); + ExpiringOAuth2RefreshToken expectedExpiringRefreshToken = (ExpiringOAuth2RefreshToken) initialToken + .getRefreshToken(); + TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap( + "client_id", "id"), "id", null, null); + OAuth2AccessToken refreshedAccessToken = getTokenServices().refreshAccessToken( + expectedExpiringRefreshToken.getValue(), tokenRequest); + Map accessTokenInfo = parser.parseMap(JwtHelper.decode( + refreshedAccessToken.getValue()).getClaims()); + Map refreshTokenInfo = parser.parseMap(JwtHelper.decode( + refreshedAccessToken.getRefreshToken().getValue()).getClaims()); + assertEquals("Access token ID does not match refresh token ATI", + accessTokenInfo.get(AccessTokenConverter.JTI), + refreshTokenInfo.get(AccessTokenConverter.ATI)); + assertNotSame("Refresh token re-used", expectedExpiringRefreshToken.getValue(), + refreshedAccessToken.getRefreshToken().getValue()); + } + + @Test + public void testDoubleRefresh() throws Exception { + JsonParser parser = JsonParserFactory.create(); + OAuth2Authentication authentication = createAuthentication(); + OAuth2AccessToken initialToken = getTokenServices().createAccessToken( + authentication); + TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap( + "client_id", "id"), "id", null, null); + OAuth2AccessToken refreshedAccessToken = getTokenServices().refreshAccessToken( + initialToken.getRefreshToken().getValue(), tokenRequest); + refreshedAccessToken = getTokenServices().refreshAccessToken( + refreshedAccessToken.getRefreshToken().getValue(), tokenRequest); + Map accessTokenInfo = parser.parseMap(JwtHelper.decode( + refreshedAccessToken.getValue()).getClaims()); + Map refreshTokenInfo = parser.parseMap(JwtHelper.decode( + refreshedAccessToken.getRefreshToken().getValue()).getClaims()); + assertEquals("Access token ID does not match refresh token ATI", + accessTokenInfo.get(AccessTokenConverter.JTI), + refreshTokenInfo.get(AccessTokenConverter.ATI)); + } + } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverterTests.java index 137e10207..9fcd9d19d 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/JwtAccessTokenConverterTests.java @@ -9,9 +9,12 @@ */ package org.springframework.security.oauth2.provider.token.store; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import java.security.KeyPair; +import java.util.Arrays; import java.util.Collections; import java.util.Map; import java.util.Set; @@ -26,6 +29,8 @@ import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.DefaultOAuth2RefreshToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; +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.OAuth2Request; import org.springframework.security.oauth2.provider.token.AccessTokenConverter; @@ -49,20 +54,25 @@ public void setUp() throws Exception { @Test public void testEnhanceAccessToken() { - OAuth2Authentication authentication = new OAuth2Authentication(createOAuth2Request("foo", null), - userAuthentication); - OAuth2AccessToken token = tokenEnhancer.enhance(new DefaultOAuth2AccessToken("FOO"), authentication); + OAuth2Authentication authentication = new OAuth2Authentication( + createOAuth2Request("foo", null), userAuthentication); + OAuth2AccessToken token = tokenEnhancer.enhance(new DefaultOAuth2AccessToken( + "FOO"), authentication); assertNotNull(token.getValue()); - assertEquals("FOO", token.getAdditionalInformation().get(AccessTokenConverter.JTI)); + assertEquals("FOO", token.getAdditionalInformation() + .get(AccessTokenConverter.JTI)); String claims = JwtHelper.decode(token.getValue()).getClaims(); - assertTrue("Wrong claims: " + claims, claims.contains("\"" + AccessTokenConverter.JTI + "\"")); - assertTrue("Wrong claims: " + claims, claims.contains("\"" + UserAuthenticationConverter.USERNAME + "\"")); + assertTrue("Wrong claims: " + claims, + claims.contains("\"" + AccessTokenConverter.JTI + "\":\"FOO\"")); + assertTrue("Wrong claims: " + claims, + claims.contains("\"" + UserAuthenticationConverter.USERNAME + "\"")); } @Test public void testScopePreserved() { - OAuth2Authentication authentication = new OAuth2Authentication(createOAuth2Request("foo", - Collections.singleton("read")), userAuthentication); + OAuth2Authentication authentication = new OAuth2Authentication( + createOAuth2Request("foo", Collections.singleton("read")), + userAuthentication); DefaultOAuth2AccessToken original = new DefaultOAuth2AccessToken("FOO"); original.setScope(authentication.getOAuth2Request().getScope()); OAuth2AccessToken token = tokenEnhancer.enhance(original, authentication); @@ -72,19 +82,45 @@ public void testScopePreserved() { @Test public void testRefreshTokenAdded() throws Exception { - OAuth2Authentication authentication = new OAuth2Authentication(createOAuth2Request("foo", - Collections.singleton("read")), userAuthentication); + OAuth2Authentication authentication = new OAuth2Authentication( + createOAuth2Request("foo", Collections.singleton("read")), + userAuthentication); DefaultOAuth2AccessToken original = new DefaultOAuth2AccessToken("FOO"); original.setScope(authentication.getOAuth2Request().getScope()); original.setRefreshToken(new DefaultOAuth2RefreshToken("BAR")); OAuth2AccessToken token = tokenEnhancer.enhance(original, authentication); assertNotNull(token.getValue()); assertNotNull(token.getRefreshToken()); - String claims = JwtHelper.decode(token.getRefreshToken().getValue()).getClaims(); - assertTrue("Wrong claims: " + claims, claims.contains("\"" + AccessTokenConverter.SCOPE + "\"")); + JsonParser parser = JsonParserFactory.create(); + Map claims = parser.parseMap(JwtHelper.decode( + token.getRefreshToken().getValue()).getClaims()); + assertEquals(Arrays.asList("read"), claims.get(AccessTokenConverter.SCOPE)); + assertEquals("FOO", claims.get(AccessTokenConverter.ATI)); + assertEquals("BAR", claims.get(AccessTokenConverter.JTI)); tokenEnhancer.afterPropertiesSet(); - assertTrue(tokenEnhancer.isRefreshToken(tokenEnhancer.extractAccessToken(token.getRefreshToken().getValue(), - tokenEnhancer.decode(token.getRefreshToken().getValue())))); + assertTrue(tokenEnhancer.isRefreshToken(tokenEnhancer.extractAccessToken(token + .getRefreshToken().getValue(), tokenEnhancer.decode(token + .getRefreshToken().getValue())))); + } + + @Test + public void testRefreshTokenAccessTokenIdWhenDoubleEnhanced() throws Exception { + OAuth2Authentication authentication = new OAuth2Authentication( + createOAuth2Request("foo", Collections.singleton("read")), + userAuthentication); + DefaultOAuth2AccessToken original = new DefaultOAuth2AccessToken("FOO"); + original.setScope(authentication.getOAuth2Request().getScope()); + original.setRefreshToken(new DefaultOAuth2RefreshToken("BAR")); + OAuth2AccessToken token = tokenEnhancer.enhance(original, authentication); + token = tokenEnhancer.enhance(token, authentication); + assertNotNull(token.getValue()); + assertNotNull(token.getRefreshToken()); + JsonParser parser = JsonParserFactory.create(); + Map claims = parser.parseMap(JwtHelper.decode( + token.getRefreshToken().getValue()).getClaims()); + assertEquals(Arrays.asList("read"), claims.get(AccessTokenConverter.SCOPE)); + assertEquals("FOO", claims.get(AccessTokenConverter.ATI)); + assertEquals("Wrong claims: " + claims, "BAR", claims.get(AccessTokenConverter.JTI)); } @Test @@ -99,12 +135,13 @@ public void rsaKeyCreatesValidRsaSignedTokens() throws Exception { + "jlzxSzwVkoZo+vef7OD6OcFLeInAHzAJAjEAs6izolK+3ETa1CRSwz0lPHQlnmdM\n" + "Y/QuR5tuPt6U/saEVuJpkn4LNRtg5qt6I4JRAjAgFRYTG7irBB/wmZFp47izXEc3\n" + "gOdvA1hvq3tlWU5REDrYt24xpviA0fvrJpwMPbECMAKDKdiDi6Q4/iBkkzNMefA8\n" - + "7HX27b9LR33don/1u/yvzMUo+lrRdKAFJ+9GPE9XFA== \n" + "-----END RSA PRIVATE KEY----- "; + + "7HX27b9LR33don/1u/yvzMUo+lrRdKAFJ+9GPE9XFA== \n" + + "-----END RSA PRIVATE KEY----- "; tokenEnhancer.setSigningKey(rsaKey); - OAuth2Authentication authentication = new OAuth2Authentication(createOAuth2Request("foo", null), - userAuthentication); - OAuth2AccessToken token = tokenEnhancer.enhance(new DefaultOAuth2AccessToken("FOO"), authentication); - System.err.println(token.getValue()); + OAuth2Authentication authentication = new OAuth2Authentication( + createOAuth2Request("foo", null), userAuthentication); + OAuth2AccessToken token = tokenEnhancer.enhance(new DefaultOAuth2AccessToken( + "FOO"), authentication); JwtHelper.decodeAndVerify(token.getValue(), new RsaVerifier(rsaKey)); } @@ -112,19 +149,20 @@ public void rsaKeyCreatesValidRsaSignedTokens() throws Exception { public void publicKeyStringIsReturnedFromTokenKeyEndpoint() throws Exception { tokenEnhancer.setVerifierKey("-----BEGIN RSA PUBLIC KEY-----\n" + "MGgCYQDk3m+AGfjcDrT4fspyIBqmulFjVXuiciYvpaD5j2XaR7c6Krm5wsBLOiUo\n" - + "kmd6wbrRAMPMpoC1eogWNNoXY7Jd4eWdDVmscfHczGX13uBKXwdOCEqKqoWQsXIb\n" + "7kgz+HkCAwEAAQ==\n" - + "-----END RSA PUBLIC KEY-----"); + + "kmd6wbrRAMPMpoC1eogWNNoXY7Jd4eWdDVmscfHczGX13uBKXwdOCEqKqoWQsXIb\n" + + "7kgz+HkCAwEAAQ==\n" + "-----END RSA PUBLIC KEY-----"); tokenEnhancer.afterPropertiesSet(); Map key = tokenEnhancer.getKey(); assertTrue("Wrong key: " + key, key.get("value").contains("-----BEGIN")); } @Test - public void publicKeyStringIsReturnedFromTokenKeyEndpointWithNullPrincipal() throws Exception { + public void publicKeyStringIsReturnedFromTokenKeyEndpointWithNullPrincipal() + throws Exception { tokenEnhancer.setVerifierKey("-----BEGIN RSA PUBLIC KEY-----\n" + "MGgCYQDk3m+AGfjcDrT4fspyIBqmulFjVXuiciYvpaD5j2XaR7c6Krm5wsBLOiUo\n" - + "kmd6wbrRAMPMpoC1eogWNNoXY7Jd4eWdDVmscfHczGX13uBKXwdOCEqKqoWQsXIb\n" + "7kgz+HkCAwEAAQ==\n" - + "-----END RSA PUBLIC KEY-----"); + + "kmd6wbrRAMPMpoC1eogWNNoXY7Jd4eWdDVmscfHczGX13uBKXwdOCEqKqoWQsXIb\n" + + "7kgz+HkCAwEAAQ==\n" + "-----END RSA PUBLIC KEY-----"); Map key = tokenEnhancer.getKey(); assertTrue("Wrong key: " + key, key.get("value").contains("-----BEGIN")); } @@ -144,8 +182,8 @@ public void keysNotMatchingWithMacSigner() throws Exception { @Test public void rsaKeyPair() throws Exception { - KeyStoreKeyFactory factory = new KeyStoreKeyFactory(new ClassPathResource("keystore.jks"), - "foobar".toCharArray()); + KeyStoreKeyFactory factory = new KeyStoreKeyFactory(new ClassPathResource( + "keystore.jks"), "foobar".toCharArray()); KeyPair keys = factory.getKeyPair("test"); tokenEnhancer.setKeyPair(keys); tokenEnhancer.afterPropertiesSet(); @@ -156,8 +194,8 @@ public void rsaKeyPair() throws Exception { public void publicKeyOnlyAllowedForVerification() throws Exception { tokenEnhancer.setVerifierKey("-----BEGIN RSA PUBLIC KEY-----\n" + "MGgCYQDk3m+AGfjcDrT4fspyIBqmulFjVXuiciYvpaD5j2XaR7c6Krm5wsBLOiUo\n" - + "kmd6wbrRAMPMpoC1eogWNNoXY7Jd4eWdDVmscfHczGX13uBKXwdOCEqKqoWQsXIb\n" + "7kgz+HkCAwEAAQ==\n" - + "-----END RSA PUBLIC KEY-----"); + + "kmd6wbrRAMPMpoC1eogWNNoXY7Jd4eWdDVmscfHczGX13uBKXwdOCEqKqoWQsXIb\n" + + "7kgz+HkCAwEAAQ==\n" + "-----END RSA PUBLIC KEY-----"); tokenEnhancer.afterPropertiesSet(); tokenEnhancer .decode("eyJhbGciOiJSUzI1NiJ9.eyJ1c2VyX25hbWUiOiJ0ZXN0MiIsImp0aSI6IkZPTyIsImNsaWVudF9pZCI6ImZvbyJ9.b43ob1ALSIwr_J2oEnfMhsXvYkr1qVBNhigNH2zlaE1OQLhLfT-DMlFtHcyUlyap0C2n0q61SPaGE_z715TV0uTAv2YKDN4fKZz2bMR7eHLsvaaCuvs7KCOi_aSROaUG"); @@ -166,8 +204,8 @@ public void publicKeyOnlyAllowedForVerification() throws Exception { } private OAuth2Request createOAuth2Request(String clientId, Set scope) { - return new OAuth2Request(Collections. emptyMap(), clientId, null, true, scope, null, null, - null, null); + return new OAuth2Request(Collections. emptyMap(), clientId, null, + true, scope, null, null, null, null); } protected static class TestAuthentication extends AbstractAuthenticationToken { From 9823898f5d8da3dbfd4290e0e861574bab948cca Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 17 Mar 2015 11:56:18 +0000 Subject: [PATCH 413/831] Pass authorities through from claims in client credentials token A client credentials token has authorities, but these were not being passed on from the claims to the OAuthAuthentication in the DefaultAccessTokenConverter. Fixes gh-431 --- .../provider/token/DefaultAccessTokenConverter.java | 10 +++++++++- .../token/DefaultAccessTokenConverterTests.java | 2 ++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java index 2ea5b0496..b03b40fb8 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java @@ -22,6 +22,7 @@ import java.util.Set; import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; @@ -131,7 +132,14 @@ public OAuth2Authentication extractAuthentication(Map map) { @SuppressWarnings("unchecked") Set resourceIds = new LinkedHashSet(map.containsKey(AUD) ? (Collection) map.get(AUD) : Collections.emptySet()); - OAuth2Request request = new OAuth2Request(parameters, clientId, null, true, scope, resourceIds, null, null, + + Collection authorities = null; + if (user==null && map.containsKey(AUTHORITIES)) { + @SuppressWarnings("unchecked") + String[] roles = ((Collection)map.get(AUTHORITIES)).toArray(new String[0]); + authorities = AuthorityUtils.createAuthorityList(roles); + } + OAuth2Request request = new OAuth2Request(parameters, clientId, authorities, true, scope, resourceIds, null, null, null); return new OAuth2Authentication(request, user); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverterTests.java index 1d5e07314..b1e8f3ce5 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverterTests.java @@ -63,6 +63,7 @@ public void extractAuthentication() { assertEquals(singleton(ROLE_USER), map.get(AccessTokenConverter.AUTHORITIES)); OAuth2Authentication extracted = converter.extractAuthentication(map); assertTrue(extracted.getOAuth2Request().getResourceIds().contains("resource")); + assertEquals("[ROLE_USER]", extracted.getAuthorities().toString()); } @Test @@ -77,6 +78,7 @@ public void extractAuthenticationFromClientToken() { assertEquals(singleton(ROLE_CLIENT), map.get(AccessTokenConverter.AUTHORITIES)); OAuth2Authentication extracted = converter.extractAuthentication(map); assertTrue(extracted.getOAuth2Request().getResourceIds().contains("resource")); + assertEquals("[ROLE_CLIENT]", extracted.getAuthorities().toString()); } } From ebddd5bc362a09530901241c011e5f56f9bc7585 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 18 Mar 2015 11:27:44 +0000 Subject: [PATCH 414/831] Make samples work with Spring 4.2 Changed profile spring4->springNext and fixed dependencies. Also had to explicitly use Jackson2 in tonr2. Fixes gh-416 --- pom.xml | 113 +++++++++++++++++- samples/oauth2/sparklr/pom.xml | 6 - samples/oauth2/tonr/pom.xml | 28 +++-- .../oauth/examples/config/WebMvcConfig.java | 8 +- .../examples/tonr/mvc/FacebookController.java | 9 +- spring-security-oauth/pom.xml | 12 +- spring-security-oauth2/pom.xml | 13 +- 7 files changed, 139 insertions(+), 50 deletions(-) diff --git a/pom.xml b/pom.xml index 388eec446..00fd283a3 100644 --- a/pom.xml +++ b/pom.xml @@ -65,7 +65,7 @@ - spring4 + springNext 4.2.0.BUILD-SNAPSHOT @@ -158,6 +158,117 @@ + + + + org.springframework + spring-aop + ${spring.version} + + + + org.springframework + spring-beans + ${spring.version} + + + + org.springframework + spring-core + ${spring.version} + + + + org.springframework + spring-context + ${spring.version} + + + + org.springframework + spring-expression + ${spring.version} + + + + org.springframework + spring-aop + ${spring.version} + true + + + + org.springframework + spring-jdbc + ${spring.version} + true + + + + org.springframework + spring-tx + ${spring.version} + + + + org.springframework + spring-web + ${spring.version} + + + + org.springframework + spring-webmvc + ${spring.version} + + + + org.springframework + spring-test + ${spring.version} + test + + + + org.springframework.security + spring-security-core + ${spring.security.version} + + + + org.springframework.security + spring-security-config + ${spring.security.version} + + + + org.springframework.security + spring-security-jwt + ${spring.security.jwt.version} + true + + + + org.springframework.security + spring-security-web + ${spring.security.version} + + + org.springframework + spring-tx + + + + + + org.springframework.security + spring-security-taglibs + ${spring.security.version} + + + + + diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 422365c89..1e1ee7f99 100644 --- a/samples/oauth2/sparklr/pom.xml +++ b/samples/oauth2/sparklr/pom.xml @@ -123,38 +123,32 @@ org.springframework spring-web - ${spring.version} org.springframework spring-jdbc - ${spring.version} org.springframework spring-webmvc - ${spring.version} org.springframework spring-test - ${spring.version} test org.springframework spring-tx - ${spring.version} org.springframework.security spring-security-taglibs - ${spring.security.version} diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index ac54a4f11..490529578 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -1,4 +1,5 @@ - + 4.0.0 @@ -124,62 +125,65 @@ ${project.groupId} spring-security-oauth2 ${project.version} + + + org.codehaus.jackson + jackson-mapper-asl + + org.springframework.security spring-security-taglibs - ${spring.security.version} org.springframework - spring-webmvc - ${spring.version} + spring-web org.springframework - spring-web - ${spring.version} + spring-webmvc org.springframework spring-jdbc - ${spring.version} org.springframework spring-context - ${spring.version} org.springframework spring-aop - ${spring.version} org.springframework spring-expression - ${spring.version} org.springframework spring-tx - ${spring.version} org.springframework spring-test - ${spring.version} test + + + com.fasterxml.jackson.core + jackson-databind + 2.3.2 + javax.servlet diff --git a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/WebMvcConfig.java b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/WebMvcConfig.java index 7c56d5917..a6103958c 100644 --- a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/WebMvcConfig.java +++ b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/WebMvcConfig.java @@ -14,7 +14,7 @@ import org.springframework.http.MediaType; import org.springframework.http.converter.BufferedImageHttpMessageConverter; import org.springframework.http.converter.HttpMessageConverter; -import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.security.oauth.examples.tonr.SparklrService; import org.springframework.security.oauth.examples.tonr.converter.AccessTokenRequestConverter; import org.springframework.security.oauth.examples.tonr.impl.SparklrServiceImpl; @@ -39,7 +39,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.view.ContentNegotiatingViewResolver; import org.springframework.web.servlet.view.InternalResourceViewResolver; -import org.springframework.web.servlet.view.json.MappingJacksonJsonView; +import org.springframework.web.servlet.view.json.MappingJackson2JsonView; @Configuration @EnableWebMvc @@ -57,7 +57,7 @@ public ContentNegotiatingViewResolver contentViewResolver() throws Exception { ContentNegotiationManagerFactoryBean contentNegotiationManager = new ContentNegotiationManagerFactoryBean(); contentNegotiationManager.addMediaType("json", MediaType.APPLICATION_JSON); contentViewResolver.setContentNegotiationManager(contentNegotiationManager.getObject()); - contentViewResolver.setDefaultViews(Arrays. asList(new MappingJacksonJsonView())); + contentViewResolver.setDefaultViews(Arrays. asList(new MappingJackson2JsonView())); return contentViewResolver; } @@ -208,7 +208,7 @@ public OAuth2ProtectedResourceDetails trusted() { @Bean public OAuth2RestTemplate facebookRestTemplate(OAuth2ClientContext clientContext) { OAuth2RestTemplate template = new OAuth2RestTemplate(facebook(), clientContext); - MappingJacksonHttpMessageConverter converter = new MappingJacksonHttpMessageConverter(); + MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); converter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON, MediaType.valueOf("text/javascript"))); template.setMessageConverters(Arrays.> asList(converter)); diff --git a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/mvc/FacebookController.java b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/mvc/FacebookController.java index 7d10f8aa3..7854df129 100644 --- a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/mvc/FacebookController.java +++ b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/mvc/FacebookController.java @@ -2,14 +2,15 @@ import java.util.ArrayList; -import org.codehaus.jackson.JsonNode; -import org.codehaus.jackson.node.ArrayNode; -import org.codehaus.jackson.node.ObjectNode; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.client.RestOperations; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + /** * @author Ryan Heaton * @author Dave Syer @@ -26,7 +27,7 @@ public String photos(Model model) throws Exception { ArrayNode data = (ArrayNode) result.get("data"); ArrayList friends = new ArrayList(); for (JsonNode dataNode : data) { - friends.add(dataNode.get("name").getTextValue()); + friends.add(dataNode.get("name").asText()); } model.addAttribute("friends", friends); return "facebook"; diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index e1b7615dd..ccd55e19e 100644 --- a/spring-security-oauth/pom.xml +++ b/spring-security-oauth/pom.xml @@ -52,67 +52,57 @@ org.springframework spring-beans - ${spring.version} org.springframework spring-core - ${spring.version} org.springframework spring-context - ${spring.version} org.springframework spring-web - ${spring.version} org.springframework spring-aop - ${spring.version} org.springframework spring-jdbc - ${spring.version} true org.springframework spring-test - ${spring.version} test org.springframework.security spring-security-core - ${spring.security.version} org.springframework.security spring-security-config - ${spring.security.version} org.springframework.security spring-security-web - ${spring.security.version} @@ -126,7 +116,7 @@ javax.servlet-api 3.0.1 - provided + true diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index e134530fc..5f485ff02 100644 --- a/spring-security-oauth2/pom.xml +++ b/spring-security-oauth2/pom.xml @@ -60,81 +60,70 @@ javax.servlet-api 3.0.1 - provided + true org.springframework spring-beans - ${spring.version} org.springframework spring-core - ${spring.version} org.springframework spring-context - ${spring.version} org.springframework spring-aop - ${spring.version} true org.springframework spring-jdbc - ${spring.version} true org.springframework spring-webmvc - ${spring.version} org.springframework spring-test - ${spring.version} test org.springframework.security spring-security-core - ${spring.security.version} org.springframework.security spring-security-config - ${spring.security.version} org.springframework.security spring-security-jwt - ${spring.security.jwt.version} true org.springframework.security spring-security-web - ${spring.security.version} org.springframework From 80e6711c3243481a1ef5afb064070b26194a990f Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 18 Mar 2015 11:57:49 +0000 Subject: [PATCH 415/831] Ensure client credentials grants work with ClientTokenServices ClientTokenServices is pure optimization (global cache for access tokens basically) so nothing is broken without this change, but now at least the tokens will be cached for all grant types. Fixes gh-434 --- .../client/token/AccessTokenProviderChain.java | 2 +- .../client/token/JdbcClientTokenServices.java | 3 ++- .../client/token/AccessTokenProviderChainTests.java | 13 +++++++++++++ .../client/token/JdbcClientTokenServicesTests.java | 11 +++++++++++ 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/AccessTokenProviderChain.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/AccessTokenProviderChain.java index 0349b2aff..c41748477 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/AccessTokenProviderChain.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/AccessTokenProviderChain.java @@ -122,7 +122,7 @@ public OAuth2AccessToken obtainAccessToken(OAuth2ProtectedResourceDetails resour } } - if (clientTokenServices != null && auth != null && auth.isAuthenticated()) { + if (clientTokenServices != null && (resource.isClientOnly() || auth != null && auth.isAuthenticated())) { clientTokenServices.saveAccessToken(resource, auth, accessToken); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/JdbcClientTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/JdbcClientTokenServices.java index 05c1f5271..fbc8c9d45 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/JdbcClientTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/JdbcClientTokenServices.java @@ -75,10 +75,11 @@ public OAuth2AccessToken mapRow(ResultSet rs, int rowNum) throws SQLException { public void saveAccessToken(OAuth2ProtectedResourceDetails resource, Authentication authentication, OAuth2AccessToken accessToken) { removeAccessToken(resource, authentication); + String name = authentication==null ? null : authentication.getName(); jdbcTemplate.update( insertAccessTokenSql, new Object[] { accessToken.getValue(), new SqlLobValue(SerializationUtils.serialize(accessToken)), - keyGenerator.extractKey(resource, authentication), authentication.getName(), + keyGenerator.extractKey(resource, authentication), name, resource.getClientId() }, new int[] { Types.VARCHAR, Types.BLOB, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR }); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/AccessTokenProviderChainTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/AccessTokenProviderChainTests.java index 9dd0468bb..5fbc0fcb8 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/AccessTokenProviderChainTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/AccessTokenProviderChainTests.java @@ -31,6 +31,7 @@ import org.springframework.security.oauth2.client.resource.BaseOAuth2ProtectedResourceDetails; import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails; import org.springframework.security.oauth2.client.resource.UserRedirectRequiredException; +import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails; import org.springframework.security.oauth2.common.DefaultExpiringOAuth2RefreshToken; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.DefaultOAuth2RefreshToken; @@ -98,6 +99,18 @@ public void testSunnyDayWithTokenServicesSave() throws Exception { Mockito.verify(clientTokenServices).saveAccessToken(resource, user, token); } + @Test + public void testSunnyDayClientCredentialsWithTokenServicesSave() throws Exception { + AccessTokenProviderChain chain = new AccessTokenProviderChain(Arrays.asList(new StubAccessTokenProvider())); + chain.setClientTokenServices(clientTokenServices); + AccessTokenRequest request = new DefaultAccessTokenRequest(); + resource = new ClientCredentialsResourceDetails(); + resource.setId("resource"); + OAuth2AccessToken token = chain.obtainAccessToken(resource, request); + assertNotNull(token); + Mockito.verify(clientTokenServices).saveAccessToken(resource, null, token); + } + @Test public void testSunnyDayWithExpiredToken() throws Exception { AccessTokenProviderChain chain = new AccessTokenProviderChain(Arrays.asList(new StubAccessTokenProvider())); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/JdbcClientTokenServicesTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/JdbcClientTokenServicesTests.java index 412021911..b3548aee5 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/JdbcClientTokenServicesTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/JdbcClientTokenServicesTests.java @@ -54,6 +54,17 @@ public void testSaveAndRetrieveToken() throws Exception { assertEquals(accessToken, result); } + @Test + public void testSaveAndRetrieveTokenForClientCredentials() throws Exception { + OAuth2AccessToken accessToken = new DefaultOAuth2AccessToken("FOO"); + AuthorizationCodeResourceDetails resource = new AuthorizationCodeResourceDetails(); + resource.setClientId("client"); + resource.setScope(Arrays.asList("foo", "bar")); + tokenStore.saveAccessToken(resource, null, accessToken); + OAuth2AccessToken result = tokenStore.getAccessToken(resource, null); + assertEquals(accessToken, result); + } + @Test public void testSaveAndRemoveToken() throws Exception { OAuth2AccessToken accessToken = new DefaultOAuth2AccessToken("FOO"); From 59f0dcae39c08c5d4f4aea551e04e5779df72fb6 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 19 Mar 2015 10:54:15 +0000 Subject: [PATCH 416/831] Bump versions for 2.0.8 --- pom.xml | 12 +++++++++++- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- tests/annotation/approval/pom.xml | 2 +- tests/annotation/client/pom.xml | 2 +- tests/annotation/common/pom.xml | 2 +- tests/annotation/form/pom.xml | 2 +- tests/annotation/jaxb/pom.xml | 2 +- tests/annotation/jdbc/pom.xml | 2 +- tests/annotation/jwt/pom.xml | 2 +- tests/annotation/mappings/pom.xml | 2 +- tests/annotation/multi/pom.xml | 2 +- tests/annotation/pom.xml | 4 ++-- tests/annotation/resource/pom.xml | 2 +- tests/annotation/vanilla/pom.xml | 2 +- tests/pom.xml | 2 +- tests/xml/approval/pom.xml | 2 +- tests/xml/client/pom.xml | 2 +- tests/xml/common/pom.xml | 2 +- tests/xml/form/pom.xml | 2 +- tests/xml/jdbc/pom.xml | 2 +- tests/xml/jwt/pom.xml | 2 +- tests/xml/mappings/pom.xml | 2 +- tests/xml/pom.xml | 4 ++-- tests/xml/vanilla/pom.xml | 2 +- 30 files changed, 42 insertions(+), 32 deletions(-) diff --git a/pom.xml b/pom.xml index 00fd283a3..cdeec2927 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.7.BUILD-SNAPSHOT + 2.0.8.BUILD-SNAPSHOT http://static.springframework.org/spring-security/oauth @@ -125,6 +125,16 @@ + + bintray + + + bintray + Jcenter Repository + https://api.bintray.com/maven/spring/jars/org.springframework.security.oauth + + + central diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index 353fc56ba..654448855 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.7.BUILD-SNAPSHOT + 2.0.8.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index a12403598..023d375b2 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.7.BUILD-SNAPSHOT + 2.0.8.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 1e1ee7f99..2b898402c 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.7.BUILD-SNAPSHOT + 2.0.8.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 490529578..59630cb59 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.7.BUILD-SNAPSHOT + 2.0.8.BUILD-SNAPSHOT ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index afd5b8f75..be333228e 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.7.BUILD-SNAPSHOT + 2.0.8.BUILD-SNAPSHOT spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index ccd55e19e..89de3901f 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.7.BUILD-SNAPSHOT + 2.0.8.BUILD-SNAPSHOT spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 5f485ff02..d9d69d107 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.7.BUILD-SNAPSHOT + 2.0.8.BUILD-SNAPSHOT spring-security-oauth2 diff --git a/tests/annotation/approval/pom.xml b/tests/annotation/approval/pom.xml index fcb561999..d9ee4c726 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.7.BUILD-SNAPSHOT + 2.0.8.BUILD-SNAPSHOT diff --git a/tests/annotation/client/pom.xml b/tests/annotation/client/pom.xml index dbcb8397b..bd5aa9f39 100644 --- a/tests/annotation/client/pom.xml +++ b/tests/annotation/client/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.0.7.BUILD-SNAPSHOT + 2.0.8.BUILD-SNAPSHOT diff --git a/tests/annotation/common/pom.xml b/tests/annotation/common/pom.xml index 222b04da1..fc908ef7a 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.7.BUILD-SNAPSHOT + 2.0.8.BUILD-SNAPSHOT diff --git a/tests/annotation/form/pom.xml b/tests/annotation/form/pom.xml index 45bb04d62..58afb0178 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.7.BUILD-SNAPSHOT + 2.0.8.BUILD-SNAPSHOT diff --git a/tests/annotation/jaxb/pom.xml b/tests/annotation/jaxb/pom.xml index 8c0c31a74..e2a64c384 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.7.BUILD-SNAPSHOT + 2.0.8.BUILD-SNAPSHOT diff --git a/tests/annotation/jdbc/pom.xml b/tests/annotation/jdbc/pom.xml index 2a6f23d07..11421404d 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.7.BUILD-SNAPSHOT + 2.0.8.BUILD-SNAPSHOT diff --git a/tests/annotation/jwt/pom.xml b/tests/annotation/jwt/pom.xml index 2600565b8..195b3eb5d 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.7.BUILD-SNAPSHOT + 2.0.8.BUILD-SNAPSHOT diff --git a/tests/annotation/mappings/pom.xml b/tests/annotation/mappings/pom.xml index 8a8a7b2e0..b79255f06 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.7.BUILD-SNAPSHOT + 2.0.8.BUILD-SNAPSHOT diff --git a/tests/annotation/multi/pom.xml b/tests/annotation/multi/pom.xml index 0d8625378..ec2951674 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.7.BUILD-SNAPSHOT + 2.0.8.BUILD-SNAPSHOT diff --git a/tests/annotation/pom.xml b/tests/annotation/pom.xml index 71e737fc8..ccb0ad078 100644 --- a/tests/annotation/pom.xml +++ b/tests/annotation/pom.xml @@ -4,7 +4,7 @@ org.demo spring-oauth2-tests-parent - 2.0.7.BUILD-SNAPSHOT + 2.0.8.BUILD-SNAPSHOT pom @@ -34,7 +34,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.0.7.BUILD-SNAPSHOT + 2.0.8.BUILD-SNAPSHOT jackson-mapper-asl diff --git a/tests/annotation/resource/pom.xml b/tests/annotation/resource/pom.xml index 0979417f6..c9baa8d60 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.7.BUILD-SNAPSHOT + 2.0.8.BUILD-SNAPSHOT diff --git a/tests/annotation/vanilla/pom.xml b/tests/annotation/vanilla/pom.xml index 5f041355c..0b2917150 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.7.BUILD-SNAPSHOT + 2.0.8.BUILD-SNAPSHOT diff --git a/tests/pom.xml b/tests/pom.xml index 5c93f328a..bf78635fe 100644 --- a/tests/pom.xml +++ b/tests/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.7.BUILD-SNAPSHOT + 2.0.8.BUILD-SNAPSHOT spring-security-oauth-tests diff --git a/tests/xml/approval/pom.xml b/tests/xml/approval/pom.xml index a7590db56..943a9e35c 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.7.BUILD-SNAPSHOT + 2.0.8.BUILD-SNAPSHOT diff --git a/tests/xml/client/pom.xml b/tests/xml/client/pom.xml index 01a448e3e..9c92383c4 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.7.BUILD-SNAPSHOT + 2.0.8.BUILD-SNAPSHOT diff --git a/tests/xml/common/pom.xml b/tests/xml/common/pom.xml index 58bec99df..eb7a855bc 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.7.BUILD-SNAPSHOT + 2.0.8.BUILD-SNAPSHOT diff --git a/tests/xml/form/pom.xml b/tests/xml/form/pom.xml index 308cf7020..649558656 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.7.BUILD-SNAPSHOT + 2.0.8.BUILD-SNAPSHOT diff --git a/tests/xml/jdbc/pom.xml b/tests/xml/jdbc/pom.xml index 92274a0bf..546437f79 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.7.BUILD-SNAPSHOT + 2.0.8.BUILD-SNAPSHOT diff --git a/tests/xml/jwt/pom.xml b/tests/xml/jwt/pom.xml index bd5d7e1ce..652c4ab3a 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.7.BUILD-SNAPSHOT + 2.0.8.BUILD-SNAPSHOT diff --git a/tests/xml/mappings/pom.xml b/tests/xml/mappings/pom.xml index f51fc0a81..bd3eb66f2 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.7.BUILD-SNAPSHOT + 2.0.8.BUILD-SNAPSHOT diff --git a/tests/xml/pom.xml b/tests/xml/pom.xml index 7aa391705..8ca0b8dc5 100644 --- a/tests/xml/pom.xml +++ b/tests/xml/pom.xml @@ -4,7 +4,7 @@ org.demo spring-oauth2-tests-xml-parent - 2.0.7.BUILD-SNAPSHOT + 2.0.8.BUILD-SNAPSHOT pom @@ -32,7 +32,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.0.7.BUILD-SNAPSHOT + 2.0.8.BUILD-SNAPSHOT jackson-mapper-asl diff --git a/tests/xml/vanilla/pom.xml b/tests/xml/vanilla/pom.xml index 5603483c5..2a14e6289 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.7.BUILD-SNAPSHOT + 2.0.8.BUILD-SNAPSHOT From 3a76715509e82e5b2fe97cfc5e4abf4aaba02fa1 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 13 Apr 2015 16:36:43 +0100 Subject: [PATCH 417/831] A bunch of tidying and tweaking mainly in tests --- .../client/test/OAuth2ContextSetup.java | 141 +++++++++++++----- .../ResourceOwnerPasswordTokenGranter.java | 2 +- ...zationServerBeanDefinitionParserTests.java | 4 +- .../xml/authorization-server-disable.xml | 24 +++ ...bstractAuthorizationCodeProviderTests.java | 15 ++ ...bstractClientCredentialsProviderTests.java | 31 ++-- .../common/AbstractIntegrationTests.java | 16 ++ ...actResourceOwnerPasswordProviderTests.java | 84 +++++++---- ...bstractClientCredentialsProviderTests.java | 2 +- ...actResourceOwnerPasswordProviderTests.java | 7 +- .../src/main/java/demo/Application.java | 4 +- 11 files changed, 241 insertions(+), 89 deletions(-) create mode 100644 spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-disable.xml diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/OAuth2ContextSetup.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/OAuth2ContextSetup.java index 6e442c35b..83529d7e6 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/OAuth2ContextSetup.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/OAuth2ContextSetup.java @@ -15,6 +15,7 @@ import java.io.IOException; import java.lang.reflect.Constructor; import java.net.HttpURLConnection; +import java.net.URI; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; @@ -22,6 +23,11 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.http.client.config.CookieSpecs; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.config.RequestConfig.Builder; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.protocol.HttpContext; import org.hamcrest.CoreMatchers; import org.junit.Assert; import org.junit.internal.AssumptionViolatedException; @@ -32,7 +38,9 @@ import org.junit.runners.model.TestClass; import org.springframework.beans.BeanUtils; import org.springframework.core.env.Environment; +import org.springframework.http.HttpMethod; import org.springframework.http.client.ClientHttpResponse; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext; import org.springframework.security.oauth2.client.OAuth2ClientContext; @@ -49,10 +57,11 @@ /** *

    - * A rule that sets up an OAuth2 context for tests and makes the access token available inside a test method. In - * combination with the {@link OAuth2ContextConfiguration} annotation provides a number of different strategies for - * configuring an {@link OAuth2ProtectedResourceDetails} instance that will be used to create the OAuth2 context for - * tests. Example: + * A rule that sets up an OAuth2 context for tests and makes the access token available + * inside a test method. In combination with the {@link OAuth2ContextConfiguration} + * annotation provides a number of different strategies for configuring an + * {@link OAuth2ProtectedResourceDetails} instance that will be used to create the OAuth2 + * context for tests. Example: *

    * *
    @@ -60,16 +69,19 @@
      * public class MyIntegrationTests implements RestTemplateHolder {
      * 
      * 	@Rule
    - * 	public OAuth2ContextSetup context = OAuth2ContextSetup.withEnvironment(this, TestEnvironment.instance());
    + * 	public OAuth2ContextSetup context = OAuth2ContextSetup.withEnvironment(this,
    + * 			TestEnvironment.instance());
      * 
      * 	@Test
      * 	public void testSomethingWithClientCredentials() {
    - * 		// This call will be authenticated with the client credentials in MyClientDetailsResource
    + * 		// This call will be authenticated with the client credentials in
    + * 		// MyClientDetailsResource
      * 		getRestTemplate().getForObject("http://myserver/resource", String.class);
      * 	}
      * 
      * 	// This class is used to initialize the OAuth2 context for the test methods.
    - * 	static class MyClientDetailsResource extends ResourceOwnerPasswordProtectedResourceDetails {
    + * 	static class MyClientDetailsResource extends
    + * 			ResourceOwnerPasswordProtectedResourceDetails {
      * 		public MyClientDetailsResource(Environment environment) {
      *             ... do stuff with environment to initialize the password credentials
      *         }
    @@ -110,33 +122,40 @@ public class OAuth2ContextSetup extends TestWatchman {
     	private final Environment environment;
     
     	/**
    -	 * Create a new client that can inject an Environment into its protected resource details.
    +	 * Create a new client that can inject an Environment into its protected resource
    +	 * details.
     	 * 
    -	 * @param clientHolder receives an OAuth2RestTemplate with the authenticated client for the duration of a test
    +	 * @param clientHolder receives an OAuth2RestTemplate with the authenticated client
    +	 * for the duration of a test
     	 * @param environment a Spring Environment that can be used to initialize the client
     	 * 
     	 * @return a rule that wraps test methods in an OAuth2 context
     	 */
    -	public static OAuth2ContextSetup withEnvironment(RestTemplateHolder clientHolder, Environment environment) {
    +	public static OAuth2ContextSetup withEnvironment(RestTemplateHolder clientHolder,
    +			Environment environment) {
     		return new OAuth2ContextSetup(clientHolder, null, environment);
     	}
     
     	/**
    -	 * Create a new client that can inject a {@link TestAccounts} instance into its protected resource details.
    +	 * Create a new client that can inject a {@link TestAccounts} instance into its
    +	 * protected resource details.
     	 * 
    -	 * @param clientHolder receives an OAuth2RestTemplate with the authenticated client for the duration of a test
    -	 * @param testAccounts a test account generator that can be used to initialize the client
    +	 * @param clientHolder receives an OAuth2RestTemplate with the authenticated client
    +	 * for the duration of a test
    +	 * @param testAccounts a test account generator that can be used to initialize the
    +	 * client
     	 * 
     	 * @return a rule that wraps test methods in an OAuth2 context
     	 */
    -	public static OAuth2ContextSetup withTestAccounts(RestTemplateHolder clientHolder, TestAccounts testAccounts) {
    +	public static OAuth2ContextSetup withTestAccounts(RestTemplateHolder clientHolder,
    +			TestAccounts testAccounts) {
     		return new OAuth2ContextSetup(clientHolder, testAccounts, null);
     	}
     
     	/**
    -	 * Create a new client that knows how to create its protected resource with no externalization help. Typically it
    -	 * will use resource details which accept an instance of the current test case (downcasting it from Object). For
    -	 * example
    +	 * Create a new client that knows how to create its protected resource with no
    +	 * externalization help. Typically it will use resource details which accept an
    +	 * instance of the current test case (downcasting it from Object). For example
     	 * 
     	 * 
     	 * static class MyClientDetailsResource extends ClientCredentialsProtectedResourceDetails {
    @@ -147,7 +166,8 @@ public static OAuth2ContextSetup withTestAccounts(RestTemplateHolder clientHolde
     	 * }
     	 * 
    * - * @param clientHolder receives an OAuth2RestTemplate with the authenticated client for the duration of a test + * @param clientHolder receives an OAuth2RestTemplate with the authenticated client + * for the duration of a test * * @return a rule that wraps test methods in an OAuth2 context */ @@ -155,7 +175,8 @@ public static OAuth2ContextSetup standard(RestTemplateHolder clientHolder) { return new OAuth2ContextSetup(clientHolder, null, null); } - private OAuth2ContextSetup(RestTemplateHolder clientHolder, TestAccounts testAccounts, Environment environment) { + private OAuth2ContextSetup(RestTemplateHolder clientHolder, + TestAccounts testAccounts, Environment environment) { this.clientHolder = clientHolder; this.testAccounts = testAccounts; this.environment = environment; @@ -202,8 +223,9 @@ public void setParameters(Map parameters) { } /** - * Get the current access token. Should be available inside a test method as long as a resource has been setup with - * {@link OAuth2ContextConfiguration @OAuth2ContextConfiguration}. + * Get the current access token. Should be available inside a test method as long as a + * resource has been setup with {@link OAuth2ContextConfiguration + * @OAuth2ContextConfiguration}. * * @return the current access token initializing it if necessary */ @@ -263,7 +285,8 @@ public OAuth2ClientContext getOAuth2ClientContext() { private void initializeIfNecessary(FrameworkMethod method, final Object target) { final TestClass testClass = new TestClass(target.getClass()); - OAuth2ContextConfiguration contextConfiguration = findOAuthContextConfiguration(method, testClass); + OAuth2ContextConfiguration contextConfiguration = findOAuthContextConfiguration( + method, testClass); if (contextConfiguration == null) { // Nothing to do return; @@ -273,7 +296,8 @@ private void initializeIfNecessary(FrameworkMethod method, final Object target) this.resource = creatResource(target, contextConfiguration); - final List befores = testClass.getAnnotatedMethods(BeforeOAuth2Context.class); + final List befores = testClass + .getAnnotatedMethods(BeforeOAuth2Context.class); if (!befores.isEmpty()) { logger.debug("Running @BeforeOAuth2Context methods"); @@ -282,13 +306,16 @@ private void initializeIfNecessary(FrameworkMethod method, final Object target) RestOperations savedServerClient = clientHolder.getRestTemplate(); - OAuth2ContextConfiguration beforeConfiguration = findOAuthContextConfiguration(before, testClass); + OAuth2ContextConfiguration beforeConfiguration = findOAuthContextConfiguration( + before, testClass); if (beforeConfiguration != null) { - OAuth2ProtectedResourceDetails resource = creatResource(target, beforeConfiguration); + OAuth2ProtectedResourceDetails resource = creatResource(target, + beforeConfiguration); AccessTokenRequest beforeRequest = new DefaultAccessTokenRequest(); beforeRequest.setAll(parameters); - OAuth2RestTemplate client = createRestTemplate(resource, beforeRequest); + OAuth2RestTemplate client = createRestTemplate(resource, + beforeRequest); clientHolder.setRestTemplate(client); } @@ -327,16 +354,11 @@ public void evaluate() { } - private OAuth2RestTemplate createRestTemplate(OAuth2ProtectedResourceDetails resource, AccessTokenRequest request) { + private OAuth2RestTemplate createRestTemplate( + OAuth2ProtectedResourceDetails resource, AccessTokenRequest request) { OAuth2ClientContext context = new DefaultOAuth2ClientContext(request); OAuth2RestTemplate client = new OAuth2RestTemplate(resource, context); - client.setRequestFactory(new SimpleClientHttpRequestFactory() { - @Override - protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException { - super.prepareConnection(connection, httpMethod); - connection.setInstanceFollowRedirects(false); - } - }); + setupConnectionFactory(client); client.setErrorHandler(new DefaultResponseErrorHandler() { // Pass errors through in response entity for status code analysis public boolean hasError(ClientHttpResponse response) throws IOException { @@ -349,13 +371,46 @@ public boolean hasError(ClientHttpResponse response) throws IOException { return client; } - private OAuth2ProtectedResourceDetails creatResource(Object target, OAuth2ContextConfiguration contextLoader) { + private void setupConnectionFactory(OAuth2RestTemplate client) { + if (Boolean.getBoolean("http.components.enabled") + && ClassUtils.isPresent("org.apache.http.client.config.RequestConfig", + null)) { + client.setRequestFactory(new HttpComponentsClientHttpRequestFactory() { + @Override + protected HttpContext createHttpContext(HttpMethod httpMethod, URI uri) { + HttpClientContext context = HttpClientContext.create(); + context.setRequestConfig(getRequestConfig()); + return context; + } + + protected RequestConfig getRequestConfig() { + Builder builder = RequestConfig.custom() + .setCookieSpec(CookieSpecs.IGNORE_COOKIES) + .setAuthenticationEnabled(false).setRedirectsEnabled(false); + return builder.build(); + } + }); + } + else { + client.setRequestFactory(new SimpleClientHttpRequestFactory() { + @Override + protected void prepareConnection(HttpURLConnection connection, + String httpMethod) throws IOException { + super.prepareConnection(connection, httpMethod); + connection.setInstanceFollowRedirects(false); + } + }); + } + } + + private OAuth2ProtectedResourceDetails creatResource(Object target, + OAuth2ContextConfiguration contextLoader) { Class type = contextLoader.value(); if (type == OAuth2ProtectedResourceDetails.class) { type = contextLoader.resource(); } - Constructor constructor = ClassUtils.getConstructorIfAvailable(type, - TestAccounts.class); + Constructor constructor = ClassUtils + .getConstructorIfAvailable(type, TestAccounts.class); if (constructor != null && testAccounts != null) { return BeanUtils.instantiateClass(constructor, testAccounts); } @@ -371,13 +426,17 @@ private OAuth2ProtectedResourceDetails creatResource(Object target, OAuth2Contex return BeanUtils.instantiate(type); } - private OAuth2ContextConfiguration findOAuthContextConfiguration(FrameworkMethod method, TestClass testClass) { - OAuth2ContextConfiguration methodConfiguration = method.getAnnotation(OAuth2ContextConfiguration.class); + private OAuth2ContextConfiguration findOAuthContextConfiguration( + FrameworkMethod method, TestClass testClass) { + OAuth2ContextConfiguration methodConfiguration = method + .getAnnotation(OAuth2ContextConfiguration.class); if (methodConfiguration != null) { return methodConfiguration; } - if (testClass.getJavaClass().isAnnotationPresent(OAuth2ContextConfiguration.class)) { - return testClass.getJavaClass().getAnnotation(OAuth2ContextConfiguration.class); + if (testClass.getJavaClass() + .isAnnotationPresent(OAuth2ContextConfiguration.class)) { + return testClass.getJavaClass().getAnnotation( + OAuth2ContextConfiguration.class); } return null; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java index b556179fc..15b0d4649 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java @@ -70,7 +70,7 @@ protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, Tok throw new InvalidGrantException(ase.getMessage()); } catch (BadCredentialsException e) { - // If the username/password are wrong the spec says we should send 400/invlid grant + // If the username/password are wrong the spec says we should send 400/invalid grant throw new InvalidGrantException(e.getMessage()); } if (userAuth == null || !userAuth.isAuthenticated()) { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/AuthorizationServerBeanDefinitionParserTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/AuthorizationServerBeanDefinitionParserTests.java index 752cea947..f1c1f3c7d 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/AuthorizationServerBeanDefinitionParserTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/AuthorizationServerBeanDefinitionParserTests.java @@ -42,7 +42,9 @@ public class AuthorizationServerBeanDefinitionParserTests { @Parameters public static List parameters() { return Arrays.asList(new Object[] { "authorization-server-vanilla" }, - new Object[] { "authorization-server-extras" }, new Object[] { "authorization-server-types" }); + new Object[] { "authorization-server-extras" }, + new Object[] { "authorization-server-types" }, + new Object[] { "authorization-server-disable" }); } public AuthorizationServerBeanDefinitionParserTests(String resource) { diff --git a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-disable.xml b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-disable.xml new file mode 100644 index 000000000..0fda58d74 --- /dev/null +++ b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-disable.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java b/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java index b8609ba89..eb6ab6ce8 100755 --- a/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java @@ -25,6 +25,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.security.oauth2.client.resource.BaseOAuth2ProtectedResourceDetails; import org.springframework.security.oauth2.client.resource.UserRedirectRequiredException; import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration; import org.springframework.security.oauth2.client.token.AccessTokenRequest; @@ -234,4 +235,18 @@ public void testRegisteredRedirectWithWrongOneInTokenEndpoint() throws Exception } } + @Test + @OAuth2ContextConfiguration(resource = MyTrustedClient.class, initialize = false) + public void testWrongClientIdTokenEndpoint() throws Exception { + approveAccessTokenGrant("http://anywhere/?key=value", true); + ((BaseOAuth2ProtectedResourceDetails) context.getResource()).setClientId("non-existent"); + try { + assertNotNull(context.getAccessToken()); + fail("Expected HttpClientErrorException"); + } + catch (HttpClientErrorException e) { + assertEquals(HttpStatus.UNAUTHORIZED, e.getStatusCode()); + } + } + } diff --git a/tests/annotation/common/src/main/java/sparklr/common/AbstractClientCredentialsProviderTests.java b/tests/annotation/common/src/main/java/sparklr/common/AbstractClientCredentialsProviderTests.java index 1f58b814d..0dd177157 100644 --- a/tests/annotation/common/src/main/java/sparklr/common/AbstractClientCredentialsProviderTests.java +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractClientCredentialsProviderTests.java @@ -14,6 +14,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.client.ClientHttpResponse; import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration; +import org.springframework.security.oauth2.client.token.AccessTokenProvider; import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsAccessTokenProvider; import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails; import org.springframework.security.oauth2.common.OAuth2AccessToken; @@ -29,6 +30,23 @@ public abstract class AbstractClientCredentialsProviderTests extends AbstractInt private HttpHeaders responseHeaders; private HttpStatus responseStatus; + + @Override + protected AccessTokenProvider createAccessTokenProvider() { + return new ClientCredentialsAccessTokenProvider() { + @Override + protected ResponseErrorHandler getResponseErrorHandler() { + final ResponseErrorHandler delegate = super.getResponseErrorHandler(); + return new DefaultResponseErrorHandler() { + public void handleError(ClientHttpResponse response) throws IOException { + responseHeaders = response.getHeaders(); + responseStatus = response.getStatusCode(); + delegate.handleError(response); + } + }; + } + }; + } /** * tests the basic provider @@ -53,25 +71,14 @@ public void testPostForTokenWithNoScopes() throws Exception { @Test @OAuth2ContextConfiguration(resource = InvalidClientCredentials.class, initialize = false) public void testInvalidCredentials() throws Exception { - context.setAccessTokenProvider(new ClientCredentialsAccessTokenProvider() { - @Override - protected ResponseErrorHandler getResponseErrorHandler() { - return new DefaultResponseErrorHandler() { - public void handleError(ClientHttpResponse response) throws IOException { - responseHeaders = response.getHeaders(); - responseStatus = response.getStatusCode(); - } - }; - } - }); try { context.getAccessToken(); fail("Expected ResourceAccessException"); } catch (Exception e) { + // System.err.println(responseHeaders); // ignore } - // System.err.println(responseHeaders); String header = responseHeaders.getFirst("WWW-Authenticate"); assertTrue("Wrong header: " + header, header.contains("Basic realm")); assertEquals(HttpStatus.UNAUTHORIZED, responseStatus); 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 ca90a208f..9ceaaf783 100644 --- a/tests/annotation/common/src/main/java/sparklr/common/AbstractIntegrationTests.java +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractIntegrationTests.java @@ -39,6 +39,8 @@ import org.springframework.security.oauth2.client.resource.BaseOAuth2ProtectedResourceDetails; import org.springframework.security.oauth2.client.test.BeforeOAuth2Context; import org.springframework.security.oauth2.client.test.OAuth2ContextSetup; +import org.springframework.security.oauth2.client.token.AccessTokenProvider; +import org.springframework.security.oauth2.client.token.OAuth2AccessTokenSupport; import org.springframework.security.oauth2.client.token.grant.implicit.ImplicitResourceDetails; import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordResourceDetails; import org.springframework.security.oauth2.client.token.grant.redirect.AbstractRedirectResourceDetails; @@ -119,6 +121,10 @@ protected void cancelToken(String value) { } } + protected AccessTokenProvider createAccessTokenProvider() { + return null; + } + @Before public void init() { String prefix = server.getServletPrefix(); @@ -126,6 +132,16 @@ public void init() { http.setPrefix(prefix); } + @BeforeOAuth2Context + public void setupAccessTokenProvider() { + AccessTokenProvider accessTokenProvider = createAccessTokenProvider(); + if (accessTokenProvider instanceof OAuth2AccessTokenSupport) { + ((OAuth2AccessTokenSupport) accessTokenProvider).setRequestFactory(context + .getRestTemplate().getRequestFactory()); + context.setAccessTokenProvider(accessTokenProvider); + } + } + @BeforeOAuth2Context public void fixPaths() { String prefix = server.getServletPrefix(); diff --git a/tests/annotation/common/src/main/java/sparklr/common/AbstractResourceOwnerPasswordProviderTests.java b/tests/annotation/common/src/main/java/sparklr/common/AbstractResourceOwnerPasswordProviderTests.java index 2e881d956..af91c85d6 100644 --- a/tests/annotation/common/src/main/java/sparklr/common/AbstractResourceOwnerPasswordProviderTests.java +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractResourceOwnerPasswordProviderTests.java @@ -18,12 +18,14 @@ import org.springframework.http.ResponseEntity; import org.springframework.http.client.ClientHttpResponse; import org.springframework.security.crypto.codec.Base64; -import org.springframework.security.oauth2.client.test.BeforeOAuth2Context; +import org.springframework.security.oauth2.client.OAuth2RestTemplate; +import org.springframework.security.oauth2.client.resource.OAuth2AccessDeniedException; import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration; import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordAccessTokenProvider; import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordResourceDetails; import org.springframework.security.oauth2.common.AuthenticationScheme; import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.util.LinkedMultiValueMap; import org.springframework.web.client.DefaultResponseErrorHandler; import org.springframework.web.client.HttpClientErrorException; @@ -34,22 +36,21 @@ * @author Ryan Heaton * @author Dave Syer */ -public abstract class AbstractResourceOwnerPasswordProviderTests extends AbstractIntegrationTests { +public abstract class AbstractResourceOwnerPasswordProviderTests extends + AbstractIntegrationTests { - private ClientHttpResponse tokenEndpointResponse; + protected ClientHttpResponse tokenEndpointResponse; - @BeforeOAuth2Context - public void setupAccessTokenProvider() { + @Override + protected ResourceOwnerPasswordAccessTokenProvider createAccessTokenProvider() { ResourceOwnerPasswordAccessTokenProvider accessTokenProvider = new ResourceOwnerPasswordAccessTokenProvider() { - private ResponseExtractor extractor = super.getResponseExtractor(); - - private ResponseErrorHandler errorHandler = super.getResponseErrorHandler(); - @Override protected ResponseErrorHandler getResponseErrorHandler() { + final ResponseErrorHandler errorHandler = super.getResponseErrorHandler(); return new DefaultResponseErrorHandler() { - public void handleError(ClientHttpResponse response) throws IOException { + public void handleError(ClientHttpResponse response) + throws IOException { response.getHeaders(); response.getStatusCode(); tokenEndpointResponse = response; @@ -60,9 +61,12 @@ public void handleError(ClientHttpResponse response) throws IOException { @Override protected ResponseExtractor getResponseExtractor() { + final ResponseExtractor extractor = super + .getResponseExtractor(); return new ResponseExtractor() { - public OAuth2AccessToken extractData(ClientHttpResponse response) throws IOException { + public OAuth2AccessToken extractData(ClientHttpResponse response) + throws IOException { response.getHeaders(); response.getStatusCode(); tokenEndpointResponse = response; @@ -72,7 +76,7 @@ public OAuth2AccessToken extractData(ClientHttpResponse response) throws IOExcep }; } }; - context.setAccessTokenProvider(accessTokenProvider); + return accessTokenProvider; } @Test @@ -87,7 +91,8 @@ public void testUnauthenticatedErrorMessage() throws Exception { ResponseEntity response = http.getForResponse("/admin/beans", headers); assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); String authenticate = response.getHeaders().getFirst("WWW-Authenticate"); - assertTrue("Wrong header: " + authenticate, authenticate.contains("error=\"unauthorized\"")); + assertTrue("Wrong header: " + authenticate, + authenticate.contains("error=\"unauthorized\"")); } @Test @@ -97,17 +102,18 @@ public void testInvalidTokenErrorMessage() throws Exception { ResponseEntity response = http.getForResponse("/admin/beans", headers); assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); String authenticate = response.getHeaders().getFirst("WWW-Authenticate"); - assertTrue("Wrong header: " + authenticate, authenticate.contains("error=\"invalid_token\"")); + assertTrue("Wrong header: " + authenticate, + authenticate.contains("error=\"invalid_token\"")); } - + @Test @OAuth2ContextConfiguration(ResourceOwner.class) public void testTokenObtainedWithHeaderAuthentication() throws Exception { assertEquals(HttpStatus.OK, http.getStatusCode("/admin/beans")); int expiry = context.getAccessToken().getExpiresIn(); assertTrue("Expiry not overridden in config: " + expiry, expiry < 1000); - assertEquals(new MediaType("application", "json", Charset.forName("UTF-8")), tokenEndpointResponse.getHeaders() - .getContentType()); + assertEquals(new MediaType("application", "json", Charset.forName("UTF-8")), + tokenEndpointResponse.getHeaders().getContentType()); } @Test @@ -124,10 +130,12 @@ public void testTokenNotGrantedIfSecretNotProvided() throws Exception { } catch (HttpClientErrorException e) { assertEquals(HttpStatus.UNAUTHORIZED, e.getStatusCode()); - List values = tokenEndpointResponse.getHeaders().get("WWW-Authenticate"); + List values = tokenEndpointResponse.getHeaders().get( + "WWW-Authenticate"); assertEquals(1, values.size()); String header = values.get(0); - assertTrue("Wrong header " + header, header.contains("Basic realm=\"oauth2/client\"")); + assertTrue("Wrong header " + header, + header.contains("Basic realm=\"oauth2/client\"")); } } @@ -147,7 +155,8 @@ public void testSecretProvidedInHeader() throws Exception { @OAuth2ContextConfiguration(resource = NoSuchClient.class, initialize = false) public void testNoSuchClient() throws Exception { - // The error comes back as additional information because OAuth2AccessToken is so extensible! + // The error comes back as additional information because OAuth2AccessToken is so + // extensible! try { context.getAccessToken(); } @@ -165,19 +174,36 @@ public void testNoSuchClient() throws Exception { } @Test - public void testTokenEndpointunauthenticated() throws Exception { + @OAuth2ContextConfiguration(value=ResourceOwner.class, initialize=false) + public void testTokenEndpointWrongPassword() throws Exception { + ResourceOwnerPasswordResourceDetails resource = (ResourceOwnerPasswordResourceDetails) context + .getResource(); + resource.setPassword("bogus"); + try { + new OAuth2RestTemplate(resource).getAccessToken(); + } catch (OAuth2AccessDeniedException e) { + String summary = ((OAuth2Exception)e.getCause()).getSummary(); + assertTrue("Wrong summary: " + summary, summary.contains("Bad credentials")); + } + } + + @Test + public void testTokenEndpointUnauthenticated() throws Exception { + ResponseEntity result = http.getRestTemplate().exchange( + http.getUrl("/oauth/token"), HttpMethod.GET, + new HttpEntity((Void) null), String.class); // first make sure the resource is actually protected. - assertEquals( - HttpStatus.UNAUTHORIZED, - http.getRestTemplate().exchange(http.getUrl("/oauth/token"), HttpMethod.GET, - new HttpEntity((Void)null), String.class).getStatusCode()); + assertEquals(HttpStatus.UNAUTHORIZED, result.getStatusCode()); + assertTrue("Wrong body: " + result.getBody(), + result.getBody().toLowerCase().contains("unauthorized")); } @Test @OAuth2ContextConfiguration(resource = InvalidGrantType.class, initialize = false) public void testInvalidGrantType() throws Exception { - // The error comes back as additional information because OAuth2AccessToken is so extensible! + // The error comes back as additional information because OAuth2AccessToken is so + // extensible! try { context.getAccessToken(); } @@ -200,8 +226,10 @@ public void testInvalidGrantType() throws Exception { @Test public void testMissingGrantType() throws Exception { HttpHeaders headers = new HttpHeaders(); - headers.set("Authorization", - String.format("Basic %s", new String(Base64.encode("my-trusted-client:".getBytes())))); + headers.set( + "Authorization", + String.format("Basic %s", + new String(Base64.encode("my-trusted-client:".getBytes())))); headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); ResponseEntity response = http.postForString(tokenPath(), headers, new LinkedMultiValueMap()); diff --git a/tests/xml/common/src/main/java/sparklr/common/AbstractClientCredentialsProviderTests.java b/tests/xml/common/src/main/java/sparklr/common/AbstractClientCredentialsProviderTests.java index 895462590..0b1a38d1c 100644 --- a/tests/xml/common/src/main/java/sparklr/common/AbstractClientCredentialsProviderTests.java +++ b/tests/xml/common/src/main/java/sparklr/common/AbstractClientCredentialsProviderTests.java @@ -69,9 +69,9 @@ public void handleError(ClientHttpResponse response) throws IOException { fail("Expected ResourceAccessException"); } catch (Exception e) { + // System.err.println(responseHeaders); // ignore } - // System.err.println(responseHeaders); String header = responseHeaders.getFirst("WWW-Authenticate"); assertTrue("Wrong header: " + header, header.contains("Basic realm")); assertEquals(HttpStatus.UNAUTHORIZED, responseStatus); diff --git a/tests/xml/common/src/main/java/sparklr/common/AbstractResourceOwnerPasswordProviderTests.java b/tests/xml/common/src/main/java/sparklr/common/AbstractResourceOwnerPasswordProviderTests.java index 1aee44bc6..15a4d9fa0 100644 --- a/tests/xml/common/src/main/java/sparklr/common/AbstractResourceOwnerPasswordProviderTests.java +++ b/tests/xml/common/src/main/java/sparklr/common/AbstractResourceOwnerPasswordProviderTests.java @@ -40,12 +40,9 @@ public abstract class AbstractResourceOwnerPasswordProviderTests extends Abstrac public void setupAccessTokenProvider() { ResourceOwnerPasswordAccessTokenProvider accessTokenProvider = new ResourceOwnerPasswordAccessTokenProvider() { - private ResponseExtractor extractor = super.getResponseExtractor(); - - private ResponseErrorHandler errorHandler = super.getResponseErrorHandler(); - @Override protected ResponseErrorHandler getResponseErrorHandler() { + final ResponseErrorHandler errorHandler = super.getResponseErrorHandler(); return new DefaultResponseErrorHandler() { public void handleError(ClientHttpResponse response) throws IOException { response.getHeaders(); @@ -58,6 +55,7 @@ public void handleError(ClientHttpResponse response) throws IOException { @Override protected ResponseExtractor getResponseExtractor() { + final ResponseExtractor extractor = super.getResponseExtractor(); return new ResponseExtractor() { public OAuth2AccessToken extractData(ClientHttpResponse response) throws IOException { @@ -70,6 +68,7 @@ public OAuth2AccessToken extractData(ClientHttpResponse response) throws IOExcep }; } }; + accessTokenProvider.setRequestFactory(context.getRestTemplate().getRequestFactory()); context.setAccessTokenProvider(accessTokenProvider); } diff --git a/tests/xml/vanilla/src/main/java/demo/Application.java b/tests/xml/vanilla/src/main/java/demo/Application.java index b70fa3857..3f4116af2 100644 --- a/tests/xml/vanilla/src/main/java/demo/Application.java +++ b/tests/xml/vanilla/src/main/java/demo/Application.java @@ -138,7 +138,9 @@ protected void configure(HttpSecurity http) throws Exception { .httpBasic().authenticationEntryPoint(authenticationEntryPoint()) .and() .csrf().requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/token")).disable() - .exceptionHandling().accessDeniedHandler(accessDeniedHandler()) + .exceptionHandling() + .accessDeniedHandler(accessDeniedHandler()) + .authenticationEntryPoint(authenticationEntryPoint()) .and() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); // @formatter:on From bbd7b7052b1d6479f9f9180a3de28712ab9f0504 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 14 Apr 2015 11:38:08 +0100 Subject: [PATCH 418/831] Fix WWW-Authenticate challenge for form-based client authentication The default AuthenticationEntryPoint for the client credentials token filter was returning "Basic" style headers on a 401. This change fixes the default to be the same as it was in XML (I believe). --- .../AuthorizationServerSecurityConfigurer.java | 4 ++++ ...AbstractResourceOwnerPasswordProviderTests.java | 2 +- .../demo/ResourceOwnerPasswordProviderTests.java | 14 ++++++++++++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java index 89eb9e268..9df61198f 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java @@ -174,6 +174,10 @@ private ClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilte frameworkEndpointHandlerMapping().getServletPath("/oauth/token")); clientCredentialsTokenEndpointFilter .setAuthenticationManager(http.getSharedObject(AuthenticationManager.class)); + OAuth2AuthenticationEntryPoint authenticationEntryPoint = new OAuth2AuthenticationEntryPoint(); + authenticationEntryPoint.setTypeName("Form"); + authenticationEntryPoint.setRealmName(realm); + clientCredentialsTokenEndpointFilter.setAuthenticationEntryPoint(authenticationEntryPoint); clientCredentialsTokenEndpointFilter = postProcess(clientCredentialsTokenEndpointFilter); http.addFilterBefore(clientCredentialsTokenEndpointFilter, BasicAuthenticationFilter.class); return clientCredentialsTokenEndpointFilter; diff --git a/tests/annotation/common/src/main/java/sparklr/common/AbstractResourceOwnerPasswordProviderTests.java b/tests/annotation/common/src/main/java/sparklr/common/AbstractResourceOwnerPasswordProviderTests.java index af91c85d6..15d1f2a94 100644 --- a/tests/annotation/common/src/main/java/sparklr/common/AbstractResourceOwnerPasswordProviderTests.java +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractResourceOwnerPasswordProviderTests.java @@ -135,7 +135,7 @@ public void testTokenNotGrantedIfSecretNotProvided() throws Exception { assertEquals(1, values.size()); String header = values.get(0); assertTrue("Wrong header " + header, - header.contains("Basic realm=\"oauth2/client\"")); + header.contains("realm=\"oauth2/client\"")); } } diff --git a/tests/annotation/form/src/test/java/demo/ResourceOwnerPasswordProviderTests.java b/tests/annotation/form/src/test/java/demo/ResourceOwnerPasswordProviderTests.java index aa5786098..6eaa554eb 100644 --- a/tests/annotation/form/src/test/java/demo/ResourceOwnerPasswordProviderTests.java +++ b/tests/annotation/form/src/test/java/demo/ResourceOwnerPasswordProviderTests.java @@ -1,13 +1,23 @@ 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; import sparklr.common.AbstractResourceOwnerPasswordProviderTests; /** * @author Dave Syer */ -@SpringApplicationConfiguration(classes=Application.class) -public class ResourceOwnerPasswordProviderTests extends AbstractResourceOwnerPasswordProviderTests { +@SpringApplicationConfiguration(classes = Application.class) +public class ResourceOwnerPasswordProviderTests extends + AbstractResourceOwnerPasswordProviderTests { + + @BeforeOAuth2Context + public void tweakClientAuthentication() { + ((BaseOAuth2ProtectedResourceDetails)context.getResource()) + .setClientAuthenticationScheme(AuthenticationScheme.form); + } } From eb9b5cc1c1c72282e187ebdb64e153cc975995fc Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 14 Apr 2015 11:40:01 +0100 Subject: [PATCH 419/831] Add flag to auth code client to make state key mandatory by default User has to choose explicitly the old behaviour where a null state key was acceptable even when the wrong state key was an error. Fixes gh-440 --- .../AuthorizationCodeAccessTokenProvider.java | 15 +++++++++++++-- ...AuthorizationCodeAccessTokenProviderTests.java | 11 +++++++++++ ...odeAccessTokenProviderWithConversionTests.java | 4 ++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProvider.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProvider.java index 9e312f752..37743c624 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProvider.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProvider.java @@ -77,6 +77,17 @@ public class AuthorizationCodeAccessTokenProvider extends OAuth2AccessTokenSuppo private RequestEnhancer authorizationRequestEnhancer = new DefaultRequestEnhancer(); + private boolean stateMandatory = true; + + /** + * Flag to say that the use of state parameter is mandatory. + * + * @param stateMandatory the flag value (default true) + */ + public void setStateMandatory(boolean stateMandatory) { + this.stateMandatory = stateMandatory; + } + /** * A custom enhancer for the authorization request * @param authorizationRequestEnhancer @@ -237,12 +248,12 @@ private MultiValueMap getParametersForTokenRequest(Authorization form.set("code", request.getAuthorizationCode()); Object preservedState = request.getPreservedState(); - if (request.getStateKey() != null) { + if (request.getStateKey() != null || stateMandatory) { // The token endpoint has no use for the state so we don't send it back, but we are using it // for CSRF detection client side... if (preservedState == null) { throw new InvalidRequestException( - "Possible CSRF detected - state parameter was present but no state could be found"); + "Possible CSRF detected - state parameter was required but no state could be found"); } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProviderTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProviderTests.java index 8c3c26ca4..deeacc458 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProviderTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProviderTests.java @@ -25,6 +25,7 @@ import org.springframework.security.oauth2.client.token.DefaultAccessTokenRequest; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.common.exceptions.InvalidRequestException; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; @@ -52,9 +53,19 @@ protected OAuth2AccessToken retrieveToken(AccessTokenRequest request, OAuth2Prot @Test public void testGetAccessToken() throws Exception { + AccessTokenRequest request = new DefaultAccessTokenRequest(); + request.setAuthorizationCode("foo"); + request.setPreservedState(new Object()); + resource.setAccessTokenUri("http://localhost/oauth/token"); + assertEquals("FOO", provider.obtainAccessToken(resource, request).getValue()); + } + + @Test + public void testGetAccessTokenFailsWithNoState() throws Exception { AccessTokenRequest request = new DefaultAccessTokenRequest(); request.setAuthorizationCode("foo"); resource.setAccessTokenUri("http://localhost/oauth/token"); + expected.expect(InvalidRequestException.class); assertEquals("FOO", provider.obtainAccessToken(resource, request).getValue()); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProviderWithConversionTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProviderWithConversionTests.java index 34fca6f85..568a2ebee 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProviderWithConversionTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProviderWithConversionTests.java @@ -156,6 +156,7 @@ public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IO AccessTokenRequest request = new DefaultAccessTokenRequest(); request.setAuthorizationCode("foo"); resource.setAccessTokenUri("http://localhost/oauth/token"); + request.setPreservedState(new Object()); setUpRestTemplate(); assertEquals(token, provider.obtainAccessToken(resource, request)); } @@ -171,6 +172,7 @@ public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IO }; AccessTokenRequest request = new DefaultAccessTokenRequest(); request.setAuthorizationCode("foo"); + request.setPreservedState(new Object()); resource.setAccessTokenUri("http://localhost/oauth/token"); expected.expect(OAuth2AccessDeniedException.class); expected.expect(hasCause(instanceOf(InvalidClientException.class))); @@ -190,6 +192,7 @@ public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IO }; AccessTokenRequest request = new DefaultAccessTokenRequest(); request.setAuthorizationCode("foo"); + request.setPreservedState(new Object()); resource.setAccessTokenUri("http://localhost/oauth/token"); setUpRestTemplate(); assertEquals(token, provider.obtainAccessToken(resource, request)); @@ -207,6 +210,7 @@ public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IO }; AccessTokenRequest request = new DefaultAccessTokenRequest(); request.setAuthorizationCode("foo"); + request.setPreservedState(new Object()); resource.setAccessTokenUri("http://localhost/oauth/token"); expected.expect(OAuth2AccessDeniedException.class); expected.expect(hasCause(instanceOf(InvalidClientException.class))); From 5beebfd3ff5b4d9ab9830d4943da79f2266b8a2a Mon Sep 17 00:00:00 2001 From: Eric Dahl Date: Mon, 6 Apr 2015 19:57:52 -0700 Subject: [PATCH 420/831] Docs: Update many links - Update many springsource links to use spring.io domain - Update many github "SpringSource/spring-security-oauth" links to "spring-projects/spring-security-oauth" Fixes gh-451 --- README.md | 8 +-- docs/Home.md | 8 +-- docs/devguide.md | 4 +- docs/downloads.md | 2 +- docs/oauth1.md | 58 +++++++++---------- docs/oauth2.md | 2 +- docs/tutorial.md | 6 +- docs/twolegged.md | 8 +-- .../oauth/spring-security-oauth-1.0.xsd | 2 +- src/site/apt/index.apt | 2 +- 10 files changed, 50 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index ce47dabcf..22c0246e9 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,9 @@ Security programming models and configuration idioms. # Getting Started -[Download](https://github.com/SpringSource/spring-security-oauth/tags) +[Download](https://github.com/spring-projects/spring-security-oauth/tags) or clone from -[GIT](https://github.com/SpringSource/spring-security-oauth) and then +[GIT](https://github.com/spring-projects/spring-security-oauth) and then use Maven (3.0.\*) and Java (1.6 or better): $ git clone ... @@ -43,8 +43,8 @@ require slightly different settings for Tomcat so you need to add a profile: ## Changelog -Lists of issues addressed per release can be found in [github](https://github.com/spring-projects/spring-security-oauth/issues/milestones) (older releases are in -[JIRA](https://jira.springsource.org/browse/SECOAUTH#selectedTab=com.atlassian.jira.plugin.system.project%3Aversions-panel)). +Lists of issues addressed per release can be found in [github](https://github.com/spring-projects/spring-security-oauth/milestones) (older releases are in +[JIRA](https://jira.spring.io/browse/SECOAUTH/?selectedTab=com.atlassian.jira.jira-projects-plugin:versions-panel)). ## Additional Resources diff --git a/docs/Home.md b/docs/Home.md index 083edff8f..f5402ca0c 100644 --- a/docs/Home.md +++ b/docs/Home.md @@ -9,7 +9,7 @@ home: ../ OAuth for Spring Security provides an [OAuth](http://oauth.net) implementation for -[Spring Security](http://static.springsource.org/spring-security/site/). +[Spring Security](http://projects.spring.io/spring-security/). Support is provided for the implementation of OAuth providers and OAuth consumers. There is support for [Oauth 1(a)](oauth1.html) (including [two-legged OAuth](twolegged.html), a.k.a. "Signed Fetch") and for @@ -18,10 +18,10 @@ OAuth consumers. There is support for [Oauth 1(a)](oauth1.html) (including Applying security to an application is not for the faint of heart, and OAuth is no exception. Before you get started, you're going to want to make sure you understand OAuth and the problem it's designed to address. There is good documentation at [the OAuth site](http://oauth.net). You will also want to make sure you understand how -[Spring](http://springframework.org/) and [Spring Security](http://static.springsource.org/spring-security/site/) work. +[Spring](http://springframework.org/) and [Spring Security](http://projects.spring.io/spring-security/) work. You're going to want to be quite familiar with both [OAuth](http://oauth.net) (and/or [OAuth2](http://tools.ietf.org/html/draft-ietf-oauth-v2)) -and [Spring Security](http://static.springsource.org/spring-security/site/), to maximize the effectiveness of this developers guide. OAuth for +and [Spring Security](http://projects.spring.io/spring-security/), to maximize the effectiveness of this developers guide. OAuth for Spring Security is tightly tied to both technologies, so the more familiar you are with them, the more likely you'll be to recognize the terminology and patterns that are used. @@ -30,7 +30,7 @@ With that, you're ready to get started. Here are some useful links: * For access to the binaries, use Maven ([instructions here](downloads.html)) * Source code is in github - [at SpringSource/spring-security-oauth](https://github.com/SpringSource/spring-security-oauth). + [at spring-projects/spring-security-oauth](https://github.com/spring-projects/spring-security-oauth). * You'll want to see OAuth for Spring Security in action, so here is a [tutorial](tutorial.html) diff --git a/docs/devguide.md b/docs/devguide.md index 1a2626542..2c20a4938 100644 --- a/docs/devguide.md +++ b/docs/devguide.md @@ -10,9 +10,9 @@ home: ../ ## Preparation You're going to want to be quite familiar with -[OAuth2](http://tools.ietf.org/html/draft-ietf-oauth-v2)(and/or +[OAuth2](http://tools.ietf.org/html/draft-ietf-oauth-v2) (and/or [OAuth](http://oauth.net) ) and -[Spring Security](http://static.springsource.org/spring-security/site/), +[Spring Security](http://projects.spring.io/spring-security/), to maximize the effectiveness of this developers guide. OAuth for Spring Security is tightly tied to both technologies, so the more familiar you are with them, the more likely you'll be to recognize the diff --git a/docs/downloads.md b/docs/downloads.md index ce5f6a359..b9cfb6829 100644 --- a/docs/downloads.md +++ b/docs/downloads.md @@ -32,4 +32,4 @@ and for snapshots: [mavenrepo]: http://shrub.appspot.com/maven.springframework.org/release/org/springframework/security/oauth/spring-security-oauth/ [central]: http://repo1.maven.org/maven2/org/springframework/security/oauth/spring-security-oauth/ -[Github]: http://github.com/SpringSource/spring-security-oauth +[Github]: https://github.com/spring-projects/spring-security-oauth diff --git a/docs/oauth1.md b/docs/oauth1.md index a026c7731..8d36e833c 100644 --- a/docs/oauth1.md +++ b/docs/oauth1.md @@ -267,33 +267,33 @@ wanted to replace it you could override the bean definition: In this example, the explicit bean definition overrides the one created by the `` because of the ordering in the application context declaration (this is a standard Spring bean factory feature). Bean definitions created by the namespace parsers follow the convention that they start with "oauth" and generally they are the class name of the default implementation provided by the framework. -[ConsumerDetailsService]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/ConsumerDetailsService.html -[ConsumerDetails]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/ConsumerDetails.html -[InMemoryConsumerDetailsService]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/InMemoryConsumerDetailsService.html -[BaseConsumerDetails]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/BaseConsumerDetails.html -[OAuthProviderTokenServices]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/token/OAuthProviderTokenServices.html -[RandomValueProviderTokenServices]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/token/RandomValueProviderTokenServices.html -[InMemoryProviderTokenServices]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/token/InMemoryProviderTokenServices.html -[UnauthenticatedRequestTokenProcessingFilter]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/UnauthenticatedRequestTokenProcessingFilter.html -[UserAuthorizationProcessingFilter]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/UserAuthorizationProcessingFilter.html -[AccessTokenProcessingFilter]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/AccessTokenProcessingFilter.html -[ProtectedResourceProcessingFilter]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/ProtectedResourceProcessingFilter.html -[OAuthNonceServices]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/nonce/OAuthNonceServices.html -[ExpiringTimestampNonceServices]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/nonce/ExpiringTimestampNonceServices.html -[InMemoryNonceServices]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/nonce/InMemoryNonceServices.html -[OAuthCallbackServices]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/callback/OAuthCallbackServices.html -[InMemoryCallbackServices]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/callback/InMemoryCallbackServices.html -[OAuthVerifierServices]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/verifier/OAuthVerifierServices.html -[RandomValueInMemoryVerifierServices]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/verifier/RandomValueInMemoryVerifierServices.html -[attributes-package]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/attributes/package-summary.html -[ConsumerSecurityConfig]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/attributes/ConsumerSecurityConfig.html -[ConsumerSecurityVoter]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/attributes/ConsumerSecurityVoter.html -[ProtectedResourceDetailsService]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/consumer/ProtectedResourceDetailsService.html -[InMemoryProtectedResourceDetailsService]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/consumer/InMemoryProtectedResourceDetailsService.html -[BaseProtectedResourceDetails]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/consumer/BaseProtectedResourceDetails.html -[OAuthConsumerTokenServices]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/consumer/token/OAuthConsumerTokenServices.html -[HttpSessionBasedTokenServices]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/consumer/token/HttpSessionBasedTokenServices.html -[OAuthConsumerContextFilter]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/consumer/OAuthConsumerContextFilter.html -[OAuthConsumerProcessingFilter]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/consumer/OAuthConsumerProcessingFilter.html -[OAuthRestTemplate]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/consumer/OAuthRestTemplate.html +[ConsumerDetailsService]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/ConsumerDetailsService.html +[ConsumerDetails]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/ConsumerDetails.html +[InMemoryConsumerDetailsService]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/InMemoryConsumerDetailsService.html +[BaseConsumerDetails]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/BaseConsumerDetails.html +[OAuthProviderTokenServices]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/token/OAuthProviderTokenServices.html +[RandomValueProviderTokenServices]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/token/RandomValueProviderTokenServices.html +[InMemoryProviderTokenServices]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/token/InMemoryProviderTokenServices.html +[UnauthenticatedRequestTokenProcessingFilter]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/UnauthenticatedRequestTokenProcessingFilter.html +[UserAuthorizationProcessingFilter]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/UserAuthorizationProcessingFilter.html +[AccessTokenProcessingFilter]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/AccessTokenProcessingFilter.html +[ProtectedResourceProcessingFilter]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/ProtectedResourceProcessingFilter.html +[OAuthNonceServices]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/nonce/OAuthNonceServices.html +[ExpiringTimestampNonceServices]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/nonce/ExpiringTimestampNonceServices.html +[InMemoryNonceServices]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/nonce/InMemoryNonceServices.html +[OAuthCallbackServices]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/callback/OAuthCallbackServices.html +[InMemoryCallbackServices]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/callback/InMemoryCallbackServices.html +[OAuthVerifierServices]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/verifier/OAuthVerifierServices.html +[RandomValueInMemoryVerifierServices]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/verifier/RandomValueInMemoryVerifierServices.html +[attributes-package]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/attributes/package-summary.html +[ConsumerSecurityConfig]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/attributes/ConsumerSecurityConfig.html +[ConsumerSecurityVoter]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/attributes/ConsumerSecurityVoter.html +[ProtectedResourceDetailsService]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/consumer/ProtectedResourceDetailsService.html +[InMemoryProtectedResourceDetailsService]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/consumer/InMemoryProtectedResourceDetailsService.html +[BaseProtectedResourceDetails]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/consumer/BaseProtectedResourceDetails.html +[OAuthConsumerTokenServices]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/consumer/token/OAuthConsumerTokenServices.html +[HttpSessionBasedTokenServices]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/consumer/token/HttpSessionBasedTokenServices.html +[OAuthConsumerContextFilter]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/consumer/OAuthConsumerContextFilter.html +[OAuthConsumerProcessingFilter]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/consumer/OAuthConsumerProcessingFilter.html +[OAuthRestTemplate]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/consumer/OAuthRestTemplate.html [oauth1.xsd]: http://www.springframework.org/schema/security/spring-security-oauth.xsd "oauth1.xsd" diff --git a/docs/oauth2.md b/docs/oauth2.md index a90370fb5..8345f788b 100644 --- a/docs/oauth2.md +++ b/docs/oauth2.md @@ -269,5 +269,5 @@ Facebook token responses also contain a non-compliant JSON entry for the expiry [AccessTokenProviderChain]: /spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/AccessTokenProviderChain.java [OAuth2RestTemplate]: /spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/OAuth2RestTemplate.java [OAuth2ProtectedResourceDetails]: /spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/resource/OAuth2ProtectedResourceDetails.java - [restTemplate]: http://static.springsource.org/spring/docs/3.2.x/javadoc-api/org/springframework/web/client/RestTemplate.html "RestTemplate" + [restTemplate]: http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html "RestTemplate" [Facebook]: http://developers.facebook.com/docs/authentication "Facebook" diff --git a/docs/tutorial.md b/docs/tutorial.md index a342d94f3..bad04c0b2 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -21,9 +21,9 @@ to access her photos on Sparklr without ever giving Tonr her credentials to Spar There is a Sparklr application for both OAuth 1.0 and for OAuth 2.0, likewise Tonr. The best way to run them is to clone or download the -[repo on github](https://github.com/SpringSource/spring-security-oauth/tree) +[repo on github](https://github.com/spring-projects/spring-security-oauth) and run from source code See the -[samples/README.md](https://github.com/SpringSource/spring-security-oauth/tree/master/samples) +[samples/README.md](https://github.com/spring-projects/spring-security-oauth/tree/master/samples) for detailed instructions. OAuth 1.0|OAuth 2.0 @@ -41,7 +41,7 @@ many MVC applications use a root context and a child for the DispatcherServlet). Checkout the Sparklr and Tonr applications, and take a look around. Note especially the Spring configuration files in `src/main/webapp/WEB-INF`. For Sparklr, you'll notice the definition of the OAuth provider mechanism and the consumer/client details along with the -[standard spring security configuration](http://static.springsource.org/spring-security/site/docs/3.0.x/reference/ns-config.html) elements. For Tonr, +[standard spring security configuration](http://docs.spring.io/spring-security/site/docs/4.0.x/reference/html/ns-config.html) elements. For Tonr, you'll notice the definition of the OAuth consumer/client mechanism and the resource details. For more information about the necessary components of an OAuth provider and consumer, see the [developers guide](devguide.html). diff --git a/docs/twolegged.md b/docs/twolegged.md index 9ffbf78ef..1ca6356c0 100644 --- a/docs/twolegged.md +++ b/docs/twolegged.md @@ -27,7 +27,7 @@ authentication will be set up in the context. However, if a user authentication `org.springframework.security.oauth.provider.OAuthAuthenticationHandler` that loads the user authentication, and provide a reference to the alternate implementation using the "auth-handler-ref" attribute of the "provider" configuration element. -[ConsumerDetailsService]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/ConsumerDetailsService.html -[ConsumerDetails]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/ConsumerDetails.html -[ExtraTrustConsumerDetails]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/ExtraTrustConsumerDetails.html -[isRequiredToObtainAuthenticatedToken]: http://static.springsource.org/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/ExtraTrustConsumerDetails.html#isRequiredToObtainAuthenticatedToken() +[ConsumerDetailsService]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/ConsumerDetailsService.html +[ConsumerDetails]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/ConsumerDetails.html +[ExtraTrustConsumerDetails]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/ExtraTrustConsumerDetails.html +[isRequiredToObtainAuthenticatedToken]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth/provider/ExtraTrustConsumerDetails.html#isRequiredToObtainAuthenticatedToken() diff --git a/spring-security-oauth/src/main/resources/org/springframework/security/oauth/spring-security-oauth-1.0.xsd b/spring-security-oauth/src/main/resources/org/springframework/security/oauth/spring-security-oauth-1.0.xsd index 45a817dcd..97ae17460 100644 --- a/spring-security-oauth/src/main/resources/org/springframework/security/oauth/spring-security-oauth-1.0.xsd +++ b/spring-security-oauth/src/main/resources/org/springframework/security/oauth/spring-security-oauth-1.0.xsd @@ -257,7 +257,7 @@ - Element for declaring and configuring an expression handler for oauth security expressions. See http://static.springsource.org/spring-security/site/docs/3.0.x/reference/el-access.html + Element for declaring and configuring an expression handler for oauth security expressions. See http://docs.spring.io/spring-security/site/docs/4.0.x/reference/html/el-access.html diff --git a/src/site/apt/index.apt b/src/site/apt/index.apt index deb08ed9e..dba39cae5 100644 --- a/src/site/apt/index.apt +++ b/src/site/apt/index.apt @@ -11,5 +11,5 @@ Welcome auto-generated site, including Javadocs and project reports (see sidebar). For user and develeoper documentation please see the readmes in the source code and the - {{{http://github.com/SpringSource/spring-security-oauth/wiki}wiki}} + {{{https://github.com/spring-projects/spring-security-oauth/wiki}wiki}} on the Github site. From 10c6c4e5a26e391435c08952c868ed43386eb7ab Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 16 Apr 2015 11:51:20 +0100 Subject: [PATCH 421/831] Defensive coding against race condition / bug in TokenStore If an access token is in the store it should always have a non-null authentication attached. There is a possible race condition in DefaultTokenServices though, and this change guards against it bu throwing InvalidTokenException instead of the NullPointerException. Fixes gh-458 --- .../provider/token/DefaultTokenServices.java | 4 +++ .../token/DefaultTokenServicesTests.java | 33 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesTests.java diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java index 9faf6d6e8..f580f0596 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java @@ -236,6 +236,10 @@ else if (accessToken.isExpired()) { } OAuth2Authentication result = tokenStore.readAuthentication(accessToken); + if (result == null) { + // in case of race condition + throw new InvalidTokenException("Invalid access token: " + accessTokenValue); + } if (clientDetailsService != null) { String clientId = result.getOAuth2Request().getClientId(); try { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesTests.java new file mode 100644 index 000000000..7eda9601b --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesTests.java @@ -0,0 +1,33 @@ +package org.springframework.security.oauth2.provider.token; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; + +public class DefaultTokenServicesTests { + + private DefaultTokenServices services; + private TokenStore tokenStore = Mockito.mock(TokenStore.class); + + @Before + public void init() throws Exception { + services = new DefaultTokenServices(); + services.setTokenStore(tokenStore); + services.afterPropertiesSet(); + } + + @Test(expected = InvalidTokenException.class) + public void testAccidentalNullAuthentication() { + Mockito.when(tokenStore.readAccessToken(Mockito.anyString())).thenReturn( + new DefaultOAuth2AccessToken("FOO")); + // A bug in the TokenStore or a race condition could lead to the authentication + // being null even if the token is not: + Mockito.when(tokenStore.readAuthentication(Mockito.any(OAuth2AccessToken.class))) + .thenReturn(null); + services.loadAuthentication("FOO"); + } + +} From f25592e682303b0cf89e1d7555174bac18e174df Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 17 Apr 2015 13:04:03 +0100 Subject: [PATCH 422/831] Update oauth2 docs to clarify usage of checkUserScopes flag Fixes gh-450 --- docs/oauth2.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/oauth2.md b/docs/oauth2.md index 8345f788b..213542a11 100644 --- a/docs/oauth2.md +++ b/docs/oauth2.md @@ -129,6 +129,10 @@ Most of the Authorization Server endpoints are used primarily by machines, but t Error handling in an Authorization Server uses standard Spring MVC features, namely `@ExceptionHandler` methods in the endpoints themselves. Users can also provide a `WebResponseExceptionTranslator` to the endpoints themselves which is the best way to change the content of the responses as opposed to the way they are rendered. The rendering of exceptions delegates to `HttpMesssageConverters` (which can be added to the MVC configuration) in the case of token endpoint and to the OAuth error view (`/oauth/error`) in the case of teh authorization endpoint. The whitelabel error endpoint is provided for HTML responses, but users probably need to provide a custom implementation (e.g. just add a `@Controller` with `@RequestMapping("/oauth/error")`). +## Mapping User Roles to Scopes + +It is sometimes useful to limit the scope of tokens not only by the scopes assigned to the client, but also according to the user's own permissions. If you use a `DefaultOAuth2RequestFactory` in your `AuthorizationEndpoint` you can set a flag `checkUserScopes=true` to restrict permitted scopes to only those that match the user's roles. You can also inject an `OAuth2RequestFactory` into the `TokenEndpoint` but that only works (i.e. with password grants) if you also install a `TokenEndpointAuthenticationFilter` - you just need to add that filter after the HTTP `BasicAuthenticationFilter`. Of course, you can also implement your own rules for mapping scopes to roles and install your own version of the `OAuth2RequestFactory`. The `AuthorizationServerEndpointsConfigurer` allows you to inject a custom `OAuth2RequestFactory` so you can use that feature to set up a factory if you use `@EnableAuthorizationServer`. + ## Resource Server Configuration A Resource Server (can be the same as the Authorization Server or a separate application) serves resources that are protected by the OAuth2 token. Spring OAuth provides a Spring Security authentication filter that implements this protection. You can switch it on with `@EnableResourceServer` on an `@Configuration` class, and configure it (as necessary) using a `ResourceServerConfigurer`. The following features can be configured: From 0c0888ffbd321afb5ac910a33169b01afe9e92c2 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 14 May 2015 15:31:52 +0100 Subject: [PATCH 423/831] Simplify addition of custom token granter It wasn't hard in principle to add a custom granter, but since all practical examples of granters need at least an `AuthorizationServerTokenServices` and probably also a `ClientDetailsService` it was quite inconvenient to do, because those things are created for you by the same `AuthorizationServerEndpointsConfigurer` that is used to override the `TokenGranter`. (I.e. you would have to customize all 3 really.) This change makes the common granter helpers (token services, client details service, and outh2 request factory) available as lazy proxies so even if the token granter is created before the configuration is executed for those services it can still use them later. The convenient `AbstractTokenGranter` can therefore bew used as a base class for instance. There is a sample in test/annotation/custom-grant. Fixes gh-422 --- .../oauth2/common/util/ProxyCreator.java | 71 ++++++++++++++ ...uthorizationServerEndpointsConfigurer.java | 75 +++++++++++---- tests/annotation/custom-grant/README.md | 12 +++ tests/annotation/custom-grant/pom.xml | 50 ++++++++++ .../src/main/java/demo/Application.java | 96 +++++++++++++++++++ .../main/java/demo/CustomTokenGranter.java | 57 +++++++++++ .../src/main/resources/application.yml | 11 +++ .../src/test/java/demo/AdHocTests.java | 34 +++++++ .../src/test/java/demo/ApplicationTests.java | 20 ++++ .../demo/AuthorizationCodeProviderTests.java | 76 +++++++++++++++ .../demo/ClientCredentialsProviderTests.java | 14 +++ .../test/java/demo/CustomProviderTests.java | 45 +++++++++ .../test/java/demo/ImplicitProviderTests.java | 74 ++++++++++++++ .../java/demo/ProtectedResourceTests.java | 27 ++++++ .../java/demo/RefreshTokenSupportTests.java | 13 +++ .../ResourceOwnerPasswordProviderTests.java | 13 +++ tests/annotation/pom.xml | 1 + 17 files changed, 669 insertions(+), 20 deletions(-) create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/ProxyCreator.java create mode 100644 tests/annotation/custom-grant/README.md create mode 100644 tests/annotation/custom-grant/pom.xml create mode 100644 tests/annotation/custom-grant/src/main/java/demo/Application.java create mode 100644 tests/annotation/custom-grant/src/main/java/demo/CustomTokenGranter.java create mode 100644 tests/annotation/custom-grant/src/main/resources/application.yml create mode 100644 tests/annotation/custom-grant/src/test/java/demo/AdHocTests.java create mode 100644 tests/annotation/custom-grant/src/test/java/demo/ApplicationTests.java create mode 100755 tests/annotation/custom-grant/src/test/java/demo/AuthorizationCodeProviderTests.java create mode 100644 tests/annotation/custom-grant/src/test/java/demo/ClientCredentialsProviderTests.java create mode 100644 tests/annotation/custom-grant/src/test/java/demo/CustomProviderTests.java create mode 100644 tests/annotation/custom-grant/src/test/java/demo/ImplicitProviderTests.java create mode 100644 tests/annotation/custom-grant/src/test/java/demo/ProtectedResourceTests.java create mode 100644 tests/annotation/custom-grant/src/test/java/demo/RefreshTokenSupportTests.java create mode 100644 tests/annotation/custom-grant/src/test/java/demo/ResourceOwnerPasswordProviderTests.java diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/ProxyCreator.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/ProxyCreator.java new file mode 100644 index 000000000..d99622c15 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/ProxyCreator.java @@ -0,0 +1,71 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.springframework.security.oauth2.common.util; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +import org.springframework.beans.factory.ObjectFactory; + +/** + * @author Dave Syer + * + */ +public class ProxyCreator { + + @SuppressWarnings("unchecked") + public static T getProxy(Class type, ObjectFactory factory) { + return (T) Proxy.newProxyInstance(ProxyCreator.class.getClassLoader(), new Class[] { type }, + new LazyInvocationHandler(factory)); + } + + private static class LazyInvocationHandler implements InvocationHandler { + + private T target; + + private ObjectFactory factory; + + public LazyInvocationHandler(ObjectFactory factory) { + this.factory = factory; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + // Invocation on interface coming in... + + if (method.getName().equals("equals")) { + return (proxy == args[0]); + } + else if (method.getName().equals("hashCode")) { + return System.identityHashCode(proxy); + } + try { + return method.invoke(getTarget(method), args); + } + catch (InvocationTargetException ex) { + throw ex.getTargetException(); + } + } + + private Object getTarget(Method method) { + if (target == null) { + target = factory.getObject(); + } + return target; + } + + } +} 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 29d34952d..42d07bc60 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 @@ -24,12 +24,16 @@ import java.util.Map; import java.util.Set; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.ObjectFactory; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.ProviderManager; import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper; import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +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; @@ -37,6 +41,7 @@ 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; @@ -133,7 +138,13 @@ public final class AuthorizationServerEndpointsConfigurer { private WebResponseExceptionTranslator exceptionTranslator; public AuthorizationServerTokenServices getTokenServices() { - return tokenServices; + return ProxyCreator.getProxy(AuthorizationServerTokenServices.class, + new ObjectFactory() { + @Override + public AuthorizationServerTokenServices getObject() throws BeansException { + return tokenServices(); + } + }); } public TokenStore getTokenStore() { @@ -153,11 +164,21 @@ public ApprovalStore getApprovalStore() { } public ClientDetailsService getClientDetailsService() { - return clientDetailsService; + return ProxyCreator.getProxy(ClientDetailsService.class, new ObjectFactory() { + @Override + public ClientDetailsService getObject() throws BeansException { + return clientDetailsService(); + } + }); } public OAuth2RequestFactory getOAuth2RequestFactory() { - return requestFactory(); + return ProxyCreator.getProxy(OAuth2RequestFactory.class, new ObjectFactory() { + @Override + public OAuth2RequestFactory getObject() throws BeansException { + return requestFactory(); + } + }); } public OAuth2RequestValidator getOAuth2RequestValidator() { @@ -507,25 +528,39 @@ private OAuth2RequestValidator requestValidator() { return requestValidator; } + private List getDefaultTokenGranters() { + ClientDetailsService clientDetails = clientDetailsService(); + AuthorizationServerTokenServices tokenServices = tokenServices(); + AuthorizationCodeServices authorizationCodeServices = authorizationCodeServices(); + OAuth2RequestFactory requestFactory = requestFactory(); + + List tokenGranters = new ArrayList(); + tokenGranters.add(new AuthorizationCodeTokenGranter(tokenServices, authorizationCodeServices, clientDetails, + requestFactory)); + tokenGranters.add(new RefreshTokenGranter(tokenServices, clientDetails, requestFactory)); + ImplicitTokenGranter implicit = new ImplicitTokenGranter(tokenServices, clientDetails, requestFactory); + tokenGranters.add(implicit); + tokenGranters.add(new ClientCredentialsTokenGranter(tokenServices, clientDetails, requestFactory)); + if (authenticationManager != null) { + tokenGranters.add(new ResourceOwnerPasswordTokenGranter(authenticationManager, tokenServices, + clientDetails, requestFactory)); + } + return tokenGranters; + } + private TokenGranter tokenGranter() { if (tokenGranter == null) { - ClientDetailsService clientDetails = clientDetailsService(); - AuthorizationServerTokenServices tokenServices = tokenServices(); - AuthorizationCodeServices authorizationCodeServices = authorizationCodeServices(); - OAuth2RequestFactory requestFactory = requestFactory(); - - List tokenGranters = new ArrayList(); - tokenGranters.add(new AuthorizationCodeTokenGranter(tokenServices, authorizationCodeServices, - clientDetails, requestFactory)); - tokenGranters.add(new RefreshTokenGranter(tokenServices, clientDetails, requestFactory)); - ImplicitTokenGranter implicit = new ImplicitTokenGranter(tokenServices, clientDetails, requestFactory); - tokenGranters.add(implicit); - tokenGranters.add(new ClientCredentialsTokenGranter(tokenServices, clientDetails, requestFactory)); - if (authenticationManager != null) { - tokenGranters.add(new ResourceOwnerPasswordTokenGranter(authenticationManager, tokenServices, - clientDetails, requestFactory)); - } - tokenGranter = new CompositeTokenGranter(tokenGranters); + tokenGranter = new TokenGranter() { + private CompositeTokenGranter delegate; + + @Override + public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) { + if (delegate == null) { + delegate = new CompositeTokenGranter(getDefaultTokenGranters()); + } + return delegate.grant(grantType, tokenRequest); + } + }; } return tokenGranter; } diff --git a/tests/annotation/custom-grant/README.md b/tests/annotation/custom-grant/README.md new file mode 100644 index 000000000..c7a66f89a --- /dev/null +++ b/tests/annotation/custom-grant/README.md @@ -0,0 +1,12 @@ +This project shows what you can do with the minimum configuration to +set up an Authorization Server with a custom grant type. + +For the Authorization Server you need to `@EnableAuthorizationServer` +and also configure at least one client registration +(`OAuth2ClientDetails`). You can see this is the bulk of +`Application.java`. + +An `AuthenticationManager` is created by Spring Boot (it has a single +user, named "user", with password "password", per +`application.yml`). It is needed in the Authorization Server to +provide authentication for the Resource Owner Password grant type. diff --git a/tests/annotation/custom-grant/pom.xml b/tests/annotation/custom-grant/pom.xml new file mode 100644 index 000000000..bd27e6e86 --- /dev/null +++ b/tests/annotation/custom-grant/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + + spring-oauth2-tests-custom-grant + + spring-oauth-tests-custom-grant + Demo project + + + org.demo + spring-oauth2-tests-parent + 2.0.8.BUILD-SNAPSHOT + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.security.oauth + spring-security-oauth2 + + + org.demo + spring-oauth2-tests-common + ${project.version} + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/tests/annotation/custom-grant/src/main/java/demo/Application.java b/tests/annotation/custom-grant/src/main/java/demo/Application.java new file mode 100644 index 000000000..7dd777944 --- /dev/null +++ b/tests/annotation/custom-grant/src/main/java/demo/Application.java @@ -0,0 +1,96 @@ +package demo; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpStatus; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; +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.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; +import org.springframework.security.oauth2.provider.CompositeTokenGranter; +import org.springframework.security.oauth2.provider.TokenGranter; +import org.springframework.util.MultiValueMap; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +@Configuration +@EnableAutoConfiguration +@EnableResourceServer +@RestController +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + @RequestMapping("/") + public String home() { + return "Hello World"; + } + + @RequestMapping(value = "/", method = RequestMethod.POST) + @ResponseStatus(HttpStatus.CREATED) + public String create(@RequestBody MultiValueMap map) { + return "OK"; + } + + @Configuration + @EnableAuthorizationServer + protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter { + + @Autowired + private AuthenticationManager authenticationManager; + + @Override + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + endpoints.authenticationManager(authenticationManager); + endpoints.tokenGranter(tokenGranter(endpoints)); + } + + private TokenGranter tokenGranter(final AuthorizationServerEndpointsConfigurer endpoints) { + List granters = new ArrayList(Arrays.asList(endpoints.getTokenGranter())); + granters.add(new CustomTokenGranter(endpoints.getTokenServices(), endpoints.getClientDetailsService(), endpoints.getOAuth2RequestFactory(), "custom")); + return new CompositeTokenGranter(granters); + } + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + // @formatter:off + clients.inMemory() + .withClient("my-trusted-client") + .authorizedGrantTypes("custom", "password", "authorization_code", "refresh_token", "implicit") + .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") + .scopes("read", "write", "trust") + .resourceIds("oauth2-resource") + .accessTokenValiditySeconds(600) + .and() + .withClient("my-client-with-registered-redirect") + .authorizedGrantTypes("authorization_code") + .authorities("ROLE_CLIENT") + .scopes("read", "trust") + .resourceIds("oauth2-resource") + .redirectUris("http://anywhere/?key=value") + .and() + .withClient("my-client-with-secret") + .authorizedGrantTypes("client_credentials", "password") + .authorities("ROLE_CLIENT") + .scopes("read") + .resourceIds("oauth2-resource") + .secret("secret"); + // @formatter:on + } + + } + +} diff --git a/tests/annotation/custom-grant/src/main/java/demo/CustomTokenGranter.java b/tests/annotation/custom-grant/src/main/java/demo/CustomTokenGranter.java new file mode 100644 index 000000000..cab7c0417 --- /dev/null +++ b/tests/annotation/custom-grant/src/main/java/demo/CustomTokenGranter.java @@ -0,0 +1,57 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package demo; + +import java.util.List; +import java.util.Map; + +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.oauth2.common.util.OAuth2Utils; +import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; +import org.springframework.security.oauth2.provider.TokenGranter; +import org.springframework.security.oauth2.provider.TokenRequest; +import org.springframework.security.oauth2.provider.token.AbstractTokenGranter; +import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; + +/** + * A custom {@link TokenGranter} that always grants a token, and does not authenticate users (hence the client has to be + * trusted to only send authenticated client details). + * + * @author Dave Syer + * + */ +public class CustomTokenGranter extends AbstractTokenGranter { + + CustomTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, + OAuth2RequestFactory requestFactory, String grantType) { + super(tokenServices, clientDetailsService, requestFactory, grantType); + } + + protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) { + Map params = tokenRequest.getRequestParameters(); + String username = params.containsKey("username") ? params.get("username") : "guest"; + List authorities = params.containsKey("authorities") ? AuthorityUtils + .createAuthorityList(OAuth2Utils.parseParameterList(params.get("authorities")).toArray(new String[0])) + : AuthorityUtils.NO_AUTHORITIES; + Authentication user = new UsernamePasswordAuthenticationToken(username, "N/A", authorities); + OAuth2Authentication authentication = new OAuth2Authentication(tokenRequest.createOAuth2Request(client), user); + return authentication; + } +} \ No newline at end of file diff --git a/tests/annotation/custom-grant/src/main/resources/application.yml b/tests/annotation/custom-grant/src/main/resources/application.yml new file mode 100644 index 000000000..a7c74036e --- /dev/null +++ b/tests/annotation/custom-grant/src/main/resources/application.yml @@ -0,0 +1,11 @@ +spring: + application: + name: vanilla +management: + context_path: /admin +security: + user: + password: password +logging: + level: + org.springframework.security: DEBUG \ No newline at end of file diff --git a/tests/annotation/custom-grant/src/test/java/demo/AdHocTests.java b/tests/annotation/custom-grant/src/test/java/demo/AdHocTests.java new file mode 100644 index 000000000..ee518795d --- /dev/null +++ b/tests/annotation/custom-grant/src/test/java/demo/AdHocTests.java @@ -0,0 +1,34 @@ +/* + * Copyright 20013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package demo; + +import org.junit.Ignore; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +/** + * @author Dave Syer + * + */ +@RunWith(Suite.class) +// @formatter:off +@SuiteClasses({ + RefreshTokenSupportTests.class + }) +// @formatter:on +@Ignore("Test suite for tracking order dependencies") +public class AdHocTests { + +} diff --git a/tests/annotation/custom-grant/src/test/java/demo/ApplicationTests.java b/tests/annotation/custom-grant/src/test/java/demo/ApplicationTests.java new file mode 100644 index 000000000..15eca8da6 --- /dev/null +++ b/tests/annotation/custom-grant/src/test/java/demo/ApplicationTests.java @@ -0,0 +1,20 @@ +package demo; + +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; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = Application.class) +@WebAppConfiguration +@IntegrationTest("server.port=0") +public class ApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/tests/annotation/custom-grant/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/custom-grant/src/test/java/demo/AuthorizationCodeProviderTests.java new file mode 100755 index 000000000..49a38d4ab --- /dev/null +++ b/tests/annotation/custom-grant/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -0,0 +1,76 @@ +/* + * Copyright 2006-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 demo; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +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; +import org.springframework.util.LinkedMultiValueMap; + +import sparklr.common.AbstractAuthorizationCodeProviderTests; + +/** + * @author Dave Syer + */ +@SpringApplicationConfiguration(classes = Application.class) +public class AuthorizationCodeProviderTests extends AbstractAuthorizationCodeProviderTests { + + @Test + @OAuth2ContextConfiguration(resource = MyTrustedClient.class, initialize = false) + public void testPostToProtectedResource() throws Exception { + approveAccessTokenGrant("http://anywhere/", true); + assertNotNull(context.getAccessToken()); + LinkedMultiValueMap form = new LinkedMultiValueMap<>(); + form.set("foo", "bar"); + assertEquals(HttpStatus.CREATED, http.postForStatus("/", form).getStatusCode()); + } + + @Test + public void testWrongClientIdProvided() throws Exception { + ResponseEntity response = attemptToGetConfirmationPage("no-such-client", "http://anywhere/"); + // With no client id you get an InvalidClientException on the server which is forwarded to /oauth/error + assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); + String body = response.getBody(); + assertTrue("Wrong body: " + body, body.contains(" response = attemptToGetConfirmationPage("no-such-client", "http://anywhere/", null); + // With bad client id you get an InvalidClientException on the server which is forwarded to /oauth/error + assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); + String body = response.getBody(); + assertTrue("Wrong body: " + body, body.contains(" response = attemptToGetConfirmationPage("no-such-client", "http://anywhere/", "unsupported"); + // With bad client id you get an InvalidClientException on the server which is forwarded to /oauth/error + assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); + String body = response.getBody(); + assertTrue("Wrong body: " + body, body.contains(" form = new LinkedMultiValueMap(); + form.set("grant_type", "custom"); + HttpHeaders headers = new HttpHeaders(); + headers.set("Authorization", "Basic " + new String(Base64.encode(("my-trusted-client:").getBytes()))); + @SuppressWarnings("rawtypes") + ResponseEntity response = http.postForMap("/oauth/token", headers, form); + assertEquals(HttpStatus.OK, response.getStatusCode()); + } + + @Test + public void invalidGrant() throws Exception { + LinkedMultiValueMap form = new LinkedMultiValueMap(); + form.set("grant_type", "foo"); + HttpHeaders headers = new HttpHeaders(); + headers.set("Authorization", "Basic " + new String(Base64.encode(("my-trusted-client:").getBytes()))); + @SuppressWarnings("rawtypes") + ResponseEntity response = http.postForMap("/oauth/token", headers, form); + assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); + } + +} diff --git a/tests/annotation/custom-grant/src/test/java/demo/ImplicitProviderTests.java b/tests/annotation/custom-grant/src/test/java/demo/ImplicitProviderTests.java new file mode 100644 index 000000000..92379335a --- /dev/null +++ b/tests/annotation/custom-grant/src/test/java/demo/ImplicitProviderTests.java @@ -0,0 +1,74 @@ +package demo; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +import org.junit.Test; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.boot.test.TestRestTemplate; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration; +import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordResourceDetails; + +import sparklr.common.AbstractImplicitProviderTests; + +/** + * @author Dave Syer + */ +@SpringApplicationConfiguration(classes = Application.class) +public class ImplicitProviderTests extends AbstractImplicitProviderTests { + + @Test + @OAuth2ContextConfiguration(ResourceOwner.class) + public void parallelGrants() throws Exception { + getToken(); + Collection> futures = new HashSet>(); + ExecutorService pool = Executors.newFixedThreadPool(10); + for (int i = 0; i < 100; i++) { + futures.add(pool.submit(new Runnable() { + @Override + public void run() { + getToken(); + } + })); + } + for (Future future : futures) { + future.get(); + } + } + + private void getToken() { + Map form = new LinkedHashMap(); + form.put("client_id", "my-trusted-client"); + form.put("redirect_uri", "http://foo.com/"); + form.put("response_type", "token"); + form.put("scope", "read"); + ResponseEntity response = new TestRestTemplate("user", "password") + .getForEntity( + http.getUrl("/oauth/authorize?client_id={client_id}&redirect_uri={redirect_uri}&response_type={response_type}&scope={scope}"), + Void.class, form); + assertEquals(HttpStatus.FOUND, response.getStatusCode()); + assertTrue(response.getHeaders().getLocation().toString().contains("access_token")); + } + + protected static class ResourceOwner extends ResourceOwnerPasswordResourceDetails { + public ResourceOwner(Object target) { + setClientId("my-trusted-client"); + setScope(Arrays.asList("read")); + setId(getClientId()); + setUsername("user"); + setPassword("password"); + } + } + +} diff --git a/tests/annotation/custom-grant/src/test/java/demo/ProtectedResourceTests.java b/tests/annotation/custom-grant/src/test/java/demo/ProtectedResourceTests.java new file mode 100644 index 000000000..c752cbe12 --- /dev/null +++ b/tests/annotation/custom-grant/src/test/java/demo/ProtectedResourceTests.java @@ -0,0 +1,27 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package 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 new file mode 100644 index 000000000..4ed370eea --- /dev/null +++ b/tests/annotation/custom-grant/src/test/java/demo/RefreshTokenSupportTests.java @@ -0,0 +1,13 @@ +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 new file mode 100644 index 000000000..aa5786098 --- /dev/null +++ b/tests/annotation/custom-grant/src/test/java/demo/ResourceOwnerPasswordProviderTests.java @@ -0,0 +1,13 @@ +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/pom.xml b/tests/annotation/pom.xml index ccb0ad078..16f476a1a 100644 --- a/tests/annotation/pom.xml +++ b/tests/annotation/pom.xml @@ -15,6 +15,7 @@ jwt approval jdbc + custom-grant multi client resource From efaf1d6124bf68ac40853f7a86ccb1488bd7bf37 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 14 May 2015 17:27:49 +0100 Subject: [PATCH 424/831] Fix key error in InMemoryTokenServices Removing an access token used the wrong key for clientId and username, so the tokens were still findable even though they had been removed. Fixes gh-439 --- .../token/store/InMemoryTokenStore.java | 4 +- .../AbstractDefaultTokenServicesTests.java | 11 +++ .../token/store/TokenStoreBaseTests.java | 89 +++++++++++++------ 3 files changed, 73 insertions(+), 31 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/InMemoryTokenStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/InMemoryTokenStore.java index ae287f6e3..b5ab22ee4 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/InMemoryTokenStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/InMemoryTokenStore.java @@ -203,11 +203,11 @@ public void removeAccessToken(String tokenValue) { if (authentication != null) { this.authenticationToAccessTokenStore.remove(authenticationKeyGenerator.extractKey(authentication)); Collection tokens; - tokens = this.userNameToAccessTokenStore.get(authentication.getName()); + String clientId = authentication.getOAuth2Request().getClientId(); + tokens = this.userNameToAccessTokenStore.get(getApprovalKey(clientId, authentication.getName())); if (tokens != null) { tokens.remove(removed); } - String clientId = authentication.getOAuth2Request().getClientId(); tokens = this.clientIdToAccessTokenStore.get(clientId); if (tokens != null) { tokens.remove(removed); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractDefaultTokenServicesTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractDefaultTokenServicesTests.java index 3f10b428a..feda46137 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractDefaultTokenServicesTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractDefaultTokenServicesTests.java @@ -19,6 +19,7 @@ import static org.junit.Assert.assertTrue; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.LinkedHashSet; @@ -193,6 +194,16 @@ public void testRefreshedTokenNotExpiring() throws Exception { assertFalse(expectedExpiringRefreshToken instanceof DefaultExpiringOAuth2RefreshToken); } + @Test + public void testRevokedTokenNotAvailable() throws Exception { + OAuth2Authentication authentication = createAuthentication(); + OAuth2AccessToken token = getTokenServices().createAccessToken(authentication); + getTokenServices().revokeToken(token.getValue()); + Collection tokens = getTokenStore().findTokensByClientIdAndUserName(authentication.getOAuth2Request().getClientId(), authentication.getUserAuthentication().getName()); + assertFalse(tokens.contains(token)); + assertTrue(tokens.isEmpty()); + } + protected void configureTokenServices(DefaultTokenServices services) throws Exception { services.setTokenStore(tokenStore); services.setSupportRefreshToken(true); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/TokenStoreBaseTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/TokenStoreBaseTests.java index a81e20ada..c088033e0 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/TokenStoreBaseTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/TokenStoreBaseTests.java @@ -16,6 +16,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import java.util.Collection; import java.util.Date; @@ -32,7 +33,7 @@ import org.springframework.security.oauth2.provider.RequestTokenFactory; import org.springframework.security.oauth2.provider.token.TokenStore; -/** +/** * @author Dave Syer * */ @@ -47,7 +48,8 @@ public void testReadingAuthenticationForTokenThatDoesNotExist() { @Test public void testStoreAccessToken() { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request("id", false), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request( + "id", false), new TestAuthentication("test2", false)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); @@ -61,7 +63,8 @@ public void testStoreAccessToken() { @Test public void testStoreAccessTokenTwice() { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request( "id", false), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request( + "id", false), new TestAuthentication("test2", false)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); @@ -76,21 +79,25 @@ public void testStoreAccessTokenTwice() { @Test public void testRetrieveAccessToken() { - //Test approved request + // Test approved request OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request("id", true); - OAuth2Authentication authentication = new OAuth2Authentication(storedOAuth2Request, new TestAuthentication("test2", true)); + OAuth2Authentication authentication = new OAuth2Authentication(storedOAuth2Request, new TestAuthentication( + "test2", true)); DefaultOAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); - expectedOAuth2AccessToken.setExpiration(new Date(Long.MAX_VALUE-1)); + expectedOAuth2AccessToken.setExpiration(new Date(Long.MAX_VALUE - 1)); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, authentication); - //Test unapproved request + // Test unapproved request storedOAuth2Request = RequestTokenFactory.createOAuth2Request("id", false); authentication = new OAuth2Authentication(storedOAuth2Request, new TestAuthentication("test2", true)); OAuth2AccessToken actualOAuth2AccessToken = getTokenStore().getAccessToken(authentication); assertEquals(expectedOAuth2AccessToken, actualOAuth2AccessToken); - assertEquals(authentication.getUserAuthentication(), getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue()).getUserAuthentication()); - // The authorizationRequest does not match because it is unapproved, but the token was granted to an approved request - assertFalse(storedOAuth2Request.equals(getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue()).getOAuth2Request())); + assertEquals(authentication.getUserAuthentication(), + getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue()).getUserAuthentication()); + // The authorizationRequest does not match because it is unapproved, but the token was granted to an approved + // request + assertFalse(storedOAuth2Request.equals(getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue()) + .getOAuth2Request())); actualOAuth2AccessToken = getTokenStore().getAccessToken(authentication); assertEquals(expectedOAuth2AccessToken, actualOAuth2AccessToken); getTokenStore().removeAccessToken(expectedOAuth2AccessToken); @@ -101,17 +108,20 @@ public void testRetrieveAccessToken() { @Test public void testFindAccessTokensByClientIdAndUserName() { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request("id", false), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request( + "id", false), new TestAuthentication("test2", false)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); - Collection actualOAuth2AccessTokens = getTokenStore().findTokensByClientIdAndUserName("id", "test2"); + Collection actualOAuth2AccessTokens = getTokenStore().findTokensByClientIdAndUserName("id", + "test2"); assertEquals(1, actualOAuth2AccessTokens.size()); } @Test public void testFindAccessTokensByClientId() { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request("id", false), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request( + "id", false), new TestAuthentication("test2", false)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); @@ -126,14 +136,15 @@ public void testReadingAccessTokenForTokenThatDoesNotExist() { @Test public void testRefreshTokenIsNotStoredDuringAccessToken() { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request("id", false), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request( + "id", false), new TestAuthentication("test2", false)); DefaultOAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); expectedOAuth2AccessToken.setRefreshToken(new DefaultOAuth2RefreshToken("refreshToken")); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); OAuth2AccessToken actualOAuth2AccessToken = getTokenStore().readAccessToken("testToken"); assertNotNull(actualOAuth2AccessToken.getRefreshToken()); - + assertNull(getTokenStore().readRefreshToken("refreshToken")); } @@ -141,12 +152,14 @@ public void testRefreshTokenIsNotStoredDuringAccessToken() { public void testStoreRefreshToken() { DefaultOAuth2RefreshToken expectedExpiringRefreshToken = new DefaultExpiringOAuth2RefreshToken("testToken", new Date()); - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request("id", false), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request( + "id", false), new TestAuthentication("test2", false)); getTokenStore().storeRefreshToken(expectedExpiringRefreshToken, expectedAuthentication); OAuth2RefreshToken actualExpiringRefreshToken = getTokenStore().readRefreshToken("testToken"); assertEquals(expectedExpiringRefreshToken, actualExpiringRefreshToken); - assertEquals(expectedAuthentication, getTokenStore().readAuthenticationForRefreshToken(expectedExpiringRefreshToken)); + assertEquals(expectedAuthentication, + getTokenStore().readAuthenticationForRefreshToken(expectedExpiringRefreshToken)); getTokenStore().removeRefreshToken(expectedExpiringRefreshToken); assertNull(getTokenStore().readRefreshToken("testToken")); assertNull(getTokenStore().readAuthentication(expectedExpiringRefreshToken.getValue())); @@ -159,40 +172,58 @@ public void testReadingRefreshTokenForTokenThatDoesNotExist() { @Test public void testGetAccessTokenForDeletedUser() throws Exception { - //Test approved request + // Test approved request OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request("id", true); - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(storedOAuth2Request, new TestAuthentication("test", true)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(storedOAuth2Request, + new TestAuthentication("test", true)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); assertEquals(expectedOAuth2AccessToken, getTokenStore().getAccessToken(expectedAuthentication)); assertEquals(expectedAuthentication, getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue())); - - //Test unapproved request + + // Test unapproved request storedOAuth2Request = RequestTokenFactory.createOAuth2Request("id", false); - OAuth2Authentication anotherAuthentication = new OAuth2Authentication(storedOAuth2Request, new TestAuthentication("test", true)); + OAuth2Authentication anotherAuthentication = new OAuth2Authentication(storedOAuth2Request, + new TestAuthentication("test", true)); assertEquals(expectedOAuth2AccessToken, getTokenStore().getAccessToken(anotherAuthentication)); // The generated key for the authentication is the same as before, but the two auths are not equal. This could // happen if there are 2 users in a system with the same username, or (more likely), if a user account was // deleted and re-created. - assertEquals(anotherAuthentication.getUserAuthentication(), getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue()).getUserAuthentication()); - // The authorizationRequest does not match because it is unapproved, but the token was granted to an approved request - assertFalse(storedOAuth2Request.equals(getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue()).getOAuth2Request())); + assertEquals(anotherAuthentication.getUserAuthentication(), + getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue()).getUserAuthentication()); + // The authorizationRequest does not match because it is unapproved, but the token was granted to an approved + // request + assertFalse(storedOAuth2Request.equals(getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue()) + .getOAuth2Request())); } @Test public void testRemoveRefreshToken() { - OAuth2RefreshToken expectedExpiringRefreshToken = new DefaultExpiringOAuth2RefreshToken("testToken", - new Date()); - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request("id", false), new TestAuthentication("test2", false)); + OAuth2RefreshToken expectedExpiringRefreshToken = new DefaultExpiringOAuth2RefreshToken("testToken", new Date()); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request( + "id", false), new TestAuthentication("test2", false)); getTokenStore().storeRefreshToken(expectedExpiringRefreshToken, expectedAuthentication); getTokenStore().removeRefreshToken(expectedExpiringRefreshToken); - + assertNull(getTokenStore().readRefreshToken("testToken")); } + @Test + public void testRemovedTokenCannotBeFoundByUsername() { + OAuth2AccessToken token = new DefaultOAuth2AccessToken("testToken"); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request( + "id", false), new TestAuthentication("test2", false)); + getTokenStore().storeAccessToken(token, expectedAuthentication); + getTokenStore().removeAccessToken(token); + Collection tokens = getTokenStore().findTokensByClientIdAndUserName("id", "test2"); + assertFalse(tokens.contains(token)); + assertTrue(tokens.isEmpty()); + } + protected static class TestAuthentication extends AbstractAuthenticationToken { private static final long serialVersionUID = 1L; + private String principal; public TestAuthentication(String name, boolean authenticated) { From 9c06d8a50fba7321f1a35bbe33640738a3d8ebc8 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 14 May 2015 17:43:21 +0100 Subject: [PATCH 425/831] Ensure OAuth2Auth*Details has equals() and hashCode() Fixes gh-478 --- .../oauth2/provider/OAuth2Authentication.java | 4 ++ .../OAuth2AuthenticationDetails.java | 42 +++++++++++++++++++ .../provider/OAuth2AuthenticationTests.java | 13 ++++++ .../OAuth2AuthenticationDetailsTests.java | 39 +++++++++++++++++ 4 files changed, 98 insertions(+) create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationDetailsTests.java diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Authentication.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Authentication.java index 8f34613bb..8717a3af4 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Authentication.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2Authentication.java @@ -93,6 +93,10 @@ public boolean equals(Object o) { : that.userAuthentication != null) { return false; } + + if (getDetails()!=null ? !getDetails().equals(that.getDetails()) : that.getDetails()!=null) { + // return false; + } return true; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationDetails.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationDetails.java index 49ff29292..e2adb379b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationDetails.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationDetails.java @@ -142,4 +142,46 @@ public String toString() { return display; } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((sessionId == null) ? 0 : sessionId.hashCode()); + result = prime * result + ((tokenType == null) ? 0 : tokenType.hashCode()); + result = prime * result + ((tokenValue == null) ? 0 : tokenValue.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + OAuth2AuthenticationDetails other = (OAuth2AuthenticationDetails) obj; + if (sessionId == null) { + if (other.sessionId != null) + return false; + } + else if (!sessionId.equals(other.sessionId)) + return false; + if (tokenType == null) { + if (other.tokenType != null) + return false; + } + else if (!tokenType.equals(other.tokenType)) + return false; + if (tokenValue == null) { + if (other.tokenValue != null) + return false; + } + else if (!tokenValue.equals(other.tokenValue)) + return false; + return true; + } + + + } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/OAuth2AuthenticationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/OAuth2AuthenticationTests.java index 402362ed8..0e24a6705 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/OAuth2AuthenticationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/OAuth2AuthenticationTests.java @@ -8,8 +8,10 @@ import org.codehaus.jackson.map.ObjectMapper; import org.junit.Test; +import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails; import org.springframework.test.annotation.Rollback; import org.springframework.util.SerializationUtils; @@ -63,4 +65,15 @@ public void testSerialization() { assertEquals(holder, other); } + @Test + public void testSerializationWithDetails() { + OAuth2Authentication holder = new OAuth2Authentication( + new AuthorizationRequest("client", Arrays.asList("read")).createOAuth2Request(), + new UsernamePasswordAuthenticationToken("user", "pwd")); + holder.setDetails(new OAuth2AuthenticationDetails(new MockHttpServletRequest())); + OAuth2Authentication other = (OAuth2Authentication) SerializationUtils.deserialize(SerializationUtils + .serialize(holder)); + assertEquals(holder, other); + } + } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationDetailsTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationDetailsTests.java new file mode 100644 index 000000000..658c958ee --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationDetailsTests.java @@ -0,0 +1,39 @@ +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.springframework.security.oauth2.provider.authentication; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.util.SerializationUtils; + +/** + * @author Dave Syer + * + */ +public class OAuth2AuthenticationDetailsTests { + + @Test + public void testSerializationWithDetails() { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_VALUE, "FOO"); + request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_TYPE, "bearer"); + OAuth2AuthenticationDetails holder = new OAuth2AuthenticationDetails(request); + OAuth2AuthenticationDetails other = (OAuth2AuthenticationDetails) SerializationUtils.deserialize(SerializationUtils + .serialize(holder)); + assertEquals(holder, other); + } + +} From b2a527a4e7c220f4a0a18c231cc4c4f70f294de3 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 15 May 2015 11:05:04 +0100 Subject: [PATCH 426/831] Add some docs on schema.sql (still only for test) Particularly the token tables need a primary key to prevent duplicate rows. Fixes gh-463 --- docs/oauth2.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/oauth2.md b/docs/oauth2.md index 213542a11..aea918866 100644 --- a/docs/oauth2.md +++ b/docs/oauth2.md @@ -56,6 +56,8 @@ The `ClientDetailsServiceConfigurer` (a callback from your `AuthorizationServerC Client details can be updated in a running application by access the underlying store directly (e.g. database tables in the case of `JdbcClientDetailsService`) or through the `ClientDetailsManager` interface (which both implementations of `ClientDetailsService` also implement). +> NOTE: the schema for the JDBC service is not packaged with the library (because there are too many variations you might like to use in practice), but there is an example you can start from in the [test code in github](https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth2/src/test/resources/schema.sql). + ### Managing Tokens The [`AuthorizationServerTokenServices`][AuthorizationServerTokenServices] interface defines the operations that are necessary to manage OAuth 2.0 tokens. Note the following: @@ -71,6 +73,8 @@ When creating your `AuthorizationServerTokenServices` implementation, you may wa * The [JSON Web Token (JWT) version](`JwtTokenStore`) of the store encodes all the data about the grant into the token itself (so no back end store at all which is a significant advantage). One disadvantage is that you can't easily revoke an access token, so they normally are granted with short expiry and the revocation is handled at the refresh token. Another disadvantage is that the tokens can get quite large if you are storing a lot of user credential information in them. The `JwtTokenStore` is not really a "store" in the sense that it doesn't persist any data, but it plays the same role of translating betweeen token values and authentication information in the `DefaultTokenServices`. +> NOTE: the schema for the JDBC service is not packaged with the library (because there are too many variations you might like to use in practice), but there is an example you can start from in the [test code in github](https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth2/src/test/resources/schema.sql). Be sure to `@EnableTransactionManagement` to prevent clashes between client apps competing for the same rows when tokens are created. Note also that the sample schema has explicit `PRIMARY KEY` declarations - these are also necessary in a concurrent environment. + ### JWT Tokens To use JWT tokens you need a `JwtTokenStore` in your Authorization Server. The Resource Server also needs to be able to decode the tokens so the `JwtTokenStore` has a dependency on a `JwtAccessTokenConverter`, and the same implementation is needed by both the Authorization Server and the Resource Server. The tokens are signed by default, and the Resource Server also has to be able to verify the signature, so it either needs the same symmetric (signing) key as the Authorization Server (shared secret, or symmetric key), or it needs the public key (verifier key) that matches the private key (signing key) in the Authorization Server (public-private or asymmetric key). The public key (if available) is exposed by the Authorization Server on the `/oauth/token_key` endpoint, which is secure by default with access rule "denyAll()". You can open it up by injecting a standard SpEL expression into the `AuthorizationServerSecurityConfigurer` (e.g. "permitAll()" is probably adequate since it is a public key). From 2bf4b7581622d4bab91b59e1e2e05d484179f6b2 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 15 May 2015 11:39:56 +0100 Subject: [PATCH 427/831] Add flag for requiresSecure() in the security endpoint configurer Fixes gh-480 --- docs/oauth2.md | 14 +++++++++++++- .../AuthorizationServerSecurityConfigurer.java | 10 ++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/docs/oauth2.md b/docs/oauth2.md index aea918866..a0f215564 100644 --- a/docs/oauth2.md +++ b/docs/oauth2.md @@ -125,9 +125,21 @@ The token endpoint is protected for you by default by Spring OAuth in the `@Conf In XML the `` element has some attributes that can be used to change the default endpoint URLs in a similar way. +### + ## Customizing the UI -Most of the Authorization Server endpoints are used primarily by machines, but there are a couple of resource that need a UI and those are the GET for `/oauth/confirm_access` and the HTML response from `/oauth/error`. They are provided using whitelabel implementations in the framework, so most real-world instances of the Authorization Server will want to provide their own so they can control the styling and content. All you need to do is provide a Spring MVC controller with `@RequestMappings` for those endpoints, and the framework defaults will take a lower priority in the dispatcher. In the `/oauth/confirm_access` endpoint you can expect an `AuthorizationRequest` bound to the session carrying all the data needed to seek approval from the user (the default implementation is `WhitelabelApprovalEndpoint` so look there for a starting point to copy). +Most of the Authorization Server endpoints are used primarily by machines, but there are a couple of resource that need a UI and those are the GET for `/oauth/confirm_access` and the HTML response from `/oauth/error`. They are provided using whitelabel implementations in the framework, so most real-world instances of the Authorization Server will want to provide their own so they can control the styling and content. All you need to do is provide a Spring MVC controller with `@RequestMappings` for those endpoints, and the framework defaults will take a lower priority in the dispatcher. In the `/oauth/confirm_access` endpoint you can expect an `AuthorizationRequest` bound to the session carrying all the data needed to seek approval from the user (the default implementation is `WhitelabelApprovalEndpoint` so look there for a starting point to copy). You can grab all the data from that request and render it however you like, and then all the user needs to do is POST back to `/oauth/authorize` with information about approving or denying the grant. The request parameters are passed directly to a `UserApprovalHandler` in the `AuthorizationEndpoint` so you can interpret the data more or less as you please. The default `UserApprovalHandler` depends on whether or not you have supplied an `ApprovalStore` in your `AuthorizationServerEndpointsConfigurer` (in which case it is an `ApprovalStoreUserApprovalHandler`) or not (in which case it is a `TokenStoreUserApprovalHandler`). The standard approval handlers accept the following: + +* `TokenStoreUserApprovalHandler`: a simple yes/no decision via `user_oauth_approval` equals to "true" or "false". + +* `ApprovalStoreUserApprovalHandler`: a set of `scope.*` parameter keys with "*" equal to the scopes being requested. The value of the parameter can be "true" or "approved" (if the user approved the grant) else the user is deemed to have rejected that scope. A grant is successful if at least one scope is approved. + +> NOTE: don't forget to include CSRF protection in your form that you render for the user. Spring Security is expecting a request parameter called "_csrf" by default (and it provides the value in a request attribute). See the Spring Security user guide for more information on that, or look at the whitelabel implementation for guidance. + +### Enforcing SSL + +Plain HTTP is fine for testing but an Authorization Server should only be used over SSL in production. You can run the app in a secure container or behind a proxy and it should work fine if you set the proxy and the container up correctly (which is nothing to do with OAuth2). You might also want to secure the endpoints using Spring Security `requiresChannel()` constraints. For the `/authorize` endpoint is up to you to do that as part of your normal application security. For the `/token` endpoint there is a flag in the `AuthorizationServerEndpointsConfigurer` that you can set using the `sslOnly()` method. In both cases the secure channel setting is optional but will cause Spring Security to redirect to what it thinks is a secure channel if it detects a request on an insecure channel. ## Customizing the Error Handling diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java index 9df61198f..7b47d915d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java @@ -63,6 +63,13 @@ public final class AuthorizationServerSecurityConfigurer extends private String checkTokenAccess = "denyAll()"; + private boolean sslOnly = false; + + public AuthorizationServerSecurityConfigurer sslOnly() { + this.sslOnly = true; + return this; + } + public AuthorizationServerSecurityConfigurer allowFormAuthenticationForClients() { this.allowFormAuthenticationForClients = true; return this; @@ -166,6 +173,9 @@ public void configure(HttpSecurity http) throws Exception { clientCredentialsTokenEndpointFilter(http); } http.exceptionHandling().accessDeniedHandler(accessDeniedHandler); + if (sslOnly ) { + http.requiresChannel().anyRequest().requiresSecure(); + } } From 36deb5e104f57e9c0740eeb717843c7f17f0af7c Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 15 May 2015 11:55:41 +0100 Subject: [PATCH 428/831] Expose stateless flag in resource-server XML config Fixes gh-455 --- .../config/xml/ResourceServerBeanDefinitionParser.java | 5 +++++ .../security/oauth2/spring-security-oauth2-2.0.xsd | 8 ++++++++ .../oauth2/config/xml/resource-server-context.xml | 2 +- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ResourceServerBeanDefinitionParser.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ResourceServerBeanDefinitionParser.java index abc47bde6..8301b596a 100755 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ResourceServerBeanDefinitionParser.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ResourceServerBeanDefinitionParser.java @@ -39,6 +39,7 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P String authenticationManagerRef = element.getAttribute("authentication-manager-ref"); String tokenExtractorRef = element.getAttribute("token-extractor-ref"); String entryAuthDetailsSource = element.getAttribute("auth-details-source-ref"); + String stateless = element.getAttribute("stateless"); // configure the protected resource filter BeanDefinitionBuilder protectedResourceFilterBean = BeanDefinitionBuilder @@ -75,6 +76,10 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P protectedResourceFilterBean.addPropertyReference("tokenExtractor", tokenExtractorRef); } + if (StringUtils.hasText(stateless)) { + protectedResourceFilterBean.addPropertyValue("stateless", stateless); + } + return protectedResourceFilterBean.getBeanDefinition(); } diff --git a/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-2.0.xsd b/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-2.0.xsd index 03505a920..15c040592 100644 --- a/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-2.0.xsd +++ b/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-2.0.xsd @@ -421,6 +421,14 @@ + + + + + Flag to say that the resource is stateless, i.e. it handles authentication on its own and it doesn't accept incoming pre-authentication. Default true. + + + diff --git a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/resource-server-context.xml b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/resource-server-context.xml index 965addbd1..52366eaa5 100644 --- a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/resource-server-context.xml +++ b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/resource-server-context.xml @@ -16,7 +16,7 @@ - + From 3bceb922023f8c6e82dd93cb9c4ba1d7d679bcf4 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 15 May 2015 12:07:21 +0100 Subject: [PATCH 429/831] Add build status --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 22c0246e9..4de3dd39b 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +![Build Status]https://travis-ci.org/spring-projects/spring-security-oauth.svg?branch=master + This project provides support for using Spring Security with OAuth (1a) and OAuth2. It provides features for implementing both consumers and providers of these protocols using standard Spring and Spring From 816be6735573b6834777e9efb909f7cef7692ff6 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 15 May 2015 13:06:44 +0100 Subject: [PATCH 430/831] Tone down logs for CI --- .../custom-grant/src/main/resources/application.yml | 2 +- tests/annotation/jdbc/src/main/resources/application.yml | 2 +- tests/annotation/jwt/src/main/resources/application.yml | 2 +- tests/annotation/mappings/src/main/resources/application.yml | 2 +- tests/annotation/vanilla/src/main/resources/application.yml | 2 +- tests/xml/jdbc/src/main/resources/application.yml | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/annotation/custom-grant/src/main/resources/application.yml b/tests/annotation/custom-grant/src/main/resources/application.yml index a7c74036e..ccf06f8ba 100644 --- a/tests/annotation/custom-grant/src/main/resources/application.yml +++ b/tests/annotation/custom-grant/src/main/resources/application.yml @@ -8,4 +8,4 @@ security: password: password logging: level: - org.springframework.security: DEBUG \ No newline at end of file + # org.springframework.security: DEBUG \ No newline at end of file diff --git a/tests/annotation/jdbc/src/main/resources/application.yml b/tests/annotation/jdbc/src/main/resources/application.yml index 2817b5703..da08708a2 100644 --- a/tests/annotation/jdbc/src/main/resources/application.yml +++ b/tests/annotation/jdbc/src/main/resources/application.yml @@ -5,7 +5,7 @@ management: context_path: /admin logging: level: - org.springframework.security: DEBUG + # org.springframework.security: DEBUG --- diff --git a/tests/annotation/jwt/src/main/resources/application.yml b/tests/annotation/jwt/src/main/resources/application.yml index a7c74036e..ccf06f8ba 100644 --- a/tests/annotation/jwt/src/main/resources/application.yml +++ b/tests/annotation/jwt/src/main/resources/application.yml @@ -8,4 +8,4 @@ security: password: password logging: level: - org.springframework.security: DEBUG \ No newline at end of file + # org.springframework.security: DEBUG \ No newline at end of file diff --git a/tests/annotation/mappings/src/main/resources/application.yml b/tests/annotation/mappings/src/main/resources/application.yml index cc1cf090c..3b09181d7 100644 --- a/tests/annotation/mappings/src/main/resources/application.yml +++ b/tests/annotation/mappings/src/main/resources/application.yml @@ -8,7 +8,7 @@ security: password: password logging: level: - org.springframework.security: DEBUG + # org.springframework.security: DEBUG oauth: paths: token: /token diff --git a/tests/annotation/vanilla/src/main/resources/application.yml b/tests/annotation/vanilla/src/main/resources/application.yml index a7c74036e..ccf06f8ba 100644 --- a/tests/annotation/vanilla/src/main/resources/application.yml +++ b/tests/annotation/vanilla/src/main/resources/application.yml @@ -8,4 +8,4 @@ security: password: password logging: level: - org.springframework.security: DEBUG \ No newline at end of file + # org.springframework.security: DEBUG \ No newline at end of file diff --git a/tests/xml/jdbc/src/main/resources/application.yml b/tests/xml/jdbc/src/main/resources/application.yml index b9ce01048..2712a551f 100644 --- a/tests/xml/jdbc/src/main/resources/application.yml +++ b/tests/xml/jdbc/src/main/resources/application.yml @@ -8,9 +8,9 @@ security: password: password logging: level: - org.springframework.security: DEBUG +# org.springframework.security: DEBUG # org.springframework.web: DEBUG - org.springframework.jdbc: DEBUG +# org.springframework.jdbc: DEBUG --- From b5194b432746aafa5fb25431043142e5bce8130d Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 19 May 2015 16:32:44 +0100 Subject: [PATCH 431/831] Fix client app jar file so it is executable Fixes gh-485 --- tests/annotation/client/pom.xml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/annotation/client/pom.xml b/tests/annotation/client/pom.xml index bd5aa9f39..a57241b0f 100644 --- a/tests/annotation/client/pom.xml +++ b/tests/annotation/client/pom.xml @@ -1,5 +1,6 @@ - + 4.0.0 spring-oauth2-tests-client @@ -13,6 +14,10 @@ 2.0.8.BUILD-SNAPSHOT + + client.ClientApplication + + org.springframework.boot From e66d068285f823837c0adfe6183b9d7f977d21c4 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 8 Jun 2015 13:36:11 +0100 Subject: [PATCH 432/831] Upgrade to Spring Security 3.2.7 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index cdeec2927..673cfb30a 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,7 @@ UTF-8 4.0.9.RELEASE - 3.2.6.RELEASE + 3.2.7.RELEASE 1.6 From 5df63d4036a8d7528f491160ab263ea59168152e Mon Sep 17 00:00:00 2001 From: Christopher Giroir Date: Thu, 30 Apr 2015 10:44:53 -0700 Subject: [PATCH 433/831] Adding support for properly handling the HttpMethodNotSupported error --- .../provider/endpoint/TokenEndpoint.java | 4 +-- ...DefaultWebResponseExceptionTranslator.java | 27 ++++++++++++++++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java index 4a802ee00..ff75badb5 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java @@ -156,9 +156,9 @@ protected String getClientId(Principal principal) { } @ExceptionHandler(HttpRequestMethodNotSupportedException.class) - public void handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) throws Exception { + public ResponseEntity handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) throws Exception { logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage()); - throw e; + return getExceptionTranslator().translate(e); } @ExceptionHandler(Exception.class) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/DefaultWebResponseExceptionTranslator.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/DefaultWebResponseExceptionTranslator.java index a242e564a..c8bcd952b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/DefaultWebResponseExceptionTranslator.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/DefaultWebResponseExceptionTranslator.java @@ -27,6 +27,7 @@ import org.springframework.security.oauth2.common.exceptions.InsufficientScopeException; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.web.util.ThrowableAnalyzer; +import org.springframework.web.HttpRequestMethodNotSupportedException; /** * @author Dave Syer @@ -40,7 +41,7 @@ public ResponseEntity translate(Exception e) throws Exception { // Try to extract a SpringSecurityException from the stacktrace Throwable[] causeChain = throwableAnalyzer.determineCauseChain(e); - RuntimeException ase = (OAuth2Exception) throwableAnalyzer.getFirstThrowableOfType( + Exception ase = (OAuth2Exception) throwableAnalyzer.getFirstThrowableOfType( OAuth2Exception.class, causeChain); if (ase != null) { @@ -59,6 +60,12 @@ public ResponseEntity translate(Exception e) throws Exception { return handleOAuth2Exception(new ForbiddenException(ase.getMessage(), ase)); } + ase = (HttpRequestMethodNotSupportedException) throwableAnalyzer + .getFirstThrowableOfType(HttpRequestMethodNotSupportedException.class, causeChain); + if (ase instanceof HttpRequestMethodNotSupportedException) { + return handleOAuth2Exception(new BadRequest(ase.getMessage(), ase)); + } + return handleOAuth2Exception(new ServerErrorException(e.getMessage(), e)); } @@ -117,6 +124,7 @@ public int getHttpErrorCode() { } } + @SuppressWarnings("serial") private static class UnauthorizedException extends OAuth2Exception { @@ -133,4 +141,21 @@ public int getHttpErrorCode() { } } + + @SuppressWarnings("serial") + private static class BadRequest extends OAuth2Exception { + + public BadRequest(String msg, Throwable t) { + super(msg, t); + } + + public String getOAuth2ErrorCode() { + return "bad_request"; + } + + public int getHttpErrorCode() { + return 400; + } + + } } From 4a0574fde141d2e3eda0e95258db19b709ec6783 Mon Sep 17 00:00:00 2001 From: Christopher Giroir Date: Thu, 14 May 2015 11:06:17 -0700 Subject: [PATCH 434/831] Changing method error to 405 Method Not Allowed --- .../error/DefaultWebResponseExceptionTranslator.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/DefaultWebResponseExceptionTranslator.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/DefaultWebResponseExceptionTranslator.java index c8bcd952b..39bb4cf00 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/DefaultWebResponseExceptionTranslator.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/DefaultWebResponseExceptionTranslator.java @@ -63,7 +63,7 @@ public ResponseEntity translate(Exception e) throws Exception { ase = (HttpRequestMethodNotSupportedException) throwableAnalyzer .getFirstThrowableOfType(HttpRequestMethodNotSupportedException.class, causeChain); if (ase instanceof HttpRequestMethodNotSupportedException) { - return handleOAuth2Exception(new BadRequest(ase.getMessage(), ase)); + return handleOAuth2Exception(new MethodNotAllowed(ase.getMessage(), ase)); } return handleOAuth2Exception(new ServerErrorException(e.getMessage(), e)); @@ -143,18 +143,18 @@ public int getHttpErrorCode() { } @SuppressWarnings("serial") - private static class BadRequest extends OAuth2Exception { + private static class MethodNotAllowed extends OAuth2Exception { - public BadRequest(String msg, Throwable t) { + public MethodNotAllowed(String msg, Throwable t) { super(msg, t); } public String getOAuth2ErrorCode() { - return "bad_request"; + return "method_not_allowed"; } public int getHttpErrorCode() { - return 400; + return 405; } } From 19c33f227e0f760a046875efe47f4e8d86e7c4d6 Mon Sep 17 00:00:00 2001 From: Eric Fenderbosch Date: Mon, 2 Feb 2015 15:54:50 -0500 Subject: [PATCH 435/831] Add redis token store and tests Fixes gh-494, fixes gh-367, fixes gh-488 --- spring-security-oauth2/pom.xml | 21 +- ...eRedisTokenStoreSerializationStrategy.java | 56 +++ .../store/redis/JdkSerializationStrategy.java | 26 ++ .../token/store/redis/RedisTokenStore.java | 378 ++++++++++++++++++ .../RedisTokenStoreSerializationStrategy.java | 16 + .../StandardStringSerializationStrategy.java | 25 ++ .../token/store/TokenStoreBaseTests.java | 96 ++--- .../store/redis/RedisTokenStoreTests.java | 93 +++++ 8 files changed, 652 insertions(+), 59 deletions(-) create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/redis/BaseRedisTokenStoreSerializationStrategy.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/redis/JdkSerializationStrategy.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/redis/RedisTokenStore.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/redis/RedisTokenStoreSerializationStrategy.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/redis/StandardStringSerializationStrategy.java create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/redis/RedisTokenStoreTests.java diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index d9d69d107..b2bf88a0d 100644 --- a/spring-security-oauth2/pom.xml +++ b/spring-security-oauth2/pom.xml @@ -144,6 +144,18 @@ ${jackson1.version} + + org.springframework.data + spring-data-redis + 1.5.0.RELEASE + + + + redis.clients + jedis + 2.6.3 + + com.fasterxml.jackson.core jackson-annotations @@ -207,7 +219,14 @@ 2.0.0 test - + + + com.orange.redis-embedded + embedded-redis + 0.6 + test + + diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/redis/BaseRedisTokenStoreSerializationStrategy.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/redis/BaseRedisTokenStoreSerializationStrategy.java new file mode 100644 index 000000000..4a37506f7 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/redis/BaseRedisTokenStoreSerializationStrategy.java @@ -0,0 +1,56 @@ +package org.springframework.security.oauth2.provider.token.store.redis; + +/** + * Handles null/empty byte arrays on deserialize and null objects on serialize. + * + * @author efenderbosch + */ +public abstract class BaseRedisTokenStoreSerializationStrategy implements RedisTokenStoreSerializationStrategy { + + private static final byte[] EMPTY_ARRAY = new byte[0]; + + private static boolean isEmpty(byte[] bytes) { + return bytes == null || bytes.length == 0; + } + + @Override + public T deserialize(byte[] bytes, Class clazz) { + if (isEmpty(bytes)) { + return null; + } + return deserializeInternal(bytes, clazz); + } + + protected abstract T deserializeInternal(byte[] bytes, Class clazz); + + @Override + public String deserializeString(byte[] bytes) { + if (isEmpty(bytes)) { + return null; + } + return deserializeStringInternal(bytes); + } + + protected abstract String deserializeStringInternal(byte[] bytes); + + @Override + public byte[] serialize(Object object) { + if (object == null) { + return EMPTY_ARRAY; + } + return serializeInternal(object); + } + + protected abstract byte[] serializeInternal(Object object); + + @Override + public byte[] serialize(String data) { + if (data == null) { + return EMPTY_ARRAY; + } + return serializeInternal(data); + } + + protected abstract byte[] serializeInternal(String data); + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/redis/JdkSerializationStrategy.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/redis/JdkSerializationStrategy.java new file mode 100644 index 000000000..aae1d7b5e --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/redis/JdkSerializationStrategy.java @@ -0,0 +1,26 @@ +package org.springframework.security.oauth2.provider.token.store.redis; + +import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; + +/** + * Serializes objects using {@link JdkSerializationRedisSerializer} + * + * @author efenderbosch + * + */ +public class JdkSerializationStrategy extends StandardStringSerializationStrategy { + + private static final JdkSerializationRedisSerializer OBJECT_SERIALIZER = new JdkSerializationRedisSerializer(); + + @Override + @SuppressWarnings("unchecked") + protected T deserializeInternal(byte[] bytes, Class clazz) { + return (T) OBJECT_SERIALIZER.deserialize(bytes); + } + + @Override + protected byte[] serializeInternal(Object object) { + return OBJECT_SERIALIZER.serialize(object); + } + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/redis/RedisTokenStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/redis/RedisTokenStore.java new file mode 100644 index 000000000..7f487b3cf --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/redis/RedisTokenStore.java @@ -0,0 +1,378 @@ +package org.springframework.security.oauth2.provider.token.store.redis; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.List; + +import org.springframework.data.redis.connection.RedisConnection; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken; +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.AuthenticationKeyGenerator; +import org.springframework.security.oauth2.provider.token.DefaultAuthenticationKeyGenerator; +import org.springframework.security.oauth2.provider.token.TokenStore; + +/** + * @author efenderbosch + */ +public class RedisTokenStore implements TokenStore { + + private static final String ACCESS = "access:"; + private static final String AUTH_TO_ACCESS = "auth_to_access:"; + private static final String AUTH = "auth:"; + private static final String REFRESH_AUTH = "refresh_auth:"; + private static final String ACCESS_TO_REFRESH = "access_to_refresh:"; + private static final String REFRESH = "refresh:"; + private static final String REFRESH_TO_ACCESS = "refresh_to_access:"; + private static final String CLIENT_ID_TO_ACCESS = "client_id_to_access:"; + private static final String UNAME_TO_ACCESS = "uname_to_access:"; + + private final RedisConnectionFactory connectionFactory; + private AuthenticationKeyGenerator authenticationKeyGenerator = new DefaultAuthenticationKeyGenerator(); + private RedisTokenStoreSerializationStrategy serializationStrategy = new JdkSerializationStrategy(); + + public RedisTokenStore(RedisConnectionFactory connectionFactory) { + this.connectionFactory = connectionFactory; + } + + public void setAuthenticationKeyGenerator(AuthenticationKeyGenerator authenticationKeyGenerator) { + this.authenticationKeyGenerator = authenticationKeyGenerator; + } + + public void setSerializationStrategy(RedisTokenStoreSerializationStrategy serializationStrategy) { + this.serializationStrategy = serializationStrategy; + } + + private RedisConnection getConnection() { + return connectionFactory.getConnection(); + } + + private byte[] serialize(Object object) { + return serializationStrategy.serialize(object); + } + + private OAuth2AccessToken deserializeAccessToken(byte[] bytes) { + return serializationStrategy.deserialize(bytes, OAuth2AccessToken.class); + } + + private OAuth2Authentication deserializeAuthentication(byte[] bytes) { + return serializationStrategy.deserialize(bytes, OAuth2Authentication.class); + } + + private OAuth2RefreshToken deserializeRefreshToken(byte[] bytes) { + return serializationStrategy.deserialize(bytes, OAuth2RefreshToken.class); + } + + private byte[] serialize(String string) { + return serializationStrategy.serialize(string); + } + + private String deserializeString(byte[] bytes) { + return serializationStrategy.deserializeString(bytes); + } + + @Override + public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) { + String key = authenticationKeyGenerator.extractKey(authentication); + byte[] serializedKey = serialize(AUTH_TO_ACCESS + key); + byte[] bytes = null; + RedisConnection conn = getConnection(); + try { + bytes = conn.get(serializedKey); + } finally { + conn.close(); + } + OAuth2AccessToken accessToken = deserializeAccessToken(bytes); + if (accessToken != null + && !key.equals(authenticationKeyGenerator.extractKey(readAuthentication(accessToken.getValue())))) { + // Keep the stores consistent (maybe the same user is + // represented by this authentication but the details have + // changed) + storeAccessToken(accessToken, authentication); + } + return accessToken; + } + + @Override + public OAuth2Authentication readAuthentication(OAuth2AccessToken token) { + return readAuthentication(token.getValue()); + } + + @Override + public OAuth2Authentication readAuthentication(String token) { + byte[] bytes = null; + RedisConnection conn = getConnection(); + try { + bytes = conn.get(serialize(AUTH + token)); + } finally { + conn.close(); + } + OAuth2Authentication auth = deserializeAuthentication(bytes); + return auth; + } + + @Override + public OAuth2Authentication readAuthenticationForRefreshToken(OAuth2RefreshToken token) { + return readAuthenticationForRefreshToken(token.getValue()); + } + + public OAuth2Authentication readAuthenticationForRefreshToken(String token) { + RedisConnection conn = getConnection(); + try { + byte[] bytes = conn.get(serialize(REFRESH_AUTH + token)); + OAuth2Authentication auth = deserializeAuthentication(bytes); + return auth; + } finally { + conn.close(); + } + } + + @Override + public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) { + byte[] serializedAccessToken = serialize(token); + byte[] serializedAuth = serialize(authentication); + byte[] accessKey = serialize(ACCESS + token.getValue()); + byte[] authKey = serialize(AUTH + token.getValue()); + byte[] authToAccessKey = serialize(AUTH_TO_ACCESS + authenticationKeyGenerator.extractKey(authentication)); + byte[] approvalKey = serialize(UNAME_TO_ACCESS + getApprovalKey(authentication)); + byte[] clientId = serialize(CLIENT_ID_TO_ACCESS + authentication.getOAuth2Request().getClientId()); + + RedisConnection conn = getConnection(); + try { + conn.openPipeline(); + conn.set(accessKey, serializedAccessToken); + conn.set(authKey, serializedAuth); + conn.set(authToAccessKey, serializedAccessToken); + if (!authentication.isClientOnly()) { + conn.rPush(approvalKey, serializedAccessToken); + } + conn.rPush(clientId, serializedAccessToken); + if (token.getExpiration() != null) { + int seconds = token.getExpiresIn(); + conn.expire(accessKey, seconds); + conn.expire(authKey, seconds); + conn.expire(authToAccessKey, seconds); + conn.expire(clientId, seconds); + conn.expire(approvalKey, seconds); + } + OAuth2RefreshToken refreshToken = token.getRefreshToken(); + if (refreshToken != null && refreshToken.getValue() != null) { + byte[] refresh = serialize(token.getRefreshToken().getValue()); + byte[] auth = serialize(token.getValue()); + byte[] refreshToAccessKey = serialize(REFRESH_TO_ACCESS + token.getRefreshToken().getValue()); + conn.set(refreshToAccessKey, auth); + byte[] accessToRefreshKey = serialize(ACCESS_TO_REFRESH + token.getValue()); + conn.set(accessToRefreshKey, refresh); + if (refreshToken instanceof ExpiringOAuth2RefreshToken) { + ExpiringOAuth2RefreshToken expiringRefreshToken = (ExpiringOAuth2RefreshToken) refreshToken; + Date expiration = expiringRefreshToken.getExpiration(); + if (expiration != null) { + int seconds = (int) (expiration.getTime() / 1000); + conn.expireAt(refreshToAccessKey, seconds); + conn.expireAt(accessToRefreshKey, seconds); + } + } + } + conn.closePipeline(); + } finally { + conn.close(); + } + } + + private static String getApprovalKey(OAuth2Authentication authentication) { + String userName = authentication.getUserAuthentication() == null ? "" : authentication.getUserAuthentication() + .getName(); + return getApprovalKey(authentication.getOAuth2Request().getClientId(), userName); + } + + private static String getApprovalKey(String clientId, String userName) { + return clientId + (userName == null ? "" : ":" + userName); + } + + @Override + public void removeAccessToken(OAuth2AccessToken accessToken) { + removeAccessToken(accessToken.getValue()); + } + + @Override + public OAuth2AccessToken readAccessToken(String tokenValue) { + byte[] key = serialize(ACCESS + tokenValue); + byte[] bytes = null; + RedisConnection conn = getConnection(); + try { + bytes = conn.get(key); + } finally { + conn.close(); + } + OAuth2AccessToken accessToken = deserializeAccessToken(bytes); + return accessToken; + } + + public void removeAccessToken(String tokenValue) { + byte[] accessKey = serialize(ACCESS + tokenValue); + byte[] authKey = serialize(AUTH + tokenValue); + byte[] accessToRefreshKey = serialize(ACCESS_TO_REFRESH + tokenValue); + RedisConnection conn = getConnection(); + try { + conn.openPipeline(); + conn.get(accessKey); + conn.get(authKey); + conn.del(accessKey); + conn.del(accessToRefreshKey); + // Don't remove the refresh token - it's up to the caller to do that + conn.del(authKey); + List results = conn.closePipeline(); + byte[] access = (byte[]) results.get(0); + byte[] auth = (byte[]) results.get(1); + + OAuth2Authentication authentication = deserializeAuthentication(auth); + if (authentication != null) { + String key = authenticationKeyGenerator.extractKey(authentication); + byte[] authToAccessKey = serialize(AUTH_TO_ACCESS + key); + byte[] unameKey = serialize(UNAME_TO_ACCESS + getApprovalKey(authentication)); + byte[] clientId = serialize(CLIENT_ID_TO_ACCESS + authentication.getOAuth2Request().getClientId()); + conn.openPipeline(); + conn.del(authToAccessKey); + conn.lRem(unameKey, 1, access); + conn.lRem(clientId, 1, access); + conn.del(serialize(ACCESS + key)); + conn.closePipeline(); + } + } finally { + conn.close(); + } + } + + @Override + public void storeRefreshToken(OAuth2RefreshToken refreshToken, OAuth2Authentication authentication) { + byte[] refreshKey = serialize(REFRESH + refreshToken.getValue()); + byte[] refreshAuthKey = serialize(REFRESH_AUTH + refreshToken.getValue()); + byte[] serializedRefreshToken = serialize(refreshToken); + RedisConnection conn = getConnection(); + try { + conn.openPipeline(); + conn.set(refreshKey, serializedRefreshToken); + conn.set(refreshAuthKey, serialize(authentication)); + if (refreshToken instanceof ExpiringOAuth2RefreshToken) { + ExpiringOAuth2RefreshToken expiringRefreshToken = (ExpiringOAuth2RefreshToken) refreshToken; + Date expiration = expiringRefreshToken.getExpiration(); + if (expiration != null) { + int seconds = (int) (expiration.getTime() / 1000); + conn.expireAt(refreshKey, seconds); + conn.expireAt(refreshAuthKey, seconds); + } + } + conn.closePipeline(); + } finally { + conn.close(); + } + } + + @Override + public OAuth2RefreshToken readRefreshToken(String tokenValue) { + byte[] key = serialize(REFRESH + tokenValue); + byte[] bytes = null; + RedisConnection conn = getConnection(); + try { + bytes = conn.get(key); + } finally { + conn.close(); + } + OAuth2RefreshToken refreshToken = deserializeRefreshToken(bytes); + return refreshToken; + } + + @Override + public void removeRefreshToken(OAuth2RefreshToken refreshToken) { + removeRefreshToken(refreshToken.getValue()); + } + + public void removeRefreshToken(String tokenValue) { + byte[] refreshKey = serialize(REFRESH + tokenValue); + byte[] refresh2AccessKey = serialize(REFRESH_TO_ACCESS + tokenValue); + byte[] access2RefreshKey = serialize(ACCESS_TO_REFRESH + tokenValue); + RedisConnection conn = getConnection(); + try { + conn.openPipeline(); + conn.del(refreshKey); + conn.del(refresh2AccessKey); + conn.del(access2RefreshKey); + conn.closePipeline(); + } finally { + conn.close(); + } + } + + @Override + public void removeAccessTokenUsingRefreshToken(OAuth2RefreshToken refreshToken) { + removeAccessTokenUsingRefreshToken(refreshToken.getValue()); + } + + private void removeAccessTokenUsingRefreshToken(String refreshToken) { + byte[] key = serialize(REFRESH_TO_ACCESS + refreshToken); + List results = null; + RedisConnection conn = getConnection(); + try { + conn.openPipeline(); + conn.get(key); + conn.del(key); + results = conn.closePipeline(); + } finally { + conn.close(); + } + if (results == null) { + return; + } + byte[] bytes = (byte[]) results.get(0); + String accessToken = deserializeString(bytes); + if (accessToken != null) { + removeAccessToken(accessToken); + } + } + + @Override + public Collection findTokensByClientIdAndUserName(String clientId, String userName) { + byte[] approvalKey = serialize(UNAME_TO_ACCESS + getApprovalKey(clientId, userName)); + List byteList = null; + RedisConnection conn = getConnection(); + try { + byteList = conn.lRange(approvalKey, 0, -1); + } finally { + conn.close(); + } + if (byteList == null || byteList.size() == 0) { + return Collections. emptySet(); + } + List accessTokens = new ArrayList(byteList.size()); + for (byte[] bytes : byteList) { + OAuth2AccessToken accessToken = deserializeAccessToken(bytes); + accessTokens.add(accessToken); + } + return Collections. unmodifiableCollection(accessTokens); + } + + @Override + public Collection findTokensByClientId(String clientId) { + byte[] key = serialize(CLIENT_ID_TO_ACCESS + clientId); + List byteList = null; + RedisConnection conn = getConnection(); + try { + byteList = conn.lRange(key, 0, -1); + } finally { + conn.close(); + } + if (byteList == null || byteList.size() == 0) { + return Collections. emptySet(); + } + List accessTokens = new ArrayList(byteList.size()); + for (byte[] bytes : byteList) { + OAuth2AccessToken accessToken = deserializeAccessToken(bytes); + accessTokens.add(accessToken); + } + return Collections. unmodifiableCollection(accessTokens); + } +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/redis/RedisTokenStoreSerializationStrategy.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/redis/RedisTokenStoreSerializationStrategy.java new file mode 100644 index 000000000..3d48f56f6 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/redis/RedisTokenStoreSerializationStrategy.java @@ -0,0 +1,16 @@ +package org.springframework.security.oauth2.provider.token.store.redis; + +/** + * @author efenderbosch + */ +public interface RedisTokenStoreSerializationStrategy { + + T deserialize(byte[] bytes, Class clazz); + + String deserializeString(byte[] bytes); + + byte[] serialize(Object object); + + byte[] serialize(String data); + +} diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/redis/StandardStringSerializationStrategy.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/redis/StandardStringSerializationStrategy.java new file mode 100644 index 000000000..72b8faf18 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/redis/StandardStringSerializationStrategy.java @@ -0,0 +1,25 @@ +package org.springframework.security.oauth2.provider.token.store.redis; + +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * Serializes Strings using {@link StringRedisSerializer} + * + * @author efenderbosch + * + */ +public abstract class StandardStringSerializationStrategy extends BaseRedisTokenStoreSerializationStrategy { + + private static final StringRedisSerializer STRING_SERIALIZER = new StringRedisSerializer(); + + @Override + protected String deserializeStringInternal(byte[] bytes) { + return STRING_SERIALIZER.deserialize(bytes); + } + + @Override + protected byte[] serializeInternal(String string) { + return STRING_SERIALIZER.serialize(string); + } + +} diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/TokenStoreBaseTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/TokenStoreBaseTests.java index c088033e0..9f8cf26a3 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/TokenStoreBaseTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/TokenStoreBaseTests.java @@ -12,11 +12,7 @@ */ package org.springframework.security.oauth2.provider.token.store; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; import java.util.Collection; import java.util.Date; @@ -33,7 +29,7 @@ import org.springframework.security.oauth2.provider.RequestTokenFactory; import org.springframework.security.oauth2.provider.token.TokenStore; -/** +/** * @author Dave Syer * */ @@ -48,8 +44,7 @@ public void testReadingAuthenticationForTokenThatDoesNotExist() { @Test public void testStoreAccessToken() { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request( - "id", false), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request("id", false), new TestAuthentication("test2", false)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); @@ -63,8 +58,7 @@ public void testStoreAccessToken() { @Test public void testStoreAccessTokenTwice() { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request( - "id", false), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request( "id", false), new TestAuthentication("test2", false)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); @@ -79,25 +73,21 @@ public void testStoreAccessTokenTwice() { @Test public void testRetrieveAccessToken() { - // Test approved request + //Test approved request OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request("id", true); - OAuth2Authentication authentication = new OAuth2Authentication(storedOAuth2Request, new TestAuthentication( - "test2", true)); + OAuth2Authentication authentication = new OAuth2Authentication(storedOAuth2Request, new TestAuthentication("test2", true)); DefaultOAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); - expectedOAuth2AccessToken.setExpiration(new Date(Long.MAX_VALUE - 1)); + expectedOAuth2AccessToken.setExpiration(new Date(Long.MAX_VALUE-1)); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, authentication); - // Test unapproved request + //Test unapproved request storedOAuth2Request = RequestTokenFactory.createOAuth2Request("id", false); authentication = new OAuth2Authentication(storedOAuth2Request, new TestAuthentication("test2", true)); OAuth2AccessToken actualOAuth2AccessToken = getTokenStore().getAccessToken(authentication); assertEquals(expectedOAuth2AccessToken, actualOAuth2AccessToken); - assertEquals(authentication.getUserAuthentication(), - getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue()).getUserAuthentication()); - // The authorizationRequest does not match because it is unapproved, but the token was granted to an approved - // request - assertFalse(storedOAuth2Request.equals(getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue()) - .getOAuth2Request())); + assertEquals(authentication.getUserAuthentication(), getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue()).getUserAuthentication()); + // The authorizationRequest does not match because it is unapproved, but the token was granted to an approved request + assertFalse(storedOAuth2Request.equals(getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue()).getOAuth2Request())); actualOAuth2AccessToken = getTokenStore().getAccessToken(authentication); assertEquals(expectedOAuth2AccessToken, actualOAuth2AccessToken); getTokenStore().removeAccessToken(expectedOAuth2AccessToken); @@ -108,20 +98,17 @@ public void testRetrieveAccessToken() { @Test public void testFindAccessTokensByClientIdAndUserName() { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request( - "id", false), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request("id", false), new TestAuthentication("test2", false)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); - Collection actualOAuth2AccessTokens = getTokenStore().findTokensByClientIdAndUserName("id", - "test2"); + Collection actualOAuth2AccessTokens = getTokenStore().findTokensByClientIdAndUserName("id", "test2"); assertEquals(1, actualOAuth2AccessTokens.size()); } @Test public void testFindAccessTokensByClientId() { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request( - "id", false), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request("id", false), new TestAuthentication("test2", false)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); @@ -136,33 +123,32 @@ public void testReadingAccessTokenForTokenThatDoesNotExist() { @Test public void testRefreshTokenIsNotStoredDuringAccessToken() { - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request( - "id", false), new TestAuthentication("test2", false)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request("id", false), new TestAuthentication("test2", false)); DefaultOAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); expectedOAuth2AccessToken.setRefreshToken(new DefaultOAuth2RefreshToken("refreshToken")); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); OAuth2AccessToken actualOAuth2AccessToken = getTokenStore().readAccessToken("testToken"); assertNotNull(actualOAuth2AccessToken.getRefreshToken()); - + assertNull(getTokenStore().readRefreshToken("refreshToken")); } @Test + /** + * NB: This used to test expiring refresh tokens. That test has been moved to sub-classes since not all stores support the functionality + */ public void testStoreRefreshToken() { - DefaultOAuth2RefreshToken expectedExpiringRefreshToken = new DefaultExpiringOAuth2RefreshToken("testToken", - new Date()); - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request( - "id", false), new TestAuthentication("test2", false)); - getTokenStore().storeRefreshToken(expectedExpiringRefreshToken, expectedAuthentication); + DefaultOAuth2RefreshToken expectedRefreshToken = new DefaultOAuth2RefreshToken("testToken"); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request("id", false), new TestAuthentication("test2", false)); + getTokenStore().storeRefreshToken(expectedRefreshToken, expectedAuthentication); OAuth2RefreshToken actualExpiringRefreshToken = getTokenStore().readRefreshToken("testToken"); - assertEquals(expectedExpiringRefreshToken, actualExpiringRefreshToken); - assertEquals(expectedAuthentication, - getTokenStore().readAuthenticationForRefreshToken(expectedExpiringRefreshToken)); - getTokenStore().removeRefreshToken(expectedExpiringRefreshToken); + assertEquals(expectedRefreshToken, actualExpiringRefreshToken); + assertEquals(expectedAuthentication, getTokenStore().readAuthenticationForRefreshToken(expectedRefreshToken)); + getTokenStore().removeRefreshToken(expectedRefreshToken); assertNull(getTokenStore().readRefreshToken("testToken")); - assertNull(getTokenStore().readAuthentication(expectedExpiringRefreshToken.getValue())); + assertNull(getTokenStore().readAuthentication(expectedRefreshToken.getValue())); } @Test @@ -172,39 +158,34 @@ public void testReadingRefreshTokenForTokenThatDoesNotExist() { @Test public void testGetAccessTokenForDeletedUser() throws Exception { - // Test approved request + //Test approved request OAuth2Request storedOAuth2Request = RequestTokenFactory.createOAuth2Request("id", true); - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(storedOAuth2Request, - new TestAuthentication("test", true)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(storedOAuth2Request, new TestAuthentication("test", true)); OAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken("testToken"); getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); assertEquals(expectedOAuth2AccessToken, getTokenStore().getAccessToken(expectedAuthentication)); assertEquals(expectedAuthentication, getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue())); - - // Test unapproved request + + //Test unapproved request storedOAuth2Request = RequestTokenFactory.createOAuth2Request("id", false); - OAuth2Authentication anotherAuthentication = new OAuth2Authentication(storedOAuth2Request, - new TestAuthentication("test", true)); + OAuth2Authentication anotherAuthentication = new OAuth2Authentication(storedOAuth2Request, new TestAuthentication("test", true)); assertEquals(expectedOAuth2AccessToken, getTokenStore().getAccessToken(anotherAuthentication)); // The generated key for the authentication is the same as before, but the two auths are not equal. This could // happen if there are 2 users in a system with the same username, or (more likely), if a user account was // deleted and re-created. - assertEquals(anotherAuthentication.getUserAuthentication(), - getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue()).getUserAuthentication()); - // The authorizationRequest does not match because it is unapproved, but the token was granted to an approved - // request - assertFalse(storedOAuth2Request.equals(getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue()) - .getOAuth2Request())); + assertEquals(anotherAuthentication.getUserAuthentication(), getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue()).getUserAuthentication()); + // The authorizationRequest does not match because it is unapproved, but the token was granted to an approved request + assertFalse(storedOAuth2Request.equals(getTokenStore().readAuthentication(expectedOAuth2AccessToken.getValue()).getOAuth2Request())); } @Test public void testRemoveRefreshToken() { - OAuth2RefreshToken expectedExpiringRefreshToken = new DefaultExpiringOAuth2RefreshToken("testToken", new Date()); - OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request( - "id", false), new TestAuthentication("test2", false)); + OAuth2RefreshToken expectedExpiringRefreshToken = new DefaultExpiringOAuth2RefreshToken("testToken", + new Date()); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request("id", false), new TestAuthentication("test2", false)); getTokenStore().storeRefreshToken(expectedExpiringRefreshToken, expectedAuthentication); getTokenStore().removeRefreshToken(expectedExpiringRefreshToken); - + assertNull(getTokenStore().readRefreshToken("testToken")); } @@ -223,7 +204,6 @@ public void testRemovedTokenCannotBeFoundByUsername() { protected static class TestAuthentication extends AbstractAuthenticationToken { private static final long serialVersionUID = 1L; - private String principal; public TestAuthentication(String name, boolean authenticated) { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/redis/RedisTokenStoreTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/redis/RedisTokenStoreTests.java new file mode 100644 index 000000000..9d4fca267 --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/redis/RedisTokenStoreTests.java @@ -0,0 +1,93 @@ +package org.springframework.security.oauth2.provider.token.store.redis; + +import static org.junit.Assert.*; + +import java.util.Date; +import java.util.UUID; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; +import org.springframework.security.oauth2.common.DefaultExpiringOAuth2RefreshToken; +import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; +import org.springframework.security.oauth2.common.DefaultOAuth2RefreshToken; +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.RequestTokenFactory; +import org.springframework.security.oauth2.provider.token.TokenStore; +import org.springframework.security.oauth2.provider.token.store.TokenStoreBaseTests; + +import redis.clients.jedis.JedisShardInfo; +import redis.embedded.RedisServer; + +/** + * @author efenderbosch + */ +public class RedisTokenStoreTests extends TokenStoreBaseTests { + + private RedisTokenStore tokenStore; + private RedisServer redisServer; + + @Override + public TokenStore getTokenStore() { + return tokenStore; + } + + @Before + public void setup() throws Exception { + redisServer = new RedisServer(); + redisServer.start(); + JedisShardInfo shardInfo = new JedisShardInfo("localhost", redisServer.getPort()); + JedisConnectionFactory connectionFactory = new JedisConnectionFactory(shardInfo); + tokenStore = new RedisTokenStore(connectionFactory); + } + + @After + public void tearDown() throws Exception { + redisServer.stop(); + } + + @Test + public void testExpiringRefreshToken() throws InterruptedException { + String refreshToken = UUID.randomUUID().toString(); + DefaultOAuth2RefreshToken expectedExpiringRefreshToken = new DefaultExpiringOAuth2RefreshToken(refreshToken, + new Date(System.currentTimeMillis() + 1500)); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request( + "id", false), new TestAuthentication("test2", false)); + getTokenStore().storeRefreshToken(expectedExpiringRefreshToken, expectedAuthentication); + + OAuth2RefreshToken actualExpiringRefreshToken = getTokenStore().readRefreshToken(refreshToken); + assertEquals(expectedExpiringRefreshToken, actualExpiringRefreshToken); + assertEquals(expectedAuthentication, + getTokenStore().readAuthenticationForRefreshToken(expectedExpiringRefreshToken)); + + // let the token expire + Thread.sleep(1500); + // now it should be gone + assertNull(getTokenStore().readRefreshToken(refreshToken)); + assertNull(getTokenStore().readAuthenticationForRefreshToken(expectedExpiringRefreshToken)); + } + + @Test + public void testExpiringAccessToken() throws InterruptedException { + String accessToken = UUID.randomUUID().toString(); + OAuth2Authentication expectedAuthentication = new OAuth2Authentication(RequestTokenFactory.createOAuth2Request( + "id", false), new TestAuthentication("test2", false)); + DefaultOAuth2AccessToken expectedOAuth2AccessToken = new DefaultOAuth2AccessToken(accessToken); + expectedOAuth2AccessToken.setExpiration(new Date(System.currentTimeMillis() + 1500)); + getTokenStore().storeAccessToken(expectedOAuth2AccessToken, expectedAuthentication); + + OAuth2AccessToken actualOAuth2AccessToken = getTokenStore().readAccessToken(accessToken); + assertEquals(expectedOAuth2AccessToken, actualOAuth2AccessToken); + assertEquals(expectedAuthentication, getTokenStore().readAuthentication(expectedOAuth2AccessToken)); + + // let the token expire + Thread.sleep(1500); + // now it should be gone + assertNull(getTokenStore().readAccessToken(accessToken)); + assertNull(getTokenStore().readAuthentication(expectedOAuth2AccessToken)); + } + +} From 045c16b1d485fc145083d801f404fbcefcfd4e3a Mon Sep 17 00:00:00 2001 From: Mark Silvis Date: Tue, 9 Jun 2015 16:05:19 -0400 Subject: [PATCH 436/831] Fixed typos in docs Fixes gh-504 --- docs/oauth2.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/oauth2.md b/docs/oauth2.md index a0f215564..627fb1d19 100644 --- a/docs/oauth2.md +++ b/docs/oauth2.md @@ -51,7 +51,7 @@ The `ClientDetailsServiceConfigurer` (a callback from your `AuthorizationServerC * `clientId`: (required) the client id. * `secret`: (required for trusted clients) the client secret, if any. * `scope`: The scope to which the client is limited. If scope is undefined or empty (the default) the client is not limited by scope. -* `authorizedGrantTypes`: Grasnt types that are authorized for the client to use. Default value is empty. +* `authorizedGrantTypes`: Grant types that are authorized for the client to use. Default value is empty. * `authorities`: Authorities that are granted to the client (regular Spring Security authorities). Client details can be updated in a running application by access the underlying store directly (e.g. database tables in the case of `JdbcClientDetailsService`) or through the `ClientDetailsManager` interface (which both implementations of `ClientDetailsService` also implement). @@ -282,7 +282,7 @@ Facebook token responses also contain a non-compliant JSON entry for the expiry [InMemoryClientDetailsService]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/InMemoryClientDetailsService.html "InMemoryClientDetailsService" [BaseClientDetails]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/BaseClientDetails.html "BaseClientDetails" [AuthorizationServerTokenServices]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/token/AuthorizationServerTokenServices.html "AuthorizationServerTokenServices" - [OAuth2AuthenticationProcessingFilter]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/filter/OAuth2AuthenticationProcessingFilter.html "OAuth2AuthenticationProcessingFilter" + [OAuth2AuthenticationProcessingFilter]: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilter.html "OAuth2AuthenticationProcessingFilter" [oauth2.xsd]: http://www.springframework.org/schema/security/spring-security-oauth2.xsd "oauth2.xsd" [expressions]: http://docs.spring.io/spring-security/site/docs/3.2.5.RELEASE/reference/htmlsingle/#el-access "Expression Access Control" From 4faa1812835f2744fe0f26c299ed0edb98a4c654 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 10 Jun 2015 09:57:21 +0100 Subject: [PATCH 437/831] Fix more typos --- .../web/configuration/ResourceServerConfigurer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurer.java index b27557633..b8f8d4d8f 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurer.java @@ -20,8 +20,8 @@ /** * Configurer interface for @EnableResourceServer classes. Implement this interface to adjust the access - * rules and paths that are protected by OAuth2 security. APplications may provide multiple instances of this interface, - * and in general (like with other Security configurers), if more than one configures the same preoperty, then the last + * rules and paths that are protected by OAuth2 security. Applications may provide multiple instances of this interface, + * and in general (like with other Security configurers), if more than one configures the same property, then the last * one wins. The configurers are sorted by {@link Order} before being applied. * * @author Dave Syer From 21c1584b9439d22244378f0264b6209fce383375 Mon Sep 17 00:00:00 2001 From: oharsta Date: Fri, 15 May 2015 13:09:00 +0200 Subject: [PATCH 438/831] Fix for inconsistency in the auto approval of scopes Made the implementation of ClientDetails - e.g. the BaseClientDetails - solely responsible for the decision if a scope can be auto approved. Marking a ClientDetails - when using JdbcClientDetailsService - with 'true' for the autoapprove value will still cause all scopes to be auto approved. The consent screen will be skipped in this scenario. Fixes gh-479, fixes gh-482 --- .../examples/sparklr/oauth/SparklrUserApprovalHandler.java | 2 +- .../provider/approval/ApprovalStoreUserApprovalHandler.java | 2 +- .../oauth2/provider/client/BaseClientDetailsTests.java | 6 ++++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrUserApprovalHandler.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrUserApprovalHandler.java index 3ea9b1160..6ce4802b6 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrUserApprovalHandler.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrUserApprovalHandler.java @@ -77,7 +77,7 @@ public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizati ClientDetails client = clientDetailsService .loadClientByClientId(authorizationRequest.getClientId()); for (String scope : requestedScopes) { - if (client.isAutoApprove(scope) || client.isAutoApprove("all")) { + if (client.isAutoApprove(scope)) { approved = true; break; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java index 2de20cb9e..1393a359a 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java @@ -112,7 +112,7 @@ public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizati try { ClientDetails client = clientDetailsService.loadClientByClientId(clientId); for (String scope : requestedScopes) { - if (client.isAutoApprove(scope) || client.isAutoApprove("all")) { + if (client.isAutoApprove(scope)) { approvedScopes.add(scope); } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/BaseClientDetailsTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/BaseClientDetailsTests.java index 9d0340960..7c455b08f 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/BaseClientDetailsTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/BaseClientDetailsTests.java @@ -81,6 +81,12 @@ public void testBaseClientDetailsNoAutoApprove() { assertFalse(details.isAutoApprove("read")); } + @Test + public void testBaseClientDetailsNullAutoApprove() { + BaseClientDetails details = new BaseClientDetails("foo", "", "foo,bar", "authorization_code", "ROLE_USER"); + assertFalse(details.isAutoApprove("read")); + } + @Test public void testJsonSerialize() throws Exception { BaseClientDetails details = new BaseClientDetails("foo", "", "foo,bar", "authorization_code", "ROLE_USER"); From b42a51f1f5b91759fa8a06d4d3f8665a9f9b111d Mon Sep 17 00:00:00 2001 From: Justin Walsh Date: Thu, 11 Jun 2015 08:36:33 +0200 Subject: [PATCH 439/831] Fixed build status tag --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4de3dd39b..7e6838b48 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![Build Status]https://travis-ci.org/spring-projects/spring-security-oauth.svg?branch=master +[![Build Status](https://travis-ci.org/spring-projects/spring-security-oauth.svg?branch=master)](https://travis-ci.org/spring-projects/spring-security-oauth) This project provides support for using Spring Security with OAuth (1a) and OAuth2. It provides features for implementing both consumers From 1b2ae987e9486a875b40424f18bb785baf0b898c Mon Sep 17 00:00:00 2001 From: Casper Mout Date: Mon, 24 Aug 2015 15:25:28 +0200 Subject: [PATCH 440/831] Make sure scope parameter in redirect url is encoded Fixes gh-559 --- .../oauth2/client/filter/OAuth2ClientContextFilter.java | 2 +- .../client/filter/OAuth2ClientContextFilterTests.java | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilter.java index f89706865..27ced1c0d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilter.java @@ -108,7 +108,7 @@ protected void redirectUser(UserRedirectRequiredException e, } this.redirectStrategy.sendRedirect(request, response, builder.build() - .toUriString()); + .encode().toUriString()); } /** diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilterTests.java index 2049a8592..ed10052c6 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilterTests.java @@ -28,6 +28,15 @@ public void testVanillaRedirectUri() throws Exception { testRedirectUri(redirect, params, redirect + "?foo=bar&scope=spam"); } + @Test + public void testTwoScopesRedirectUri() throws Exception { + String redirect = "http://example.com/authorize"; + Map params = new LinkedHashMap(); + params.put("foo", "bar"); + params.put("scope", "spam scope2"); + testRedirectUri(redirect, params, redirect + "?foo=bar&scope=spam%20scope2"); + } + @Test public void testRedirectUriWithUrlInParams() throws Exception { String redirect = "http://example.com/authorize"; From d3c09cb58d3d8a05b424930e59038d9e27d96c80 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 6 Oct 2015 11:12:14 +0100 Subject: [PATCH 441/831] Fix BaseClientDetails.equals() so it uses Integer wrappers Fixes gh-589 --- .../oauth2/provider/client/BaseClientDetails.java | 10 ++++++++-- .../provider/client/BaseClientDetailsTests.java | 12 ++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/BaseClientDetails.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/BaseClientDetails.java index c5688b909..0dccf8230 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/BaseClientDetails.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/BaseClientDetails.java @@ -348,9 +348,15 @@ public boolean equals(Object obj) { if (getClass() != obj.getClass()) return false; BaseClientDetails other = (BaseClientDetails) obj; - if (accessTokenValiditySeconds != other.accessTokenValiditySeconds) + if (accessTokenValiditySeconds == null) { + if (other.accessTokenValiditySeconds != null) + return false; + } else if (!accessTokenValiditySeconds.equals(other.accessTokenValiditySeconds)) return false; - if (refreshTokenValiditySeconds != other.refreshTokenValiditySeconds) + if (refreshTokenValiditySeconds == null) { + if (other.refreshTokenValiditySeconds != null) + return false; + } else if (!refreshTokenValiditySeconds.equals(other.refreshTokenValiditySeconds)) return false; if (authorities == null) { if (other.authorities != null) diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/BaseClientDetailsTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/BaseClientDetailsTests.java index 7c455b08f..9ea52d430 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/BaseClientDetailsTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/BaseClientDetailsTests.java @@ -127,4 +127,16 @@ public void testJsonDeserializeWithArraysAsStrings() throws Exception { assertEquals(expected, details); } + /** + * test equality + */ + @Test + public void testEqualityOfValidity() { + BaseClientDetails details = new BaseClientDetails(); + details.setAccessTokenValiditySeconds(100); + BaseClientDetails other = new BaseClientDetails(); + other.setAccessTokenValiditySeconds(100); + assertEquals(details, other); + } + } From 27f16e57f5a15fc3a78b32aae0a33ac159d56df4 Mon Sep 17 00:00:00 2001 From: George Spalding Date: Tue, 1 Sep 2015 22:29:47 +0200 Subject: [PATCH 442/831] Fixed javadoc problems that prevented javadoc generation --- .../oauth2/client/filter/OAuth2ClientContextFilter.java | 1 - .../security/oauth2/client/http/StringSplitUtils.java | 3 ++- .../security/oauth2/client/test/RestTemplateHolder.java | 2 +- .../oauth2/common/exceptions/OAuth2Exception.java | 2 +- .../AuthorizationServerEndpointsConfigurer.java | 2 +- .../web/configurers/ResourceServerSecurityConfigurer.java | 2 +- .../security/oauth2/provider/AuthorizationRequest.java | 6 +++--- .../security/oauth2/provider/BaseRequest.java | 2 +- .../security/oauth2/provider/TokenRequest.java | 6 +++--- .../provider/authentication/BearerTokenExtractor.java | 2 +- .../endpoint/FrameworkEndpointHandlerMapping.java | 4 ++-- .../expression/OAuth2SecurityExpressionMethods.java | 8 ++++---- .../oauth2/provider/implicit/ImplicitGrantService.java | 2 +- .../oauth2/provider/token/DefaultTokenServices.java | 8 ++++---- .../security/oauth2/provider/token/TokenStore.java | 1 - 15 files changed, 25 insertions(+), 26 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilter.java index 27ced1c0d..2aa69c30c 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilter.java @@ -83,7 +83,6 @@ public void doFilter(ServletRequest servletRequest, /** * Redirect the user according to the specified exception. * - * @param resourceThatNeedsAuthorization * @param e * The user redirect exception. * @param request diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/http/StringSplitUtils.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/http/StringSplitUtils.java index 8670961a9..6eab12a45 100755 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/http/StringSplitUtils.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/http/StringSplitUtils.java @@ -90,8 +90,9 @@ public static Map splitEachArrayElementAndCreateMap(String[] arr * Splits a given string on the given separator character, skips the contents of quoted substrings * when looking for separators. * Introduced for use in DigestProcessingFilter (see SEC-506). - *

    + *

    * This was copied and modified from commons-lang StringUtils + *

    */ public static String[] splitIgnoringQuotes(String str, char separatorChar) { if (str == null) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/RestTemplateHolder.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/RestTemplateHolder.java index 98d9ce81b..aa5a863cd 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/RestTemplateHolder.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/RestTemplateHolder.java @@ -15,7 +15,7 @@ import org.springframework.web.client.RestOperations; /** - * Marker interface for an object that has a getter and setter for a {@link RestTemplate}. + * Marker interface for an object that has a getter and setter for a {@link RestOperations}. * * @author Dave Syer * diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2Exception.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2Exception.java index 3ee73cac0..3032c2655 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2Exception.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2Exception.java @@ -131,7 +131,7 @@ else if (ACCESS_DENIED.equals(errorCode)) { } /** - * Creates an {@link OAuth2Exception} from a Map. + * Creates an {@link OAuth2Exception} from a Map<String,String>. * * @param errorParams * @return 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 42d07bc60..8882cb01d 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 @@ -278,7 +278,7 @@ public AuthorizationServerEndpointsConfigurer exceptionTranslator(WebResponseExc /** * The AuthenticationManager for the password grant. * - * @param builder an AuthenticationManager, fully initialized + * @param authenticationManager an AuthenticationManager, fully initialized * @return this for a fluent style */ public AuthorizationServerEndpointsConfigurer authenticationManager(AuthenticationManager authenticationManager) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java index 4042ab38b..47252cca4 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java @@ -48,7 +48,7 @@ /** * * @author Rob Winch - * @Author Dave Syer + * @author Dave Syer * * @since 2.0.0 */ diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java index 0c58aa4ee..ddb90e808 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/AuthorizationRequest.java @@ -209,9 +209,9 @@ public void setClientId(String clientId) { /** * Set the scope value. If the collection contains only a single scope * value, this method will parse that value into a collection using - * {@link OAuth2Utils.parseParameterList}. + * {@link OAuth2Utils#parseParameterList}. * - * @see TokenRequest.setScope + * @see TokenRequest#setScope * * @param scope */ @@ -224,7 +224,7 @@ public void setScope(Collection scope) { * the original request parameters and should never be changed during * processing. The map passed in is wrapped in an unmodifiable map instance. * - * @see TokenRequest.setRequestParameters + * @see TokenRequest#setRequestParameters * * @param requestParameters */ diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java index a09ced945..52e38cf6b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java @@ -31,7 +31,7 @@ * * A base class for the three "*Request" classes used in processing OAuth 2 * authorizations. This class should never be used directly, - * and it should never be used as the type for a local or other + * and it should never be used as the type for a local or other * variable. * * @author Dave Syer diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java index e9277ef45..ebc13a56d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenRequest.java @@ -61,9 +61,9 @@ public void setClientId(String clientId) { /** * Set the scope value. If the collection contains only a single scope value, this method will parse that value into - * a collection using {@link OAuth2Utils.parseParameterList}. + * a collection using {@link OAuth2Utils#parseParameterList}. * - * @see AuthorizationRequest.setScope + * @see AuthorizationRequest#setScope * * @param scope */ @@ -75,7 +75,7 @@ public void setScope(Collection scope) { * Set the Request Parameters on this authorization request, which represent the original request parameters and * should never be changed during processing. The map passed in is wrapped in an unmodifiable map instance. * - * @see AuthorizationRequest.setRequestParameters + * @see AuthorizationRequest#setRequestParameters * * @param requestParameters */ diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/BearerTokenExtractor.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/BearerTokenExtractor.java index 281c06fd6..bc2b76c29 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/BearerTokenExtractor.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/BearerTokenExtractor.java @@ -25,7 +25,7 @@ /** * {@link TokenExtractor} that strips the authenticator from a bearer token request (with an Authorization header in the - * form "Bearer ", or as a request parameter if that fails). The access token is the principal in + * form "Bearer <TOKEN>", or as a request parameter if that fails). The access token is the principal in * the authentication token that is extracted. * * @author Dave Syer diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java index 6f8166b9e..149da89ef 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java @@ -69,7 +69,7 @@ public void setPrefix(String prefix) { * Custom mappings for framework endpoint paths. The keys in the map are the default framework endpoint path, e.g. * "/oauth/authorize", and the values are the desired runtime paths. * - * @param mappings the mappings to set + * @param patternMap the mappings to set */ public void setMappings(Map patternMap) { this.mappings = new HashMap(patternMap); @@ -109,7 +109,7 @@ public Set getPaths() { /** * The name of the request parameter that distinguishes a call to approve an authorization. Default is - * {@link AuthorizationRequest#USER_OAUTH_APPROVAL}. + * {@link OAuth2Utils#USER_OAUTH_APPROVAL}. * * @param approvalParameter the approvalParameter to set */ diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethods.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethods.java index f70aad150..a2f31f43a 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethods.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethods.java @@ -76,7 +76,7 @@ public boolean throwOnError(boolean decision) { /** * Check if the OAuth2 client (not the user) has the role specified. To check the user's roles see - * {@link #hasRole(String)}. + * {@link #clientHasRole(String)}. * * @param role the role to check * @return true if the OAuth2 client has this role @@ -87,7 +87,7 @@ public boolean clientHasRole(String role) { /** * Check if the OAuth2 client (not the user) has one of the roles specified. To check the user's roles see - * {@link #hasAnyRole(String)}. + * {@link #clientHasAnyRole(String...)}. * * @param roles the roles to check * @return true if the OAuth2 client has one of these roles @@ -109,7 +109,7 @@ public boolean hasScope(String scope) { /** * Check if the current OAuth2 authentication has one of the scopes specified. * - * @param roles the scopes to check + * @param scopes the scopes to check * @return true if the OAuth2 token has one of these scopes * @throws AccessDeniedException if the scope is invalid and we the flag is set to throw the exception */ @@ -142,7 +142,7 @@ public boolean hasScopeMatching(String scopeRegex) { * access = "#oauth2.hasAnyScopeMatching('admin:manage_scopes','.*_admin:manage_scopes','.*_admin:read_scopes')))" * * - * @param roles the scopes regex to match + * @param scopesRegex the scopes regex to match * @return true if the OAuth2 token has one of these scopes * @throws AccessDeniedException if the scope is invalid and we the flag is set to throw the exception */ diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitGrantService.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitGrantService.java index 105a3d8ce..ea1797143 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitGrantService.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitGrantService.java @@ -4,7 +4,7 @@ import org.springframework.security.oauth2.provider.TokenRequest; /** - * Service to associate & store an incoming AuthorizationRequest with the TokenRequest that is passed + * Service to associate & store an incoming AuthorizationRequest with the TokenRequest that is passed * to the ImplicitTokenGranter during the Implicit flow. This mimics the AuthorizationCodeServices * functionality from the Authorization Code flow, allowing the ImplicitTokenGranter to reference the original * AuthorizationRequest, while still allowing the ImplicitTokenGranter to adhere to the TokenGranter interface. diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java index f580f0596..17da1f8ad 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java @@ -189,7 +189,7 @@ public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) { * Create a refreshed authentication. * * @param authentication The authentication. - * @param scope The scope for the refreshed token. + * @param request The scope for the refreshed token. * @return The refreshed authentication. * @throws InvalidScopeException If the scope requested is invalid or wider than the original scope. */ @@ -304,7 +304,7 @@ private OAuth2AccessToken createAccessToken(OAuth2Authentication authentication, /** * The access token validity period in seconds * - * @param authorizationRequest the current authorization request + * @param clientAuth the current authorization request * @return the access token validity period in seconds */ protected int getAccessTokenValiditySeconds(OAuth2Request clientAuth) { @@ -321,7 +321,7 @@ protected int getAccessTokenValiditySeconds(OAuth2Request clientAuth) { /** * The refresh token validity period in seconds * - * @param authorizationRequest the current authorization request + * @param clientAuth the current authorization request * @return the refresh token validity period in seconds */ protected int getRefreshTokenValiditySeconds(OAuth2Request clientAuth) { @@ -339,7 +339,7 @@ protected int getRefreshTokenValiditySeconds(OAuth2Request clientAuth) { * Is a refresh token supported for this client (or the global setting if * {@link #setClientDetailsService(ClientDetailsService) clientDetailsService} is not set. * - * @param authorizationRequest the current authorization request + * @param clientAuth the current authorization request * @return boolean to indicate if refresh token is supported */ protected boolean isSupportRefreshToken(OAuth2Request clientAuth) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/TokenStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/TokenStore.java index bab2b9e02..eaf3d38bb 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/TokenStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/TokenStore.java @@ -104,7 +104,6 @@ public interface TokenStore { Collection findTokensByClientIdAndUserName(String clientId, String userName); /** - * @param userName the user name to search * @param clientId the client id to search * @return a collection of access tokens */ From 7f2fc9fc43239fa4662734c54a7e0b364a91874f Mon Sep 17 00:00:00 2001 From: George Spalding Date: Wed, 2 Sep 2015 21:09:46 +0200 Subject: [PATCH 443/831] Fixed pom warnings; -Replaced use of deprecated property pom.groupId -> project.groupId -Added when referencing parent pom that was not available at parent directory level -Removed duplicate dependency to org.springframework:spring-aop with scope compile --- pom.xml | 7 +------ samples/oauth/tonr/pom.xml | 10 +++++----- samples/oauth2/tonr/pom.xml | 4 ++-- tests/annotation/pom.xml | 1 + tests/xml/pom.xml | 1 + 5 files changed, 10 insertions(+), 13 deletions(-) diff --git a/pom.xml b/pom.xml index 673cfb30a..fdad7798b 100644 --- a/pom.xml +++ b/pom.xml @@ -170,12 +170,6 @@ - - org.springframework - spring-aop - ${spring.version} - - org.springframework spring-beans @@ -351,6 +345,7 @@ the Spring project nature--> org.apache.maven.plugins maven-eclipse-plugin + 2.10 org.springframework.ide.eclipse.core.springnature diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index 023d375b2..efac5510e 100644 --- a/samples/oauth/tonr/pom.xml +++ b/samples/oauth/tonr/pom.xml @@ -34,9 +34,9 @@ /sparklr2 - ${pom.groupId} + ${project.groupId} sparklr - ${pom.version} + ${project.version} war true @@ -63,11 +63,11 @@ - ${pom.groupId} + ${project.groupId} sparklr - ${pom.version} + ${project.version} war - tomcat + test diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 59630cb59..71a659f70 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -84,9 +84,9 @@ /sparklr2 - ${pom.groupId} + ${project.groupId} sparklr2 - ${pom.version} + ${project.version} war true diff --git a/tests/annotation/pom.xml b/tests/annotation/pom.xml index 16f476a1a..79b08b81f 100644 --- a/tests/annotation/pom.xml +++ b/tests/annotation/pom.xml @@ -28,6 +28,7 @@ org.springframework.boot spring-boot-starter-parent 1.2.2.RELEASE + diff --git a/tests/xml/pom.xml b/tests/xml/pom.xml index 8ca0b8dc5..0356ab53f 100644 --- a/tests/xml/pom.xml +++ b/tests/xml/pom.xml @@ -25,6 +25,7 @@ org.springframework.boot spring-boot-starter-parent 1.2.2.RELEASE + From 8e5a483ff3a575564e9b44f82984c3877585ade0 Mon Sep 17 00:00:00 2001 From: George Spalding Date: Sat, 12 Sep 2015 08:14:23 +0200 Subject: [PATCH 444/831] Removed optional from spring aop dependency in parent pom dependencymanagement --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index fdad7798b..0d0cec30c 100644 --- a/pom.xml +++ b/pom.xml @@ -13,6 +13,7 @@ spring-security-oauth2 tests samples + spring-security-jwt @@ -94,17 +95,17 @@ bootstrap - repo.spring.io/milestone + repo.spring.io-milestone Spring Framework Milestone Repository http://repo.spring.io/libs-milestone-local - repo.spring.io/release + repo.spring.io-release Spring Framework Release Repository http://repo.spring.io/libs-release-local - repo.spring.io/snapshot + repo.spring.io-snapshot Spring Framework Maven Snapshot Repository http://repo.spring.io/libs-snapshot-local true @@ -198,7 +199,6 @@ org.springframework spring-aop ${spring.version} - true From c6ae35d5c52cb7453191333731fb94e35f82257a Mon Sep 17 00:00:00 2001 From: Jakub Narloch Date: Sat, 29 Aug 2015 16:10:24 +0200 Subject: [PATCH 445/831] Made the redis client dependencies optional --- spring-security-oauth2/pom.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index b2bf88a0d..3e0c69468 100644 --- a/spring-security-oauth2/pom.xml +++ b/spring-security-oauth2/pom.xml @@ -148,12 +148,14 @@ org.springframework.data spring-data-redis 1.5.0.RELEASE + true redis.clients jedis 2.6.3 + true From 4fdd07040604935e143ecb71573c8231c6d5d6d4 Mon Sep 17 00:00:00 2001 From: Vivek Kiran Date: Fri, 25 Sep 2015 01:36:06 +0530 Subject: [PATCH 446/831] Fixed Url Fixed Url --- samples/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/README.md b/samples/README.md index c6dce912c..2ba26c4b4 100644 --- a/samples/README.md +++ b/samples/README.md @@ -59,7 +59,7 @@ To deploy the apps in Eclipse you will need the Maven plugin (`m2e`) and the Web Tools Project (WTP) plugins. If you have SpringSource Toolsuite (STS) you should already have those, aso you can deploy the apps very simply. (Update the WTP plugin to at least version 0.12 at -http://m2eclipse.sonatype.org/sites/m2e-extras if you have an older +http://download.eclipse.org/technology/m2e/releases if you have an older one, or the context roots for the apps will be wrong.) * Ensure the Spring Security OAuth dependencies are available locally From 747a0df973ec93dfb6ddde63adacd0d8795e232b Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 6 Oct 2015 11:45:39 +0100 Subject: [PATCH 447/831] Add support for x-forwarded-prefix to SpelView Fixes gh-515 (but only with Spring 4.2 --- .../security/oauth2/provider/endpoint/SpelView.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/SpelView.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/SpelView.java index 5e17e68b9..860f23e02 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/SpelView.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/SpelView.java @@ -26,6 +26,7 @@ import org.springframework.util.PropertyPlaceholderHelper; import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver; import org.springframework.web.servlet.View; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; /** * Simple String template renderer. @@ -63,7 +64,8 @@ public String getContentType() { public void render(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception { Map map = new HashMap(model); - map.put("path", (Object) request.getContextPath()); + map.put("path", (Object) ServletUriComponentsBuilder.fromContextPath(request).build() + .getPath()); context.setRootObject(map); String result = helper.replacePlaceholders(template, resolver); response.setContentType(getContentType()); From 7466dbdb9ad703689af01eff5ca6e88ce9d9f796 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 6 Oct 2015 12:04:28 +0100 Subject: [PATCH 448/831] Add test suite for ordering tests --- .../security/oauth2/AdhocTestSuite.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/AdhocTestSuite.java diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/AdhocTestSuite.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/AdhocTestSuite.java new file mode 100644 index 000000000..4838bace2 --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/AdhocTestSuite.java @@ -0,0 +1,36 @@ +/* + * Copyright 2012-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.oauth2; + +import org.junit.Ignore; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; +import org.springframework.security.oauth2.config.annotation.AuthorizationServerConfigurationTests; +import org.springframework.security.oauth2.config.annotation.ResourceServerConfigurationTests; + +/** + * A test suite for probing weird ordering problems in the tests. + * + * @author Dave Syer + */ +@RunWith(Suite.class) +@SuiteClasses({ AuthorizationServerConfigurationTests.class, ResourceServerConfigurationTests.class }) +@Ignore +public class AdhocTestSuite { + +} From 6a436db6cd959d6244d4b5cde0582018a7d974a3 Mon Sep 17 00:00:00 2001 From: Mariusz Kopylec Date: Thu, 17 Sep 2015 12:21:19 +0200 Subject: [PATCH 449/831] Allow creating custom grant types based on existing ones Fixes gh-577 --- .../security/oauth2/provider/CompositeTokenGranter.java | 7 +++++++ .../provider/client/ClientCredentialsTokenGranter.java | 7 ++++++- .../provider/code/AuthorizationCodeTokenGranter.java | 7 ++++++- .../oauth2/provider/implicit/ImplicitTokenGranter.java | 7 ++++++- .../password/ResourceOwnerPasswordTokenGranter.java | 7 ++++++- .../oauth2/provider/refresh/RefreshTokenGranter.java | 7 ++++++- 6 files changed, 37 insertions(+), 5 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/CompositeTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/CompositeTokenGranter.java index 8cae0bdd1..0148e580c 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/CompositeTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/CompositeTokenGranter.java @@ -42,5 +42,12 @@ public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) { } return null; } + + public void addTokenGranter(TokenGranter tokenGranter) { + if (tokenGranter == null) { + throw new IllegalArgumentException("Token granter is null"); + } + tokenGranters.add(tokenGranter); + } } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenGranter.java index d5eeece25..6583e255d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenGranter.java @@ -35,7 +35,12 @@ public class ClientCredentialsTokenGranter extends AbstractTokenGranter { public ClientCredentialsTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory) { - super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE); + this(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE); + } + + protected ClientCredentialsTokenGranter(AuthorizationServerTokenServices tokenServices, + ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory, String grantType) { + super(tokenServices, clientDetailsService, requestFactory, grantType); } public void setAllowRefresh(boolean allowRefresh) { diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranter.java index 578cf3f9a..c76ed6d5d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranter.java @@ -48,7 +48,12 @@ public class AuthorizationCodeTokenGranter extends AbstractTokenGranter { public AuthorizationCodeTokenGranter(AuthorizationServerTokenServices tokenServices, AuthorizationCodeServices authorizationCodeServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory) { - super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE); + this(tokenServices, authorizationCodeServices, clientDetailsService, requestFactory, GRANT_TYPE); + } + + protected AuthorizationCodeTokenGranter(AuthorizationServerTokenServices tokenServices, AuthorizationCodeServices authorizationCodeServices, + ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory, String grantType) { + super(tokenServices, clientDetailsService, requestFactory, grantType); this.authorizationCodeServices = authorizationCodeServices; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java index 73137cade..209bfc2a6 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java @@ -39,7 +39,12 @@ public class ImplicitTokenGranter extends AbstractTokenGranter { private static final String GRANT_TYPE = "implicit"; public ImplicitTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory) { - super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE); + this(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE); + } + + protected ImplicitTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, + OAuth2RequestFactory requestFactory, String grantType) { + super(tokenServices, clientDetailsService, requestFactory, grantType); } @Override diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java index 15b0d4649..c996f1d30 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java @@ -47,7 +47,12 @@ public class ResourceOwnerPasswordTokenGranter extends AbstractTokenGranter { public ResourceOwnerPasswordTokenGranter(AuthenticationManager authenticationManager, AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory) { - super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE); + this(authenticationManager, tokenServices, clientDetailsService, requestFactory, GRANT_TYPE); + } + + protected ResourceOwnerPasswordTokenGranter(AuthenticationManager authenticationManager, AuthorizationServerTokenServices tokenServices, + ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory, String grantType) { + super(tokenServices, clientDetailsService, requestFactory, grantType); this.authenticationManager = authenticationManager; } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/refresh/RefreshTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/refresh/RefreshTokenGranter.java index f9ee74347..55327ed86 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/refresh/RefreshTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/refresh/RefreshTokenGranter.java @@ -33,7 +33,12 @@ public class RefreshTokenGranter extends AbstractTokenGranter { private static final String GRANT_TYPE = "refresh_token"; public RefreshTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory) { - super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE); + this(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE); + } + + protected RefreshTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, + OAuth2RequestFactory requestFactory, String grantType) { + super(tokenServices, clientDetailsService, requestFactory, grantType); } @Override From 234ec98f88f9ef5246381beed21eb7345d4aa82d Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 6 Oct 2015 13:45:55 +0100 Subject: [PATCH 450/831] Fix SpelView for Spring 4.2 and empty context path --- .../security/oauth2/provider/endpoint/SpelView.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/SpelView.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/SpelView.java index 860f23e02..996be819c 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/SpelView.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/SpelView.java @@ -64,8 +64,9 @@ public String getContentType() { public void render(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception { Map map = new HashMap(model); - map.put("path", (Object) ServletUriComponentsBuilder.fromContextPath(request).build() - .getPath()); + String path = ServletUriComponentsBuilder.fromContextPath(request).build() + .getPath(); + map.put("path", (Object) path==null ? "" : path); context.setRootObject(map); String result = helper.replacePlaceholders(template, resolver); response.setContentType(getContentType()); From fa967f0113b6001334d7fa1b9fad152c773dd40d Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 22 Oct 2015 13:20:14 +0100 Subject: [PATCH 451/831] Be more defensive in whitelabel error view If the error is not available (e.g. user happens to browse to the /oauth/error page) we can be more defensive. Fixes gh-591 --- .../provider/endpoint/WhitelabelErrorEndpoint.java | 7 ++++++- .../endpoint/WhitelabelErrorEndpointTests.java | 10 ++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelErrorEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelErrorEndpoint.java index 2035093d9..5c0fb2b59 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelErrorEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelErrorEndpoint.java @@ -1,5 +1,6 @@ package org.springframework.security.oauth2.provider.endpoint; +import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -19,7 +20,11 @@ public class WhitelabelErrorEndpoint { @RequestMapping("/oauth/error") public ModelAndView handleError(HttpServletRequest request) { Map model = new HashMap(); - model.put("error", request.getAttribute("error")); + Object error = request.getAttribute("error"); + if (error==null) { + error = Collections.singletonMap("summary", "Unknown error"); + } + model.put("error", error); return new ModelAndView(new SpelView(ERROR), model); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelErrorEndpointTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelErrorEndpointTests.java index e03f81687..13a628e5a 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelErrorEndpointTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelErrorEndpointTests.java @@ -43,4 +43,14 @@ public void testErrorPage() throws Exception { assertTrue("Wrong content: " + content, content.contains("invalid_client")); } + @Test + public void testErrorPageNoError() throws Exception { + request.setContextPath("/foo"); + ModelAndView result = endpoint.handleError(request); + result.getView().render(result.getModel(), request , response); + String content = response.getContentAsString(); + assertTrue("Wrong content: " + content, content.contains("OAuth Error")); + assertTrue("Wrong content: " + content, content.contains("Unknown")); + } + } From 500856e1995bdc156dffbf12beb1d1eb6cc5f9ee Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 22 Oct 2015 15:04:35 +0100 Subject: [PATCH 452/831] Allow single-valued AUD claim in JWT token Apparently some providers use a single value for the audience claim (including Microsoft Azure), so we can be defensive and use it as is if it is just a String. Fixes gh-557 --- .../token/DefaultAccessTokenConverter.java | 12 +++++++++++- .../DefaultAccessTokenConverterTests.java | 19 ++++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java index b03b40fb8..06829a7c9 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java @@ -130,7 +130,7 @@ public OAuth2Authentication extractAuthentication(Map map) { parameters.put(GRANT_TYPE, (String) map.get(GRANT_TYPE)); } @SuppressWarnings("unchecked") - Set resourceIds = new LinkedHashSet(map.containsKey(AUD) ? (Collection) map.get(AUD) + Set resourceIds = new LinkedHashSet(map.containsKey(AUD) ? getAudience(map) : Collections.emptySet()); Collection authorities = null; @@ -144,4 +144,14 @@ public OAuth2Authentication extractAuthentication(Map map) { return new OAuth2Authentication(request, user); } + private Collection getAudience(Map map) { + Object auds = map.get(AUD); + if (auds instanceof Collection) { + @SuppressWarnings("unchecked") + Collection result = (Collection) auds; + return result; + } + return Collections.singleton((String)auds); + } + } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverterTests.java index b1e8f3ce5..e082254cd 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverterTests.java @@ -14,8 +14,11 @@ package org.springframework.security.oauth2.provider.token; import static java.util.Collections.singleton; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import java.util.Collection; +import java.util.LinkedHashMap; import java.util.Map; import org.junit.Before; @@ -81,4 +84,18 @@ public void extractAuthenticationFromClientToken() { assertEquals("[ROLE_CLIENT]", extracted.getAuthorities().toString()); } + @Test + public void extractAuthenticationFromClientTokenSingleValuedAudience() { + DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken("FOO"); + OAuth2Authentication authentication = new OAuth2Authentication(request, null); + token.setScope(authentication.getOAuth2Request().getScope()); + Map map = new LinkedHashMap(converter.convertAccessToken(token, authentication)); + @SuppressWarnings("unchecked") + Object aud = ((Collection)map.get(AccessTokenConverter.AUD)).iterator().next(); + map.put(AccessTokenConverter.AUD, aud); + assertTrue(map.containsKey(AccessTokenConverter.AUD)); + OAuth2Authentication extracted = converter.extractAuthentication(map); + assertEquals("["+aud+"]", extracted.getOAuth2Request().getResourceIds().toString()); + } + } From 2e091f8fd3f692abef4f002e599d86651a848e10 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 22 Oct 2015 15:22:18 +0100 Subject: [PATCH 453/831] Add support for check-token-endpoint-url in XML parser Also check-token-enabled (defaults to false). Fixes gh-514 --- docs/oauth2.md | 4 +- ...thorizationServerBeanDefinitionParser.java | 180 ++++++++++++------ .../FrameworkEndpointHandlerMapping.java | 1 - .../oauth2/spring-security-oauth2-2.0.xsd | 18 +- ...zationServerBeanDefinitionParserTests.java | 1 + .../xml/authorization-server-check-token.xml | 16 ++ 6 files changed, 156 insertions(+), 64 deletions(-) create mode 100644 spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-check-token.xml diff --git a/docs/oauth2.md b/docs/oauth2.md index 627fb1d19..aaf2eebbf 100644 --- a/docs/oauth2.md +++ b/docs/oauth2.md @@ -123,9 +123,7 @@ N.B. the Authorization endpoint `/oauth/authorize` (or its mapped alternative) s The token endpoint is protected for you by default by Spring OAuth in the `@Configuration` support using HTTP Basic authentication of the client secret. This is not the case in XML (so it should be protected explicitly). -In XML the `` element has some attributes that can be used to change the default endpoint URLs in a similar way. - -### +In XML the `` element has some attributes that can be used to change the default endpoint URLs in a similar way. The `/check_token` endpoint has to be explicitly enabled (with the `check-token-enabled` attribute). ## Customizing the UI 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 c282b239c..6cd39dc75 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 @@ -30,6 +30,7 @@ import org.springframework.security.oauth2.provider.code.AuthorizationCodeTokenGranter; import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices; import org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint; +import org.springframework.security.oauth2.provider.endpoint.CheckTokenEndpoint; import org.springframework.security.oauth2.provider.endpoint.FrameworkEndpointHandlerMapping; import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint; import org.springframework.security.oauth2.provider.endpoint.WhitelabelApprovalEndpoint; @@ -48,16 +49,21 @@ * @author Ryan Heaton * @author Dave Syer */ -public class AuthorizationServerBeanDefinitionParser extends ProviderBeanDefinitionParser { +public class AuthorizationServerBeanDefinitionParser + extends ProviderBeanDefinitionParser { @Override - protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, ParserContext parserContext, - String tokenServicesRef, String serializerRef) { + protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, + ParserContext parserContext, String tokenServicesRef, String serializerRef) { String clientDetailsRef = element.getAttribute("client-details-service-ref"); - String oAuth2RequestFactoryRef = element.getAttribute("authorization-request-manager-ref"); + String oAuth2RequestFactoryRef = element + .getAttribute("authorization-request-manager-ref"); String tokenEndpointUrl = element.getAttribute("token-endpoint-url"); - String authorizationEndpointUrl = element.getAttribute("authorization-endpoint-url"); + String checkTokenUrl = element.getAttribute("check-token-endpoint-url"); + String enableCheckToken = element.getAttribute("check-token-enabled"); + String authorizationEndpointUrl = element + .getAttribute("authorization-endpoint-url"); String tokenGranterRef = element.getAttribute("token-granter-ref"); String redirectStrategyRef = element.getAttribute("redirect-strategy-ref"); String userApprovalHandlerRef = element.getAttribute("user-approval-handler-ref"); @@ -74,10 +80,11 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P .rootBeanDefinition(AuthorizationEndpoint.class); if (!StringUtils.hasText(clientDetailsRef)) { - parserContext.getReaderContext().error("ClientDetailsService must be provided", element); + parserContext.getReaderContext() + .error("ClientDetailsService must be provided", element); return null; } - + if (!StringUtils.hasText(oAuth2RequestValidatorRef)) { oAuth2RequestValidatorRef = "defaultOAuth2RequestValidator"; BeanDefinitionBuilder oAuth2RequestValidator = BeanDefinitionBuilder @@ -85,7 +92,8 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P parserContext.getRegistry().registerBeanDefinition(oAuth2RequestValidatorRef, oAuth2RequestValidator.getBeanDefinition()); } - authorizationEndpointBean.addPropertyReference("oAuth2RequestValidator", oAuth2RequestValidatorRef); + authorizationEndpointBean.addPropertyReference("oAuth2RequestValidator", + oAuth2RequestValidatorRef); if (!StringUtils.hasText(oAuth2RequestFactoryRef)) { oAuth2RequestFactoryRef = "oAuth2AuthorizationRequestManager"; @@ -101,7 +109,8 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P tokenGranterRef = "oauth2TokenGranter"; BeanDefinitionBuilder tokenGranterBean = BeanDefinitionBuilder .rootBeanDefinition(CompositeTokenGranter.class); - parserContext.getRegistry().registerBeanDefinition(tokenGranterRef, tokenGranterBean.getBeanDefinition()); + parserContext.getRegistry().registerBeanDefinition(tokenGranterRef, + tokenGranterBean.getBeanDefinition()); tokenGranters = new ManagedList(); tokenGranterBean.addConstructorArgValue(tokenGranters); } @@ -109,39 +118,50 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P boolean registerAuthorizationEndpoint = false; - Element authorizationCodeElement = DomUtils.getChildElementByTagName(element, "authorization-code"); + Element authorizationCodeElement = DomUtils.getChildElementByTagName(element, + "authorization-code"); - if (authorizationCodeElement != null - && !"true".equalsIgnoreCase(authorizationCodeElement.getAttribute("disabled"))) { + if (authorizationCodeElement != null && !"true" + .equalsIgnoreCase(authorizationCodeElement.getAttribute("disabled"))) { // authorization code grant configuration. - String authorizationCodeServices = authorizationCodeElement.getAttribute("authorization-code-services-ref"); - String clientTokenCacheRef = authorizationCodeElement.getAttribute("client-token-cache-ref"); + String authorizationCodeServices = authorizationCodeElement + .getAttribute("authorization-code-services-ref"); + String clientTokenCacheRef = authorizationCodeElement + .getAttribute("client-token-cache-ref"); BeanDefinitionBuilder authorizationCodeTokenGranterBean = BeanDefinitionBuilder .rootBeanDefinition(AuthorizationCodeTokenGranter.class); if (StringUtils.hasText(tokenServicesRef)) { - authorizationCodeTokenGranterBean.addConstructorArgReference(tokenServicesRef); + authorizationCodeTokenGranterBean + .addConstructorArgReference(tokenServicesRef); } if (!StringUtils.hasText(authorizationCodeServices)) { authorizationCodeServices = "oauth2AuthorizationCodeServices"; BeanDefinitionBuilder authorizationCodeServicesBean = BeanDefinitionBuilder .rootBeanDefinition(InMemoryAuthorizationCodeServices.class); - parserContext.getRegistry().registerBeanDefinition(authorizationCodeServices, + parserContext.getRegistry().registerBeanDefinition( + authorizationCodeServices, authorizationCodeServicesBean.getBeanDefinition()); } - authorizationEndpointBean.addPropertyReference("authorizationCodeServices", authorizationCodeServices); - authorizationCodeTokenGranterBean.addConstructorArgReference(authorizationCodeServices); - authorizationCodeTokenGranterBean.addConstructorArgReference(clientDetailsRef); - authorizationCodeTokenGranterBean.addConstructorArgReference(oAuth2RequestFactoryRef); + authorizationEndpointBean.addPropertyReference("authorizationCodeServices", + authorizationCodeServices); + authorizationCodeTokenGranterBean + .addConstructorArgReference(authorizationCodeServices); + authorizationCodeTokenGranterBean + .addConstructorArgReference(clientDetailsRef); + authorizationCodeTokenGranterBean + .addConstructorArgReference(oAuth2RequestFactoryRef); if (StringUtils.hasText(clientTokenCacheRef)) { - authorizationEndpointBean.addPropertyReference("clientTokenCache", clientTokenCacheRef); + authorizationEndpointBean.addPropertyReference("clientTokenCache", + clientTokenCacheRef); } if (StringUtils.hasText(oAuth2RequestFactoryRef)) { - authorizationEndpointBean.addPropertyReference("oAuth2RequestFactory", oAuth2RequestFactoryRef); + authorizationEndpointBean.addPropertyReference("oAuth2RequestFactory", + oAuth2RequestFactoryRef); } if (tokenGranters != null) { @@ -152,18 +172,23 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P } if (tokenGranters != null) { - Element refreshTokenElement = DomUtils.getChildElementByTagName(element, "refresh-token"); + Element refreshTokenElement = DomUtils.getChildElementByTagName(element, + "refresh-token"); - if (refreshTokenElement != null && !"true".equalsIgnoreCase(refreshTokenElement.getAttribute("disabled"))) { + if (refreshTokenElement != null && !"true" + .equalsIgnoreCase(refreshTokenElement.getAttribute("disabled"))) { BeanDefinitionBuilder refreshTokenGranterBean = BeanDefinitionBuilder .rootBeanDefinition(RefreshTokenGranter.class); refreshTokenGranterBean.addConstructorArgReference(tokenServicesRef); refreshTokenGranterBean.addConstructorArgReference(clientDetailsRef); - refreshTokenGranterBean.addConstructorArgReference(oAuth2RequestFactoryRef); + refreshTokenGranterBean + .addConstructorArgReference(oAuth2RequestFactoryRef); tokenGranters.add(refreshTokenGranterBean.getBeanDefinition()); } - Element implicitElement = DomUtils.getChildElementByTagName(element, "implicit"); - if (implicitElement != null && !"true".equalsIgnoreCase(implicitElement.getAttribute("disabled"))) { + Element implicitElement = DomUtils.getChildElementByTagName(element, + "implicit"); + if (implicitElement != null && !"true" + .equalsIgnoreCase(implicitElement.getAttribute("disabled"))) { BeanDefinitionBuilder implicitGranterBean = BeanDefinitionBuilder .rootBeanDefinition(ImplicitTokenGranter.class); implicitGranterBean.addConstructorArgReference(tokenServicesRef); @@ -172,35 +197,44 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P tokenGranters.add(implicitGranterBean.getBeanDefinition()); registerAuthorizationEndpoint = true; } - Element clientCredentialsElement = DomUtils.getChildElementByTagName(element, "client-credentials"); - if (clientCredentialsElement != null - && !"true".equalsIgnoreCase(clientCredentialsElement.getAttribute("disabled"))) { + Element clientCredentialsElement = DomUtils.getChildElementByTagName(element, + "client-credentials"); + if (clientCredentialsElement != null && !"true".equalsIgnoreCase( + clientCredentialsElement.getAttribute("disabled"))) { BeanDefinitionBuilder clientCredentialsGranterBean = BeanDefinitionBuilder .rootBeanDefinition(ClientCredentialsTokenGranter.class); clientCredentialsGranterBean.addConstructorArgReference(tokenServicesRef); clientCredentialsGranterBean.addConstructorArgReference(clientDetailsRef); - clientCredentialsGranterBean.addConstructorArgReference(oAuth2RequestFactoryRef); + clientCredentialsGranterBean + .addConstructorArgReference(oAuth2RequestFactoryRef); tokenGranters.add(clientCredentialsGranterBean.getBeanDefinition()); } - Element clientPasswordElement = DomUtils.getChildElementByTagName(element, "password"); - if (clientPasswordElement != null - && !"true".equalsIgnoreCase(clientPasswordElement.getAttribute("disabled"))) { + Element clientPasswordElement = DomUtils.getChildElementByTagName(element, + "password"); + if (clientPasswordElement != null && !"true" + .equalsIgnoreCase(clientPasswordElement.getAttribute("disabled"))) { BeanDefinitionBuilder clientPasswordTokenGranter = BeanDefinitionBuilder .rootBeanDefinition(ResourceOwnerPasswordTokenGranter.class); - String authenticationManagerRef = clientPasswordElement.getAttribute("authentication-manager-ref"); + String authenticationManagerRef = clientPasswordElement + .getAttribute("authentication-manager-ref"); if (!StringUtils.hasText(authenticationManagerRef)) { authenticationManagerRef = BeanIds.AUTHENTICATION_MANAGER; } - clientPasswordTokenGranter.addConstructorArgReference(authenticationManagerRef); + clientPasswordTokenGranter + .addConstructorArgReference(authenticationManagerRef); clientPasswordTokenGranter.addConstructorArgReference(tokenServicesRef); clientPasswordTokenGranter.addConstructorArgReference(clientDetailsRef); - clientPasswordTokenGranter.addConstructorArgReference(oAuth2RequestFactoryRef); + clientPasswordTokenGranter + .addConstructorArgReference(oAuth2RequestFactoryRef); tokenGranters.add(clientPasswordTokenGranter.getBeanDefinition()); } - List customGrantElements = DomUtils.getChildElementsByTagName(element, "custom-grant"); + List customGrantElements = DomUtils + .getChildElementsByTagName(element, "custom-grant"); for (Element customGrantElement : customGrantElements) { - if (!"true".equalsIgnoreCase(customGrantElement.getAttribute("disabled"))) { - String customGranterRef = customGrantElement.getAttribute("token-granter-ref"); + if (!"true" + .equalsIgnoreCase(customGrantElement.getAttribute("disabled"))) { + String customGranterRef = customGrantElement + .getAttribute("token-granter-ref"); tokenGranters.add(new RuntimeBeanReference(customGranterRef)); } } @@ -214,59 +248,87 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P approvalEndpointBean.getBeanDefinition()); if (!StringUtils.hasText(clientDetailsRef)) { - parserContext.getReaderContext().error("A client details service is mandatory", element); + parserContext.getReaderContext() + .error("A client details service is mandatory", element); } if (StringUtils.hasText(redirectStrategyRef)) { - authorizationEndpointBean.addPropertyReference("redirectStrategy", redirectStrategyRef); + authorizationEndpointBean.addPropertyReference("redirectStrategy", + redirectStrategyRef); } if (StringUtils.hasText(userApprovalHandlerRef)) { - authorizationEndpointBean.addPropertyReference("userApprovalHandler", userApprovalHandlerRef); + authorizationEndpointBean.addPropertyReference("userApprovalHandler", + userApprovalHandlerRef); } - authorizationEndpointBean.addPropertyReference("clientDetailsService", clientDetailsRef); + authorizationEndpointBean.addPropertyReference("clientDetailsService", + clientDetailsRef); if (StringUtils.hasText(redirectResolverRef)) { - authorizationEndpointBean.addPropertyReference("redirectResolver", redirectResolverRef); + authorizationEndpointBean.addPropertyReference("redirectResolver", + redirectResolverRef); } if (StringUtils.hasText(approvalPage)) { - authorizationEndpointBean.addPropertyValue("userApprovalPage", approvalPage); + authorizationEndpointBean.addPropertyValue("userApprovalPage", + approvalPage); } if (StringUtils.hasText(errorPage)) { authorizationEndpointBean.addPropertyValue("errorPage", errorPage); } - parserContext.getRegistry().registerBeanDefinition("oauth2AuthorizationEndpoint", + parserContext.getRegistry().registerBeanDefinition( + "oauth2AuthorizationEndpoint", authorizationEndpointBean.getBeanDefinition()); } // configure the token endpoint - BeanDefinitionBuilder tokenEndpointBean = BeanDefinitionBuilder.rootBeanDefinition(TokenEndpoint.class); + BeanDefinitionBuilder tokenEndpointBean = BeanDefinitionBuilder + .rootBeanDefinition(TokenEndpoint.class); tokenEndpointBean.addPropertyReference("clientDetailsService", clientDetailsRef); tokenEndpointBean.addPropertyReference("tokenGranter", tokenGranterRef); - authorizationEndpointBean.addPropertyReference("oAuth2RequestValidator", oAuth2RequestValidatorRef); - parserContext.getRegistry() - .registerBeanDefinition("oauth2TokenEndpoint", tokenEndpointBean.getBeanDefinition()); + authorizationEndpointBean.addPropertyReference("oAuth2RequestValidator", + oAuth2RequestValidatorRef); + parserContext.getRegistry().registerBeanDefinition("oauth2TokenEndpoint", + tokenEndpointBean.getBeanDefinition()); if (StringUtils.hasText(oAuth2RequestFactoryRef)) { - tokenEndpointBean.addPropertyReference("oAuth2RequestFactory", oAuth2RequestFactoryRef); + tokenEndpointBean.addPropertyReference("oAuth2RequestFactory", + oAuth2RequestFactoryRef); } if (StringUtils.hasText(oAuth2RequestValidatorRef)) { - tokenEndpointBean.addPropertyReference("oAuth2RequestValidator", oAuth2RequestValidatorRef); + tokenEndpointBean.addPropertyReference("oAuth2RequestValidator", + oAuth2RequestValidatorRef); + } + + if (StringUtils.hasText(enableCheckToken) && enableCheckToken.equals("true")) { + // configure the check token endpoint + BeanDefinitionBuilder checkTokenEndpointBean = BeanDefinitionBuilder + .rootBeanDefinition(CheckTokenEndpoint.class); + checkTokenEndpointBean.addConstructorArgReference(tokenServicesRef); + parserContext.getRegistry().registerBeanDefinition("oauth2CheckTokenEndpoint", + checkTokenEndpointBean.getBeanDefinition()); } // Register a handler mapping that can detect the auth server endpoints BeanDefinitionBuilder handlerMappingBean = BeanDefinitionBuilder .rootBeanDefinition(FrameworkEndpointHandlerMapping.class); - if (StringUtils.hasText(tokenEndpointUrl) || StringUtils.hasText(authorizationEndpointUrl)) { + if (StringUtils.hasText(tokenEndpointUrl) + || StringUtils.hasText(authorizationEndpointUrl)) { ManagedMap mappings = new ManagedMap(); if (StringUtils.hasText(tokenEndpointUrl)) { - mappings.put("/oauth/token", new TypedStringValue(tokenEndpointUrl, String.class)); + mappings.put("/oauth/token", + new TypedStringValue(tokenEndpointUrl, String.class)); } if (StringUtils.hasText(authorizationEndpointUrl)) { - mappings.put("/oauth/authorize", new TypedStringValue(authorizationEndpointUrl, String.class)); + mappings.put("/oauth/authorize", + new TypedStringValue(authorizationEndpointUrl, String.class)); } if (StringUtils.hasText(approvalPage)) { - mappings.put("/oauth/confirm_access", new TypedStringValue(approvalPage, String.class)); + mappings.put("/oauth/confirm_access", + new TypedStringValue(approvalPage, String.class)); + } + if (StringUtils.hasText(checkTokenUrl)) { + mappings.put("/oauth/check_token", + new TypedStringValue(checkTokenUrl, String.class)); } handlerMappingBean.addPropertyValue("mappings", mappings); } @@ -274,8 +336,8 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P if (!StringUtils.hasText(userApprovalHandlerRef)) { BeanDefinitionBuilder userApprovalHandler = BeanDefinitionBuilder .rootBeanDefinition(DefaultUserApprovalHandler.class); - userApprovalHandler.addPropertyValue("approvalParameter", new TypedStringValue(approvalParameter, - String.class)); + userApprovalHandler.addPropertyValue("approvalParameter", + new TypedStringValue(approvalParameter, String.class)); authorizationEndpointBean.addPropertyValue("userApprovalHandler", userApprovalHandler.getBeanDefinition()); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java index 149da89ef..fd86a3a19 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java @@ -22,7 +22,6 @@ import org.springframework.core.Ordered; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.security.oauth2.common.util.OAuth2Utils; -import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.util.StringUtils; import org.springframework.web.servlet.mvc.condition.NameValueExpression; import org.springframework.web.servlet.mvc.condition.ParamsRequestCondition; diff --git a/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-2.0.xsd b/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-2.0.xsd index 15c040592..6612efbb4 100644 --- a/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-2.0.xsd +++ b/spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-2.0.xsd @@ -309,7 +309,23 @@ - + + + + + Path for check token endpoint (defaults to /oauth/check_token). + + + + + + + + True if the check token endpoint is to be installed (must be separately protected). + + + + diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/AuthorizationServerBeanDefinitionParserTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/AuthorizationServerBeanDefinitionParserTests.java index f1c1f3c7d..aee1985ee 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/AuthorizationServerBeanDefinitionParserTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/AuthorizationServerBeanDefinitionParserTests.java @@ -44,6 +44,7 @@ public static List parameters() { return Arrays.asList(new Object[] { "authorization-server-vanilla" }, new Object[] { "authorization-server-extras" }, new Object[] { "authorization-server-types" }, + new Object[] { "authorization-server-check-token" }, new Object[] { "authorization-server-disable" }); } diff --git a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-check-token.xml b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-check-token.xml new file mode 100644 index 000000000..b9ee7595c --- /dev/null +++ b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-check-token.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + From fe645eb1e75b70b5f0851d663da28ae25de70a13 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 22 Oct 2015 15:57:56 +0100 Subject: [PATCH 454/831] Update samples to Boot 1.2.7 --- .../test/java/client/CombinedApplication.java | 75 +++++++------------ .../jdbc/src/main/java/demo/Application.java | 36 +++------ tests/annotation/pom.xml | 2 +- .../jdbc/src/main/java/demo/Application.java | 28 ++----- tests/xml/pom.xml | 2 +- 5 files changed, 44 insertions(+), 99 deletions(-) diff --git a/tests/annotation/client/src/test/java/client/CombinedApplication.java b/tests/annotation/client/src/test/java/client/CombinedApplication.java index 4b0892c17..107fd1a5b 100644 --- a/tests/annotation/client/src/test/java/client/CombinedApplication.java +++ b/tests/annotation/client/src/test/java/client/CombinedApplication.java @@ -14,20 +14,11 @@ import java.util.Arrays; import java.util.Collections; -import java.util.LinkedHashSet; import java.util.List; import java.util.Map; -import java.util.Set; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.security.SecurityProperties; -import org.springframework.boot.autoconfigure.security.SecurityProperties.User; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; @@ -38,21 +29,25 @@ import org.springframework.web.bind.annotation.RestController; /** - * Combined OAuth2 client and server app for testing. Normally it only makes sense for the client to be a separate app - * (otherwise it wouldn't need HTTP resources from the server because it could get them on local channels), but for - * testing we can fake it to make things easier to set up and run. Run this main method and visit http://localhost:8080: + * Combined OAuth2 client and server app for testing. Normally it only makes sense for the + * client to be a separate app (otherwise it wouldn't need HTTP resources from the server + * because it could get them on local channels), but for testing we can fake it to make + * things easier to set up and run. Run this main method and visit http://localhost:8080: * *
      *
    • Client doesn't have a token so redirects to auth server /oauth/authorize
    • *
    • Auth server prompts for authentication (username/password=user/password)
    • - *
    • Auth server prompts for approval of the token grant and redirects to client app
    • + *
    • Auth server prompts for approval of the token grant and redirects to client app + *
    • *
    • Client app obtains token in back channel /oauth/token
    • - *
    • Client app obtains content from protected resource /admin/beans (hard-coded content for the demo)
    • + *
    • Client app obtains content from protected resource /admin/beans (hard-coded content + * for the demo)
    • *
    • Client renders content
    • *
    * - * In this demo the client app is very basic (it just re-renders content it got from the resource server), but in a real - * app it can do whatever it likes with the resource content. + * In this demo the client app is very basic (it just re-renders content it got from the + * resource server), but in a real app it can do whatever it likes with the resource + * content. * * @author Dave Syer * @@ -62,27 +57,31 @@ public class CombinedApplication { public static void main(String[] args) { - new SpringApplicationBuilder(ClientApplication.class, CombinedApplication.class).profiles("combined").run(args); + new SpringApplicationBuilder(ClientApplication.class, CombinedApplication.class) + .profiles("combined").run(args); } @RequestMapping("/admin/beans") public List> beans() { - return Arrays.asList(Collections. singletonMap("message", "Hello World")); + return Arrays.asList( + Collections.singletonMap("message", "Hello World")); } @RequestMapping("/admin/info") public Map info() { - return Collections. emptyMap(); + return Collections.emptyMap(); } @Configuration @EnableAuthorizationServer - protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter { + protected static class AuthorizationServerConfiguration + extends AuthorizationServerConfigurerAdapter { @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { - clients.inMemory().withClient("my-trusted-client").authorizedGrantTypes("authorization_code") - .authorities("ROLE_CLIENT").scopes("read", "write").resourceIds("oauth2-resource"); + clients.inMemory().withClient("my-trusted-client") + .authorizedGrantTypes("authorization_code").authorities("ROLE_CLIENT") + .scopes("read", "write").resourceIds("oauth2-resource"); } @@ -90,37 +89,13 @@ public void configure(ClientDetailsServiceConfigurer clients) throws Exception { @Configuration @EnableResourceServer - protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { + protected static class ResourceServerConfiguration + extends ResourceServerConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { - http.antMatcher("/admin/beans").authorizeRequests().anyRequest().authenticated(); - } - - } - - @Configuration - protected static class AuthenticationConfigurerAdapter extends - GlobalAuthenticationConfigurerAdapter { - - private static Log logger = LogFactory - .getLog(AuthenticationConfigurerAdapter.class); - - @Autowired - private SecurityProperties security; - - @Override - public void init(AuthenticationManagerBuilder auth) throws Exception { - User user = this.security.getUser(); - if (user.isDefaultPassword()) { - logger.info("\n\nUsing default security password: " + user.getPassword() - + "\n"); - } - - Set roles = new LinkedHashSet(user.getRole()); - auth.inMemoryAuthentication().withUser(user.getName()) - .password(user.getPassword()) - .roles(roles.toArray(new String[roles.size()])); + http.antMatcher("/admin/beans").authorizeRequests().anyRequest() + .authenticated(); } } diff --git a/tests/annotation/jdbc/src/main/java/demo/Application.java b/tests/annotation/jdbc/src/main/java/demo/Application.java index 25de4cd05..1c6409ebe 100644 --- a/tests/annotation/jdbc/src/main/java/demo/Application.java +++ b/tests/annotation/jdbc/src/main/java/demo/Application.java @@ -7,11 +7,8 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.core.Ordered; -import org.springframework.core.annotation.Order; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; @@ -34,6 +31,9 @@ @RestController public class Application { + @Autowired + private DataSource dataSource; + public static void main(String[] args) { SpringApplication.run(Application.class, args); } @@ -45,8 +45,7 @@ public String home() { @Configuration @EnableResourceServer - protected static class ResourceServer extends - ResourceServerConfigurerAdapter { + protected static class ResourceServer extends ResourceServerConfigurerAdapter { @Autowired private TokenStore tokenStore; @@ -66,8 +65,7 @@ public void configure(HttpSecurity http) throws Exception { @Configuration @EnableAuthorizationServer - protected static class OAuth2Config extends - AuthorizationServerConfigurerAdapter { + protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter { @Autowired private AuthenticationManager auth; @@ -102,8 +100,7 @@ public void configure(AuthorizationServerEndpointsConfigurer endpoints) } @Override - public void configure(ClientDetailsServiceConfigurer clients) - throws Exception { + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { // @formatter:off clients.jdbc(dataSource) .passwordEncoder(passwordEncoder) @@ -128,27 +125,12 @@ public void configure(ClientDetailsServiceConfigurer clients) } - // Global authentication configuration ordered *after* the one in Spring - // Boot (so the settings here overwrite the ones in Boot). The explicit - // order is not needed in Spring Boot 1.2.3 or greater. (Actually with Boot - // 1.2.3 you don't need this inner class at all and you can just @Autowired - // the AuthenticationManagerBuilder). - @Configuration - @Order(Ordered.LOWEST_PRECEDENCE - 20) - protected static class AuthenticationManagerConfiguration extends - GlobalAuthenticationConfigurerAdapter { - - @Autowired - private DataSource dataSource; - - @Override - public void init(AuthenticationManagerBuilder auth) throws Exception { - // @formatter:off + @Autowired + public void init(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth.jdbcAuthentication().dataSource(dataSource).withUser("dave") .password("secret").roles("USER"); // @formatter:on - } - } } diff --git a/tests/annotation/pom.xml b/tests/annotation/pom.xml index 79b08b81f..9b7c9b2c2 100644 --- a/tests/annotation/pom.xml +++ b/tests/annotation/pom.xml @@ -27,7 +27,7 @@ org.springframework.boot spring-boot-starter-parent - 1.2.2.RELEASE + 1.2.7.RELEASE diff --git a/tests/xml/jdbc/src/main/java/demo/Application.java b/tests/xml/jdbc/src/main/java/demo/Application.java index c6d0dd26b..6910cde17 100644 --- a/tests/xml/jdbc/src/main/java/demo/Application.java +++ b/tests/xml/jdbc/src/main/java/demo/Application.java @@ -12,12 +12,10 @@ import org.springframework.boot.context.embedded.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.DependsOn; import org.springframework.context.annotation.ImportResource; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.http.SessionCreationPolicy; @@ -48,17 +46,17 @@ @ImportResource("classpath:/context.xml") public class Application { + + @Autowired + private DataSource dataSource; + + @Autowired + private SecurityProperties security; + public static void main(String[] args) { SpringApplication.run(Application.class, args); } - @Bean - @DependsOn("dataSourceInitializer") - // @DependsOn only works if it is on a @Bean, so we can't use an @Import here - protected AuthenticationManagerConfiguration authenticationManagerConfiguration() { - return new AuthenticationManagerConfiguration(); - } - @RequestMapping("/") public String home() { return "Hello World"; @@ -186,18 +184,7 @@ protected AuthenticationEntryPoint authenticationEntryPoint() { } -} - -@Order(Ordered.LOWEST_PRECEDENCE - 8) -class AuthenticationManagerConfiguration extends GlobalAuthenticationConfigurerAdapter { - @Autowired - private DataSource dataSource; - - @Autowired - private SecurityProperties security; - - @Override public void init(AuthenticationManagerBuilder auth) throws Exception { User user = security.getUser(); // @formatter:off @@ -207,4 +194,5 @@ public void init(AuthenticationManagerBuilder auth) throws Exception { .roles(user.getRole().toArray(new String[0])); // @formatter:on } + } diff --git a/tests/xml/pom.xml b/tests/xml/pom.xml index 0356ab53f..33411477b 100644 --- a/tests/xml/pom.xml +++ b/tests/xml/pom.xml @@ -24,7 +24,7 @@ org.springframework.boot spring-boot-starter-parent - 1.2.2.RELEASE + 1.2.7.RELEASE From b8603c0e644f8b979254fe88026a964ec6412d13 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 22 Oct 2015 16:24:08 +0100 Subject: [PATCH 455/831] Update to 2.0.8 --- pom.xml | 6 +++--- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- tests/annotation/approval/pom.xml | 2 +- tests/annotation/client/pom.xml | 2 +- tests/annotation/common/pom.xml | 2 +- tests/annotation/custom-grant/pom.xml | 2 +- tests/annotation/form/pom.xml | 2 +- tests/annotation/jaxb/pom.xml | 2 +- tests/annotation/jdbc/pom.xml | 2 +- tests/annotation/jwt/pom.xml | 2 +- tests/annotation/mappings/pom.xml | 2 +- tests/annotation/multi/pom.xml | 2 +- tests/annotation/pom.xml | 4 ++-- tests/annotation/resource/pom.xml | 2 +- tests/annotation/vanilla/pom.xml | 2 +- tests/pom.xml | 2 +- tests/xml/approval/pom.xml | 2 +- tests/xml/client/pom.xml | 2 +- tests/xml/common/pom.xml | 2 +- tests/xml/form/pom.xml | 2 +- tests/xml/jdbc/pom.xml | 2 +- tests/xml/jwt/pom.xml | 2 +- tests/xml/mappings/pom.xml | 2 +- tests/xml/pom.xml | 4 ++-- tests/xml/vanilla/pom.xml | 2 +- 31 files changed, 35 insertions(+), 35 deletions(-) diff --git a/pom.xml b/pom.xml index 0d0cec30c..476b4bdba 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.8.BUILD-SNAPSHOT + 2.0.8.RELEASE http://static.springframework.org/spring-security/oauth @@ -13,13 +13,13 @@ spring-security-oauth2 tests samples - spring-security-jwt + UTF-8 4.0.9.RELEASE - 3.2.7.RELEASE + 3.2.8.RELEASE 1.6 diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index 654448855..d1d0720bd 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.8.BUILD-SNAPSHOT + 2.0.8.RELEASE ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index efac5510e..21524f8d2 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.8.BUILD-SNAPSHOT + 2.0.8.RELEASE ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 2b898402c..a77586888 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.8.BUILD-SNAPSHOT + 2.0.8.RELEASE ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 71a659f70..a62d8f190 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.8.BUILD-SNAPSHOT + 2.0.8.RELEASE ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index be333228e..14e590be5 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.8.BUILD-SNAPSHOT + 2.0.8.RELEASE spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index 89de3901f..a39bd9c0f 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.8.BUILD-SNAPSHOT + 2.0.8.RELEASE spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 3e0c69468..7c9aa599f 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.8.BUILD-SNAPSHOT + 2.0.8.RELEASE spring-security-oauth2 diff --git a/tests/annotation/approval/pom.xml b/tests/annotation/approval/pom.xml index d9ee4c726..02da2777e 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.8.BUILD-SNAPSHOT + 2.0.8.RELEASE diff --git a/tests/annotation/client/pom.xml b/tests/annotation/client/pom.xml index a57241b0f..e577b8ad1 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.8.BUILD-SNAPSHOT + 2.0.8.RELEASE diff --git a/tests/annotation/common/pom.xml b/tests/annotation/common/pom.xml index fc908ef7a..7d09fc29f 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.8.BUILD-SNAPSHOT + 2.0.8.RELEASE diff --git a/tests/annotation/custom-grant/pom.xml b/tests/annotation/custom-grant/pom.xml index bd27e6e86..ba718e576 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.8.BUILD-SNAPSHOT + 2.0.8.RELEASE diff --git a/tests/annotation/form/pom.xml b/tests/annotation/form/pom.xml index 58afb0178..0fe4ccb45 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.8.BUILD-SNAPSHOT + 2.0.8.RELEASE diff --git a/tests/annotation/jaxb/pom.xml b/tests/annotation/jaxb/pom.xml index e2a64c384..49527a505 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.8.BUILD-SNAPSHOT + 2.0.8.RELEASE diff --git a/tests/annotation/jdbc/pom.xml b/tests/annotation/jdbc/pom.xml index 11421404d..2128feca9 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.8.BUILD-SNAPSHOT + 2.0.8.RELEASE diff --git a/tests/annotation/jwt/pom.xml b/tests/annotation/jwt/pom.xml index 195b3eb5d..8b65d9116 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.8.BUILD-SNAPSHOT + 2.0.8.RELEASE diff --git a/tests/annotation/mappings/pom.xml b/tests/annotation/mappings/pom.xml index b79255f06..0761ed36b 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.8.BUILD-SNAPSHOT + 2.0.8.RELEASE diff --git a/tests/annotation/multi/pom.xml b/tests/annotation/multi/pom.xml index ec2951674..30cd10615 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.8.BUILD-SNAPSHOT + 2.0.8.RELEASE diff --git a/tests/annotation/pom.xml b/tests/annotation/pom.xml index 9b7c9b2c2..f06c3b8ae 100644 --- a/tests/annotation/pom.xml +++ b/tests/annotation/pom.xml @@ -4,7 +4,7 @@ org.demo spring-oauth2-tests-parent - 2.0.8.BUILD-SNAPSHOT + 2.0.8.RELEASE pom @@ -36,7 +36,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.0.8.BUILD-SNAPSHOT + 2.0.8.RELEASE jackson-mapper-asl diff --git a/tests/annotation/resource/pom.xml b/tests/annotation/resource/pom.xml index c9baa8d60..fe659ca95 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.8.BUILD-SNAPSHOT + 2.0.8.RELEASE diff --git a/tests/annotation/vanilla/pom.xml b/tests/annotation/vanilla/pom.xml index 0b2917150..fef738ba2 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.8.BUILD-SNAPSHOT + 2.0.8.RELEASE diff --git a/tests/pom.xml b/tests/pom.xml index bf78635fe..52669edf1 100644 --- a/tests/pom.xml +++ b/tests/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.8.BUILD-SNAPSHOT + 2.0.8.RELEASE spring-security-oauth-tests diff --git a/tests/xml/approval/pom.xml b/tests/xml/approval/pom.xml index 943a9e35c..944961a4a 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.8.BUILD-SNAPSHOT + 2.0.8.RELEASE diff --git a/tests/xml/client/pom.xml b/tests/xml/client/pom.xml index 9c92383c4..cc2699725 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.8.BUILD-SNAPSHOT + 2.0.8.RELEASE diff --git a/tests/xml/common/pom.xml b/tests/xml/common/pom.xml index eb7a855bc..501c521e3 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.8.BUILD-SNAPSHOT + 2.0.8.RELEASE diff --git a/tests/xml/form/pom.xml b/tests/xml/form/pom.xml index 649558656..97affd0c3 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.8.BUILD-SNAPSHOT + 2.0.8.RELEASE diff --git a/tests/xml/jdbc/pom.xml b/tests/xml/jdbc/pom.xml index 546437f79..9761c1583 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.8.BUILD-SNAPSHOT + 2.0.8.RELEASE diff --git a/tests/xml/jwt/pom.xml b/tests/xml/jwt/pom.xml index 652c4ab3a..d1614665b 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.8.BUILD-SNAPSHOT + 2.0.8.RELEASE diff --git a/tests/xml/mappings/pom.xml b/tests/xml/mappings/pom.xml index bd3eb66f2..7189b3417 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.8.BUILD-SNAPSHOT + 2.0.8.RELEASE diff --git a/tests/xml/pom.xml b/tests/xml/pom.xml index 33411477b..b4302929c 100644 --- a/tests/xml/pom.xml +++ b/tests/xml/pom.xml @@ -4,7 +4,7 @@ org.demo spring-oauth2-tests-xml-parent - 2.0.8.BUILD-SNAPSHOT + 2.0.8.RELEASE pom @@ -33,7 +33,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.0.8.BUILD-SNAPSHOT + 2.0.8.RELEASE jackson-mapper-asl diff --git a/tests/xml/vanilla/pom.xml b/tests/xml/vanilla/pom.xml index 2a14e6289..7a6968214 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.8.BUILD-SNAPSHOT + 2.0.8.RELEASE From 37ed413a4c1cd14018b43156c4f76bbb9f9fd3c6 Mon Sep 17 00:00:00 2001 From: michaeltecourt Date: Wed, 21 Oct 2015 16:31:00 +0200 Subject: [PATCH 456/831] Allow custom authentication filters for the TokenEndpoint. These filters are added upstream of the traditional BasicAuthenticationFilter. Simple integration test project added, details in README.md. Fixes gh-601, fixes gh-602 --- ...AuthorizationServerSecurityConfigurer.java | 38 +++++++- .../custom-authentication/README.md | 3 + .../annotation/custom-authentication/pom.xml | 50 +++++++++++ .../src/main/java/demo/Application.java | 76 ++++++++++++++++ .../demo/HardCodedAuthenticationFilter.java | 64 ++++++++++++++ .../src/main/resources/application.yml | 11 +++ .../src/test/java/demo/ApplicationTests.java | 20 +++++ .../demo/ClientCredentialsProviderTests.java | 86 +++++++++++++++++++ tests/annotation/pom.xml | 1 + 9 files changed, 348 insertions(+), 1 deletion(-) create mode 100644 tests/annotation/custom-authentication/README.md create mode 100644 tests/annotation/custom-authentication/pom.xml create mode 100644 tests/annotation/custom-authentication/src/main/java/demo/Application.java create mode 100644 tests/annotation/custom-authentication/src/main/java/demo/HardCodedAuthenticationFilter.java create mode 100644 tests/annotation/custom-authentication/src/main/resources/application.yml create mode 100644 tests/annotation/custom-authentication/src/test/java/demo/ApplicationTests.java create mode 100644 tests/annotation/custom-authentication/src/test/java/demo/ClientCredentialsProviderTests.java diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java index 7b47d915d..dd23a5c37 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java @@ -15,7 +15,11 @@ */ package org.springframework.security.oauth2.config.annotation.web.configurers; +import java.util.ArrayList; import java.util.Collections; +import java.util.List; + +import javax.servlet.Filter; import org.springframework.http.MediaType; import org.springframework.security.authentication.AuthenticationManager; @@ -36,6 +40,7 @@ import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; import org.springframework.security.web.context.NullSecurityContextRepository; import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher; +import org.springframework.util.Assert; import org.springframework.util.StringUtils; import org.springframework.web.accept.ContentNegotiationStrategy; import org.springframework.web.accept.HeaderContentNegotiationStrategy; @@ -65,6 +70,12 @@ public final class AuthorizationServerSecurityConfigurer extends private boolean sslOnly = false; + /** + * Custom authentication filters for the TokenEndpoint. Filters will be set upstream of the default + * BasicAuthenticationFilter. + */ + private List tokenEndpointAuthenticationFilters = new ArrayList(); + public AuthorizationServerSecurityConfigurer sslOnly() { this.sslOnly = true; return this; @@ -172,8 +183,13 @@ public void configure(HttpSecurity http) throws Exception { if (allowFormAuthenticationForClients) { clientCredentialsTokenEndpointFilter(http); } + + for (Filter filter : tokenEndpointAuthenticationFilters) { + http.addFilterBefore(filter, BasicAuthenticationFilter.class); + } + http.exceptionHandling().accessDeniedHandler(accessDeniedHandler); - if (sslOnly ) { + if (sslOnly) { http.requiresChannel().anyRequest().requiresSecure(); } @@ -201,4 +217,24 @@ private FrameworkEndpointHandlerMapping frameworkEndpointHandlerMapping() { return getBuilder().getSharedObject(FrameworkEndpointHandlerMapping.class); } + /** + * Adds a new custom authentication filter for the TokenEndpoint. Filters will be set upstream of the default + * BasicAuthenticationFilter. + * + * @param filter + */ + public void addTokenEndpointAuthenticationFilter(Filter filter) { + this.tokenEndpointAuthenticationFilters.add(filter); + } + + /** + * Sets a new list of custom authentication filters for the TokenEndpoint. Filters will be set upstream of the + * default BasicAuthenticationFilter. + * + * @param filters The authentication filters to set. + */ + public void tokenEndpointAuthenticationFilters(List filters) { + Assert.notNull(filters, "Custom authentication filter list must not be null"); + this.tokenEndpointAuthenticationFilters = new ArrayList(filters); + } } diff --git a/tests/annotation/custom-authentication/README.md b/tests/annotation/custom-authentication/README.md new file mode 100644 index 000000000..c77c2b42e --- /dev/null +++ b/tests/annotation/custom-authentication/README.md @@ -0,0 +1,3 @@ +This project tests a basic authorization server configuration, with a custom authentication filter on the `TokenEndpoint`. +The authentication mechanism only authorizes one fixed client to pass. The client_id is taken from an HTTP parameter. + diff --git a/tests/annotation/custom-authentication/pom.xml b/tests/annotation/custom-authentication/pom.xml new file mode 100644 index 000000000..d7dc6c975 --- /dev/null +++ b/tests/annotation/custom-authentication/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + + spring-oauth2-tests-custom-authentication + + spring-oauth2-tests-custom-authentication + Demo project + + + org.demo + spring-oauth2-tests-parent + 2.0.8.RELEASE + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.security.oauth + spring-security-oauth2 + + + org.demo + spring-oauth2-tests-common + ${project.version} + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/tests/annotation/custom-authentication/src/main/java/demo/Application.java b/tests/annotation/custom-authentication/src/main/java/demo/Application.java new file mode 100644 index 000000000..8566b7eb1 --- /dev/null +++ b/tests/annotation/custom-authentication/src/main/java/demo/Application.java @@ -0,0 +1,76 @@ +package demo; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpStatus; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; +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.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; +import org.springframework.util.MultiValueMap; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +@Configuration +@EnableAutoConfiguration +@EnableResourceServer +@RestController +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + @RequestMapping("/") + public String home() { + return "Hello World"; + } + + @RequestMapping(value = "/", method = RequestMethod.POST) + @ResponseStatus(HttpStatus.CREATED) + public String create(@RequestBody MultiValueMap map) { + return "OK"; + } + + @Configuration + @EnableAuthorizationServer + protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter { + + @Autowired + private AuthenticationManager authenticationManager; + + @Override + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + endpoints.authenticationManager(authenticationManager); + } + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + // @formatter:off + clients.inMemory().withClient("my-trusted-client") + .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit") + .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT").scopes("read", "write", "trust") + .resourceIds("oauth2-resource").accessTokenValiditySeconds(600).and() + .withClient("my-client-with-registered-redirect").authorizedGrantTypes("authorization_code") + .authorities("ROLE_CLIENT").scopes("read", "trust").resourceIds("oauth2-resource") + .redirectUris("http://anywhere/?key=value").and().withClient("my-client-with-secret") + .authorizedGrantTypes("client_credentials", "password").authorities("ROLE_CLIENT").scopes("read") + .resourceIds("oauth2-resource").secret("secret"); + // @formatter:on + } + + @Override + public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { + security.addTokenEndpointAuthenticationFilter(new HardCodedAuthenticationFilter()); + } + } + +} diff --git a/tests/annotation/custom-authentication/src/main/java/demo/HardCodedAuthenticationFilter.java b/tests/annotation/custom-authentication/src/main/java/demo/HardCodedAuthenticationFilter.java new file mode 100644 index 000000000..3dcdfa694 --- /dev/null +++ b/tests/annotation/custom-authentication/src/main/java/demo/HardCodedAuthenticationFilter.java @@ -0,0 +1,64 @@ +package demo; + +import java.io.IOException; +import java.util.List; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.oauth2.common.util.OAuth2Utils; + +/** + * Authentication filter that would only authenticate one client, using the + * "client_id" parameter. + * + * @author mtecourt + * + */ +public class HardCodedAuthenticationFilter implements Filter { + + private static final String AUTHORIZED_CLIENT_ID = "my-client-with-secret"; + private static final List CLIENT_AUTHORITIES = AuthorityUtils + .commaSeparatedStringToAuthorityList("ROLE_CLIENT"); + + private static final Logger LOGGER = LoggerFactory.getLogger("CustomAuthenticationFilter"); + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + // NOPE + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, + ServletException { + + String clientId = request.getParameter(OAuth2Utils.CLIENT_ID); + + if (AUTHORIZED_CLIENT_ID.equals(clientId)) { + UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( + AUTHORIZED_CLIENT_ID, "", CLIENT_AUTHORITIES); + SecurityContextHolder.getContext().setAuthentication(authentication); + LOGGER.info("Just authenticated : {}", clientId); + } else { + LOGGER.info("Did NOT authenticate : {}", clientId); + } + + chain.doFilter(request, response); + } + + @Override + public void destroy() { + // NOPE + } + +} diff --git a/tests/annotation/custom-authentication/src/main/resources/application.yml b/tests/annotation/custom-authentication/src/main/resources/application.yml new file mode 100644 index 000000000..ccf06f8ba --- /dev/null +++ b/tests/annotation/custom-authentication/src/main/resources/application.yml @@ -0,0 +1,11 @@ +spring: + application: + name: vanilla +management: + context_path: /admin +security: + user: + password: password +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 new file mode 100644 index 000000000..15eca8da6 --- /dev/null +++ b/tests/annotation/custom-authentication/src/test/java/demo/ApplicationTests.java @@ -0,0 +1,20 @@ +package demo; + +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; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = Application.class) +@WebAppConfiguration +@IntegrationTest("server.port=0") +public class ApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/tests/annotation/custom-authentication/src/test/java/demo/ClientCredentialsProviderTests.java b/tests/annotation/custom-authentication/src/test/java/demo/ClientCredentialsProviderTests.java new file mode 100644 index 000000000..f4dd6da46 --- /dev/null +++ b/tests/annotation/custom-authentication/src/test/java/demo/ClientCredentialsProviderTests.java @@ -0,0 +1,86 @@ +package demo; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +import java.net.URI; +import java.util.Map; + +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; +import org.springframework.http.MediaType; +import org.springframework.http.RequestEntity; +import org.springframework.http.ResponseEntity; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.HttpStatusCodeException; +import org.springframework.web.client.RestTemplate; + +import sparklr.common.AbstractClientCredentialsProviderTests; + +/** + * Integration tests using the {@link HardCodedAuthenticationFilter}. + * + * One client should be able to use the token endpoint /oauth/token by only providing its client_id as a parameter. + * + * @author michaeltecourt + */ +@SpringApplicationConfiguration(classes = Application.class) +public class ClientCredentialsProviderTests extends AbstractClientCredentialsProviderTests { + + protected URI tokenUri; + + @Before + public void setUp() { + tokenUri = URI.create(http.getUrl("/oauth/token")); + } + + /** + * No Basic authentication provided, only the hard coded client_id. + */ + @Test + @SuppressWarnings({ "unchecked", "rawtypes" }) + public void testHardCodedAuthenticationFineClient() { + + RestTemplate restTemplate = new RestTemplate(); + MultiValueMap params = new LinkedMultiValueMap(); + params.add("grant_type", "client_credentials"); + params.add("client_id", "my-client-with-secret"); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + RequestEntity> req = new RequestEntity>(params, + headers, HttpMethod.POST, tokenUri); + + ResponseEntity response = restTemplate.exchange(req, Map.class); + assertEquals(HttpStatus.OK, response.getStatusCode()); + Map body = response.getBody(); + String accessToken = body.get("access_token"); + assertNotNull(accessToken); + } + + @Test + public void testHardCodedAuthenticationWrongClient() { + + RestTemplate restTemplate = new RestTemplate(); + MultiValueMap params = new LinkedMultiValueMap(); + params.add("grant_type", "client_credentials"); + params.add("client_id", "my-trusted-client"); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + RequestEntity> req = new RequestEntity>(params, + headers, HttpMethod.POST, tokenUri); + + try { + restTemplate.exchange(req, Map.class); + fail("Expected HTTP 401"); + } + catch (HttpStatusCodeException e) { + assertEquals(HttpStatus.UNAUTHORIZED, e.getStatusCode()); + } + } +} diff --git a/tests/annotation/pom.xml b/tests/annotation/pom.xml index f06c3b8ae..a75225a63 100644 --- a/tests/annotation/pom.xml +++ b/tests/annotation/pom.xml @@ -19,6 +19,7 @@ multi client resource + custom-authentication spring-oauth2-tests From 00afb535ce8736f26a2ac270fabb8dc62943b0cb Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 22 Oct 2015 17:08:17 +0100 Subject: [PATCH 457/831] Switch back to snapshots for 2.0.9 --- pom.xml | 2 +- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- tests/annotation/approval/pom.xml | 2 +- tests/annotation/client/pom.xml | 2 +- tests/annotation/common/pom.xml | 2 +- tests/annotation/custom-authentication/pom.xml | 2 +- tests/annotation/custom-grant/pom.xml | 2 +- tests/annotation/form/pom.xml | 2 +- tests/annotation/jaxb/pom.xml | 2 +- tests/annotation/jdbc/pom.xml | 2 +- tests/annotation/jwt/pom.xml | 2 +- tests/annotation/mappings/pom.xml | 2 +- tests/annotation/multi/pom.xml | 2 +- tests/annotation/pom.xml | 4 ++-- tests/annotation/resource/pom.xml | 2 +- tests/annotation/vanilla/pom.xml | 2 +- tests/pom.xml | 2 +- tests/xml/approval/pom.xml | 2 +- tests/xml/client/pom.xml | 2 +- tests/xml/common/pom.xml | 2 +- tests/xml/form/pom.xml | 2 +- tests/xml/jdbc/pom.xml | 2 +- tests/xml/jwt/pom.xml | 2 +- tests/xml/mappings/pom.xml | 2 +- tests/xml/pom.xml | 4 ++-- tests/xml/vanilla/pom.xml | 2 +- 32 files changed, 34 insertions(+), 34 deletions(-) diff --git a/pom.xml b/pom.xml index 476b4bdba..eff4c2115 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.8.RELEASE + 2.0.9.BUILD-SNAPSHOT http://static.springframework.org/spring-security/oauth diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index d1d0720bd..fb3918581 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.8.RELEASE + 2.0.9.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index 21524f8d2..141bb54ba 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.8.RELEASE + 2.0.9.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index a77586888..01951b994 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.8.RELEASE + 2.0.9.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index a62d8f190..89a3529b2 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.8.RELEASE + 2.0.9.BUILD-SNAPSHOT ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index 14e590be5..f76a5d850 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.8.RELEASE + 2.0.9.BUILD-SNAPSHOT spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index a39bd9c0f..1824ba843 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.8.RELEASE + 2.0.9.BUILD-SNAPSHOT spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 7c9aa599f..0536932fc 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.8.RELEASE + 2.0.9.BUILD-SNAPSHOT spring-security-oauth2 diff --git a/tests/annotation/approval/pom.xml b/tests/annotation/approval/pom.xml index 02da2777e..76f9c630a 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.8.RELEASE + 2.0.9.BUILD-SNAPSHOT diff --git a/tests/annotation/client/pom.xml b/tests/annotation/client/pom.xml index e577b8ad1..086583416 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.8.RELEASE + 2.0.9.BUILD-SNAPSHOT diff --git a/tests/annotation/common/pom.xml b/tests/annotation/common/pom.xml index 7d09fc29f..df367fae0 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.8.RELEASE + 2.0.9.BUILD-SNAPSHOT diff --git a/tests/annotation/custom-authentication/pom.xml b/tests/annotation/custom-authentication/pom.xml index d7dc6c975..810d0a2b6 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.8.RELEASE + 2.0.9.BUILD-SNAPSHOT diff --git a/tests/annotation/custom-grant/pom.xml b/tests/annotation/custom-grant/pom.xml index ba718e576..168acb622 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.8.RELEASE + 2.0.9.BUILD-SNAPSHOT diff --git a/tests/annotation/form/pom.xml b/tests/annotation/form/pom.xml index 0fe4ccb45..92f673f4e 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.8.RELEASE + 2.0.9.BUILD-SNAPSHOT diff --git a/tests/annotation/jaxb/pom.xml b/tests/annotation/jaxb/pom.xml index 49527a505..51d97f247 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.8.RELEASE + 2.0.9.BUILD-SNAPSHOT diff --git a/tests/annotation/jdbc/pom.xml b/tests/annotation/jdbc/pom.xml index 2128feca9..bcc39fa78 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.8.RELEASE + 2.0.9.BUILD-SNAPSHOT diff --git a/tests/annotation/jwt/pom.xml b/tests/annotation/jwt/pom.xml index 8b65d9116..2add51a6a 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.8.RELEASE + 2.0.9.BUILD-SNAPSHOT diff --git a/tests/annotation/mappings/pom.xml b/tests/annotation/mappings/pom.xml index 0761ed36b..4a6d85548 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.8.RELEASE + 2.0.9.BUILD-SNAPSHOT diff --git a/tests/annotation/multi/pom.xml b/tests/annotation/multi/pom.xml index 30cd10615..377f01615 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.8.RELEASE + 2.0.9.BUILD-SNAPSHOT diff --git a/tests/annotation/pom.xml b/tests/annotation/pom.xml index a75225a63..cc403f8c6 100644 --- a/tests/annotation/pom.xml +++ b/tests/annotation/pom.xml @@ -4,7 +4,7 @@ org.demo spring-oauth2-tests-parent - 2.0.8.RELEASE + 2.0.9.BUILD-SNAPSHOT pom @@ -37,7 +37,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.0.8.RELEASE + 2.0.9.BUILD-SNAPSHOT jackson-mapper-asl diff --git a/tests/annotation/resource/pom.xml b/tests/annotation/resource/pom.xml index fe659ca95..4d8be5b03 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.8.RELEASE + 2.0.9.BUILD-SNAPSHOT diff --git a/tests/annotation/vanilla/pom.xml b/tests/annotation/vanilla/pom.xml index fef738ba2..8deef724c 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.8.RELEASE + 2.0.9.BUILD-SNAPSHOT diff --git a/tests/pom.xml b/tests/pom.xml index 52669edf1..58abba778 100644 --- a/tests/pom.xml +++ b/tests/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.0.8.RELEASE + 2.0.9.BUILD-SNAPSHOT spring-security-oauth-tests diff --git a/tests/xml/approval/pom.xml b/tests/xml/approval/pom.xml index 944961a4a..393af8831 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.8.RELEASE + 2.0.9.BUILD-SNAPSHOT diff --git a/tests/xml/client/pom.xml b/tests/xml/client/pom.xml index cc2699725..d4f244370 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.8.RELEASE + 2.0.9.BUILD-SNAPSHOT diff --git a/tests/xml/common/pom.xml b/tests/xml/common/pom.xml index 501c521e3..48158ab07 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.8.RELEASE + 2.0.9.BUILD-SNAPSHOT diff --git a/tests/xml/form/pom.xml b/tests/xml/form/pom.xml index 97affd0c3..62dda951b 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.8.RELEASE + 2.0.9.BUILD-SNAPSHOT diff --git a/tests/xml/jdbc/pom.xml b/tests/xml/jdbc/pom.xml index 9761c1583..9f0936364 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.8.RELEASE + 2.0.9.BUILD-SNAPSHOT diff --git a/tests/xml/jwt/pom.xml b/tests/xml/jwt/pom.xml index d1614665b..889450c45 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.8.RELEASE + 2.0.9.BUILD-SNAPSHOT diff --git a/tests/xml/mappings/pom.xml b/tests/xml/mappings/pom.xml index 7189b3417..701569788 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.8.RELEASE + 2.0.9.BUILD-SNAPSHOT diff --git a/tests/xml/pom.xml b/tests/xml/pom.xml index b4302929c..a62729761 100644 --- a/tests/xml/pom.xml +++ b/tests/xml/pom.xml @@ -4,7 +4,7 @@ org.demo spring-oauth2-tests-xml-parent - 2.0.8.RELEASE + 2.0.9.BUILD-SNAPSHOT pom @@ -33,7 +33,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.0.8.RELEASE + 2.0.9.BUILD-SNAPSHOT jackson-mapper-asl diff --git a/tests/xml/vanilla/pom.xml b/tests/xml/vanilla/pom.xml index 7a6968214..6e2483d17 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.8.RELEASE + 2.0.9.BUILD-SNAPSHOT From 3425e1d534b0cdee5a3c060abcc0233fbe74d4f7 Mon Sep 17 00:00:00 2001 From: michaeltecourt Date: Thu, 19 Nov 2015 10:43:43 +0100 Subject: [PATCH 458/831] WhiteLabelErrorEndpoint XSS vulnerability fix Some OAuth2Exceptions may contain client input (invalid grant types, etc), and need to be escaped before getting rendered by the default error endpoint. * Add HTML escaping for OAuth2Exception errors * Other type of "error" objects result in a default message (SpEL ${error.summary} was not going to work anyway) * Unit test Fixes gh-635, fixes gh-636 --- .../endpoint/WhitelabelErrorEndpoint.java | 23 ++++++++++++------- .../WhitelabelErrorEndpointTests.java | 11 ++++++++- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelErrorEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelErrorEndpoint.java index 5c0fb2b59..08bfb61e5 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelErrorEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelErrorEndpoint.java @@ -1,33 +1,40 @@ package org.springframework.security.oauth2.provider.endpoint; -import java.util.Collections; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; +import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.util.HtmlUtils; /** * Controller for displaying the error page for the authorization server. - * + * * @author Dave Syer */ @FrameworkEndpoint public class WhitelabelErrorEndpoint { + private static final String ERROR = "

    OAuth Error

    ${errorSummary}

    "; + @RequestMapping("/oauth/error") public ModelAndView handleError(HttpServletRequest request) { Map model = new HashMap(); Object error = request.getAttribute("error"); - if (error==null) { - error = Collections.singletonMap("summary", "Unknown error"); + // The error summary may contain malicious user input, + // it needs to be escaped to prevent XSS + String errorSummary; + if (error instanceof OAuth2Exception) { + OAuth2Exception oauthError = (OAuth2Exception) error; + errorSummary = HtmlUtils.htmlEscape(oauthError.getSummary()); + } + else { + errorSummary = "Unknown error"; } - model.put("error", error); + model.put("errorSummary", errorSummary); return new ModelAndView(new SpelView(ERROR), model); } - - private static String ERROR = "

    OAuth Error

    ${error.summary}

    "; - } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelErrorEndpointTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelErrorEndpointTests.java index 13a628e5a..722ec5e0c 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelErrorEndpointTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelErrorEndpointTests.java @@ -14,12 +14,13 @@ package org.springframework.security.oauth2.provider.endpoint; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; import org.junit.Test; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.security.oauth2.common.exceptions.InvalidClientException; +import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; import org.springframework.web.servlet.ModelAndView; /** @@ -53,4 +54,12 @@ public void testErrorPageNoError() throws Exception { assertTrue("Wrong content: " + content, content.contains("Unknown")); } + @Test + public void testErrorPageXSS() throws Exception { + request.setAttribute("error", new InvalidGrantException("Invalid grant : ")); + ModelAndView result = endpoint.handleError(request); + result.getView().render(result.getModel(), request, response); + String content = response.getContentAsString(); + assertFalse("Wrong content : " + content, content.contains(" - - - @@ -48,9 +37,22 @@

    Your Photos

    -

    - +

    +

    From a06049ed41a2cac993aa068c899cf03ff2d03910 Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Mon, 16 Jan 2017 12:26:43 -0500 Subject: [PATCH 557/831] Provide default impl ResourceServerConfigurerAdapter.configure(http) Fixes gh-948 --- .../web/configuration/ResourceServerConfigurerAdapter.java | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurerAdapter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurerAdapter.java index 6de516caa..1ab229281 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurerAdapter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurerAdapter.java @@ -27,6 +27,7 @@ public void configure(ResourceServerSecurityConfigurer resources) throws Excepti @Override public void configure(HttpSecurity http) throws Exception { + http.authorizeRequests().anyRequest().authenticated(); } } From 6abfce20a70969873333ecde27684aab3afca64d Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Mon, 16 Jan 2017 15:13:07 -0500 Subject: [PATCH 558/831] Bump spring-security 3.2.8.RELEASE -> 3.2.10.RELEASE Fixes gh-945 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7788c1181..3d5e79f56 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ UTF-8 1.9 4.0.9.RELEASE - 3.2.8.RELEASE + 3.2.10.RELEASE 1.6
    From f66a16581f860354cb5323cc4af4eaf781edf3ba Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Mon, 13 Feb 2017 15:16:13 -0500 Subject: [PATCH 559/831] Add TokenStore supporting Jwk verification Fixes gh-271 --- .../token/store/jwk/JwkAttributes.java | 35 ++++ .../token/store/jwk/JwkDefinition.java | 168 ++++++++++++++++++ .../token/store/jwk/JwkDefinitionSource.java | 117 ++++++++++++ .../token/store/jwk/JwkException.java | 42 +++++ .../token/store/jwk/JwkSetConverter.java | 144 +++++++++++++++ .../token/store/jwk/JwkTokenStore.java | 109 ++++++++++++ .../JwkVerifyingJwtAccessTokenConverter.java | 91 ++++++++++ .../token/store/jwk/JwtHeaderConverter.java | 68 +++++++ .../token/store/jwk/RSAJwkDefinition.java | 43 +++++ 9 files changed, 817 insertions(+) create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkAttributes.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkDefinition.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkDefinitionSource.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkException.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkSetConverter.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkTokenStore.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkVerifyingJwtAccessTokenConverter.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwtHeaderConverter.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/RSAJwkDefinition.java 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..72769bbc0 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkAttributes.java @@ -0,0 +1,35 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.security.oauth2.provider.token.store.jwk; + +/** + * @author Joe Grandja + */ +final class JwkAttributes { + static final String KEY_ID = "kid"; + + static final String KEY_TYPE = "kty"; + + static final String ALGORITHM = "alg"; + + static final String PUBLIC_KEY_USE = "use"; + + static final String RSA_PUBLIC_KEY_MODULUS = "n"; + + static final String RSA_PUBLIC_KEY_EXPONENT = "e"; + + 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..93caa5a5c --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkDefinition.java @@ -0,0 +1,168 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.security.oauth2.provider.token.store.jwk; + +/** + * @author Joe Grandja + */ +abstract class JwkDefinition { + private final String keyId; + private final KeyType keyType; + private final PublicKeyUse publicKeyUse; + private final CryptoAlgorithm algorithm; + + protected JwkDefinition(String keyId, + KeyType keyType, + PublicKeyUse publicKeyUse, + CryptoAlgorithm algorithm) { + this.keyId = keyId; + this.keyType = keyType; + this.publicKeyUse = publicKeyUse; + this.algorithm = algorithm; + } + + String getKeyId() { + return this.keyId; + } + + KeyType getKeyType() { + return this.keyType; + } + + PublicKeyUse getPublicKeyUse() { + return this.publicKeyUse; + } + + 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; + } + + 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; + } + } + + 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; + } + } + + enum CryptoAlgorithm { + RS256("SHA256withRSA", "RS256", "RSASSA-PKCS1-v1_5 using SHA-256"), + RS384("SHA384withRSA", "RS384", "RSASSA-PKCS1-v1_5 using SHA-384"), + RS512("SHA512withRSA", "RS512", "RSASSA-PKCS1-v1_5 using SHA-512"); + + private final String standardName; // JCA Standard Name + private final String headerParamValue; + private final String description; + + CryptoAlgorithm(String standardName, String headerParamValue, String description) { + this.standardName = standardName; + this.headerParamValue = headerParamValue; + this.description = description; + } + + String standardName() { + return this.standardName; + } + + String headerParamValue() { + return this.headerParamValue; + } + + String description() { + return this.description; + } + + static CryptoAlgorithm fromStandardName(String standardName) { + CryptoAlgorithm result = null; + for (CryptoAlgorithm algorithm : values()) { + if (algorithm.standardName().equals(standardName)) { + 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..a9f241f92 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkDefinitionSource.java @@ -0,0 +1,117 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.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.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.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; + +/** + * @author Joe Grandja + */ +class JwkDefinitionSource { + private final URL jwkSetUrl; + private final JwkSetConverter jwkSetConverter = new JwkSetConverter(); + private final AtomicReference> jwkDefinitions = + new AtomicReference>(new HashMap()); + + JwkDefinitionSource(String jwkSetUrl) { + try { + this.jwkSetUrl = new URL(jwkSetUrl); + } catch (MalformedURLException ex) { + throw new IllegalArgumentException("Invalid JWK Set URL: " + ex.getMessage(), ex); + } + } + + JwkDefinition getDefinition(String keyId) { + JwkDefinition result = null; + for (JwkDefinition jwkDefinition : this.jwkDefinitions.get().keySet()) { + if (jwkDefinition.getKeyId().equals(keyId)) { + result = jwkDefinition; + break; + } + } + return result; + } + + JwkDefinition getDefinitionRefreshIfNecessary(String keyId) { + JwkDefinition result = this.getDefinition(keyId); + if (result != null) { + return result; + } + this.refreshJwkDefinitions(); + return this.getDefinition(keyId); + } + + SignatureVerifier getVerifier(String keyId) { + SignatureVerifier result = null; + JwkDefinition jwkDefinition = this.getDefinitionRefreshIfNecessary(keyId); + if (jwkDefinition != null) { + result = this.jwkDefinitions.get().get(jwkDefinition); + } + return result; + } + + private void refreshJwkDefinitions() { + Set jwkDefinitionSet; + try { + jwkDefinitionSet = this.jwkSetConverter.convert(this.jwkSetUrl.openStream()); + } catch (IOException ex) { + throw new JwkException("An I/O error occurred while refreshing the JWK Set: " + ex.getMessage(), ex); + } + + Map refreshedJwkDefinitions = new LinkedHashMap(); + + for (JwkDefinition jwkDefinition : jwkDefinitionSet) { + if (JwkDefinition.KeyType.RSA.equals(jwkDefinition.getKeyType())) { + refreshedJwkDefinitions.put(jwkDefinition, this.createRSAVerifier((RSAJwkDefinition)jwkDefinition)); + } + } + + this.jwkDefinitions.set(refreshedJwkDefinitions); + } + + private 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; + } +} 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..f9a5e0032 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkException.java @@ -0,0 +1,42 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.security.oauth2.provider.token.store.jwk; + +import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; + +/** + * @author Joe Grandja + */ +public class JwkException extends OAuth2Exception { + + public JwkException(String message) { + super(message); + } + + public JwkException(String message, Throwable cause) { + super(message, cause); + } + + @Override + public String getOAuth2ErrorCode() { + return "server_error"; + } + + @Override + public int getHttpErrorCode() { + return 500; + } +} \ 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..1b6964adb --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkSetConverter.java @@ -0,0 +1,144 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.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.*; + + +/** + * @author Joe Grandja + */ +class JwkSetConverter implements Converter> { + private final JsonFactory factory = new JsonFactory(); + + @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; + } + + 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."); + } + + return this.createRSAJwkDefinition(attributes); + } + + 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.fromStandardName(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..cbfd1696f --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkTokenStore.java @@ -0,0 +1,109 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.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.JwtTokenStore; +import org.springframework.util.Assert; + +import java.util.Collection; + +/** + * @author Joe Grandja + */ +public class JwkTokenStore implements TokenStore { + private final JwtTokenStore delegate; + + 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); + } + + @Override + public OAuth2Authentication readAuthentication(OAuth2AccessToken token) { + return this.delegate.readAuthentication(token); + } + + @Override + public OAuth2Authentication readAuthentication(String token) { + return this.delegate.readAuthentication(token); + } + + @Override + public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) { + throw this.operationNotSupported(); + } + + @Override + public OAuth2AccessToken readAccessToken(String tokenValue) { + return this.delegate.readAccessToken(tokenValue); + } + + @Override + public void removeAccessToken(OAuth2AccessToken token) { + throw this.operationNotSupported(); + } + + @Override + public void storeRefreshToken(OAuth2RefreshToken refreshToken, OAuth2Authentication authentication) { + throw this.operationNotSupported(); + } + + @Override + public OAuth2RefreshToken readRefreshToken(String tokenValue) { + throw this.operationNotSupported(); + } + + @Override + public OAuth2Authentication readAuthenticationForRefreshToken(OAuth2RefreshToken token) { + throw this.operationNotSupported(); + } + + @Override + public void removeRefreshToken(OAuth2RefreshToken token) { + throw this.operationNotSupported(); + } + + @Override + public void removeAccessTokenUsingRefreshToken(OAuth2RefreshToken refreshToken) { + throw this.operationNotSupported(); + } + + @Override + public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) { + throw this.operationNotSupported(); + } + + @Override + public Collection findTokensByClientIdAndUserName(String clientId, String userName) { + throw this.operationNotSupported(); + } + + @Override + public Collection findTokensByClientId(String clientId) { + throw this.operationNotSupported(); + } + + private JwkException operationNotSupported() { + return new JwkException("This operation is currently 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..dc7ea2606 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkVerifyingJwtAccessTokenConverter.java @@ -0,0 +1,91 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.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.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; + +/** + * @author Joe Grandja + */ +class JwkVerifyingJwtAccessTokenConverter extends JwtAccessTokenConverter { + private final JwkDefinitionSource jwkDefinitionSource; + private final JwtHeaderConverter jwtHeaderConverter = new JwtHeaderConverter(); + private final JsonParser jsonParser = JsonParserFactory.create(); + + JwkVerifyingJwtAccessTokenConverter(JwkDefinitionSource jwkDefinitionSource) { + this.jwkDefinitionSource = jwkDefinitionSource; + } + + @Override + protected Map decode(String token) { + try { + Map headers = this.jwtHeaderConverter.convert(token); + + // Validate "kid" header + String keyIdHeader = headers.get(KEY_ID); + if (keyIdHeader == null) { + throw new JwkException("Invalid JWT/JWS: \"" + KEY_ID + "\" is a required JOSE Header."); + } + JwkDefinition jwkDefinition = this.jwkDefinitionSource.getDefinitionRefreshIfNecessary(keyIdHeader); + if (jwkDefinition == null) { + throw new JwkException("Invalid JOSE Header \"" + KEY_ID + "\" (" + keyIdHeader + ")"); + } + + // Validate "alg" header + String algorithmHeader = headers.get(ALGORITHM); + if (algorithmHeader == null) { + throw new JwkException("Invalid JWT/JWS: \"" + ALGORITHM + "\" is a required JOSE Header."); + } + if (!algorithmHeader.equals(jwkDefinition.getAlgorithm().headerParamValue())) { + throw new JwkException("Invalid JOSE Header \"" + ALGORITHM + "\" (" + algorithmHeader + ")" + + " does not match algorithm associated 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; + + } catch (Exception ex) { + throw new JwkException("Failed to decode/verify the JWT/JWS: " + ex.getMessage(), ex); + } + } + + @Override + protected String encode(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { + throw new JwkException("JWT/JWS (signing) is currently 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..2afa65a8d --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwtHeaderConverter.java @@ -0,0 +1,68 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.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 java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +/** + * @author Joe Grandja + */ +class JwtHeaderConverter implements Converter> { + private final JsonFactory factory = new JsonFactory(); + + @Override + public Map convert(String token) { + Map headers; + + int headerEndIndex = token.indexOf('.'); + if (headerEndIndex == -1) { + throw new JwkException("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 JwkException("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..ef8d1d06e --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/RSAJwkDefinition.java @@ -0,0 +1,43 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.security.oauth2.provider.token.store.jwk; + +/** + * @author Joe Grandja + */ +final class RSAJwkDefinition extends JwkDefinition { + private final String modulus; + private final String exponent; + + RSAJwkDefinition(String keyId, + JwkDefinition.PublicKeyUse publicKeyUse, + JwkDefinition.CryptoAlgorithm algorithm, + String modulus, + String exponent) { + + super(keyId, JwkDefinition.KeyType.RSA, publicKeyUse, algorithm); + this.modulus = modulus; + this.exponent = exponent; + } + + String getModulus() { + return this.modulus; + } + + String getExponent() { + return this.exponent; + } +} \ No newline at end of file From 4f65bf48091cebca4a4d3a7f222f7d89a86bbd55 Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Mon, 13 Feb 2017 16:08:22 -0500 Subject: [PATCH 560/831] Revert "Add TokenStore supporting Jwk verification" This reverts commit f66a16581f860354cb5323cc4af4eaf781edf3ba. --- .../token/store/jwk/JwkAttributes.java | 35 ---- .../token/store/jwk/JwkDefinition.java | 168 ------------------ .../token/store/jwk/JwkDefinitionSource.java | 117 ------------ .../token/store/jwk/JwkException.java | 42 ----- .../token/store/jwk/JwkSetConverter.java | 144 --------------- .../token/store/jwk/JwkTokenStore.java | 109 ------------ .../JwkVerifyingJwtAccessTokenConverter.java | 91 ---------- .../token/store/jwk/JwtHeaderConverter.java | 68 ------- .../token/store/jwk/RSAJwkDefinition.java | 43 ----- 9 files changed, 817 deletions(-) delete mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkAttributes.java delete mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkDefinition.java delete mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkDefinitionSource.java delete mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkException.java delete mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkSetConverter.java delete mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkTokenStore.java delete mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkVerifyingJwtAccessTokenConverter.java delete mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwtHeaderConverter.java delete mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/RSAJwkDefinition.java 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 deleted file mode 100644 index 72769bbc0..000000000 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkAttributes.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2012-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.security.oauth2.provider.token.store.jwk; - -/** - * @author Joe Grandja - */ -final class JwkAttributes { - static final String KEY_ID = "kid"; - - static final String KEY_TYPE = "kty"; - - static final String ALGORITHM = "alg"; - - static final String PUBLIC_KEY_USE = "use"; - - static final String RSA_PUBLIC_KEY_MODULUS = "n"; - - static final String RSA_PUBLIC_KEY_EXPONENT = "e"; - - 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 deleted file mode 100644 index 93caa5a5c..000000000 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkDefinition.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2012-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.security.oauth2.provider.token.store.jwk; - -/** - * @author Joe Grandja - */ -abstract class JwkDefinition { - private final String keyId; - private final KeyType keyType; - private final PublicKeyUse publicKeyUse; - private final CryptoAlgorithm algorithm; - - protected JwkDefinition(String keyId, - KeyType keyType, - PublicKeyUse publicKeyUse, - CryptoAlgorithm algorithm) { - this.keyId = keyId; - this.keyType = keyType; - this.publicKeyUse = publicKeyUse; - this.algorithm = algorithm; - } - - String getKeyId() { - return this.keyId; - } - - KeyType getKeyType() { - return this.keyType; - } - - PublicKeyUse getPublicKeyUse() { - return this.publicKeyUse; - } - - 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; - } - - 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; - } - } - - 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; - } - } - - enum CryptoAlgorithm { - RS256("SHA256withRSA", "RS256", "RSASSA-PKCS1-v1_5 using SHA-256"), - RS384("SHA384withRSA", "RS384", "RSASSA-PKCS1-v1_5 using SHA-384"), - RS512("SHA512withRSA", "RS512", "RSASSA-PKCS1-v1_5 using SHA-512"); - - private final String standardName; // JCA Standard Name - private final String headerParamValue; - private final String description; - - CryptoAlgorithm(String standardName, String headerParamValue, String description) { - this.standardName = standardName; - this.headerParamValue = headerParamValue; - this.description = description; - } - - String standardName() { - return this.standardName; - } - - String headerParamValue() { - return this.headerParamValue; - } - - String description() { - return this.description; - } - - static CryptoAlgorithm fromStandardName(String standardName) { - CryptoAlgorithm result = null; - for (CryptoAlgorithm algorithm : values()) { - if (algorithm.standardName().equals(standardName)) { - 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 deleted file mode 100644 index a9f241f92..000000000 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkDefinitionSource.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2012-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.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.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.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.atomic.AtomicReference; - -/** - * @author Joe Grandja - */ -class JwkDefinitionSource { - private final URL jwkSetUrl; - private final JwkSetConverter jwkSetConverter = new JwkSetConverter(); - private final AtomicReference> jwkDefinitions = - new AtomicReference>(new HashMap()); - - JwkDefinitionSource(String jwkSetUrl) { - try { - this.jwkSetUrl = new URL(jwkSetUrl); - } catch (MalformedURLException ex) { - throw new IllegalArgumentException("Invalid JWK Set URL: " + ex.getMessage(), ex); - } - } - - JwkDefinition getDefinition(String keyId) { - JwkDefinition result = null; - for (JwkDefinition jwkDefinition : this.jwkDefinitions.get().keySet()) { - if (jwkDefinition.getKeyId().equals(keyId)) { - result = jwkDefinition; - break; - } - } - return result; - } - - JwkDefinition getDefinitionRefreshIfNecessary(String keyId) { - JwkDefinition result = this.getDefinition(keyId); - if (result != null) { - return result; - } - this.refreshJwkDefinitions(); - return this.getDefinition(keyId); - } - - SignatureVerifier getVerifier(String keyId) { - SignatureVerifier result = null; - JwkDefinition jwkDefinition = this.getDefinitionRefreshIfNecessary(keyId); - if (jwkDefinition != null) { - result = this.jwkDefinitions.get().get(jwkDefinition); - } - return result; - } - - private void refreshJwkDefinitions() { - Set jwkDefinitionSet; - try { - jwkDefinitionSet = this.jwkSetConverter.convert(this.jwkSetUrl.openStream()); - } catch (IOException ex) { - throw new JwkException("An I/O error occurred while refreshing the JWK Set: " + ex.getMessage(), ex); - } - - Map refreshedJwkDefinitions = new LinkedHashMap(); - - for (JwkDefinition jwkDefinition : jwkDefinitionSet) { - if (JwkDefinition.KeyType.RSA.equals(jwkDefinition.getKeyType())) { - refreshedJwkDefinitions.put(jwkDefinition, this.createRSAVerifier((RSAJwkDefinition)jwkDefinition)); - } - } - - this.jwkDefinitions.set(refreshedJwkDefinitions); - } - - private 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; - } -} 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 deleted file mode 100644 index f9a5e0032..000000000 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkException.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2012-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.security.oauth2.provider.token.store.jwk; - -import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; - -/** - * @author Joe Grandja - */ -public class JwkException extends OAuth2Exception { - - public JwkException(String message) { - super(message); - } - - public JwkException(String message, Throwable cause) { - super(message, cause); - } - - @Override - public String getOAuth2ErrorCode() { - return "server_error"; - } - - @Override - public int getHttpErrorCode() { - return 500; - } -} \ 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 deleted file mode 100644 index 1b6964adb..000000000 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkSetConverter.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright 2012-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.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.*; - - -/** - * @author Joe Grandja - */ -class JwkSetConverter implements Converter> { - private final JsonFactory factory = new JsonFactory(); - - @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; - } - - 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."); - } - - return this.createRSAJwkDefinition(attributes); - } - - 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.fromStandardName(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 deleted file mode 100644 index cbfd1696f..000000000 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkTokenStore.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2012-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.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.JwtTokenStore; -import org.springframework.util.Assert; - -import java.util.Collection; - -/** - * @author Joe Grandja - */ -public class JwkTokenStore implements TokenStore { - private final JwtTokenStore delegate; - - 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); - } - - @Override - public OAuth2Authentication readAuthentication(OAuth2AccessToken token) { - return this.delegate.readAuthentication(token); - } - - @Override - public OAuth2Authentication readAuthentication(String token) { - return this.delegate.readAuthentication(token); - } - - @Override - public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) { - throw this.operationNotSupported(); - } - - @Override - public OAuth2AccessToken readAccessToken(String tokenValue) { - return this.delegate.readAccessToken(tokenValue); - } - - @Override - public void removeAccessToken(OAuth2AccessToken token) { - throw this.operationNotSupported(); - } - - @Override - public void storeRefreshToken(OAuth2RefreshToken refreshToken, OAuth2Authentication authentication) { - throw this.operationNotSupported(); - } - - @Override - public OAuth2RefreshToken readRefreshToken(String tokenValue) { - throw this.operationNotSupported(); - } - - @Override - public OAuth2Authentication readAuthenticationForRefreshToken(OAuth2RefreshToken token) { - throw this.operationNotSupported(); - } - - @Override - public void removeRefreshToken(OAuth2RefreshToken token) { - throw this.operationNotSupported(); - } - - @Override - public void removeAccessTokenUsingRefreshToken(OAuth2RefreshToken refreshToken) { - throw this.operationNotSupported(); - } - - @Override - public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) { - throw this.operationNotSupported(); - } - - @Override - public Collection findTokensByClientIdAndUserName(String clientId, String userName) { - throw this.operationNotSupported(); - } - - @Override - public Collection findTokensByClientId(String clientId) { - throw this.operationNotSupported(); - } - - private JwkException operationNotSupported() { - return new JwkException("This operation is currently 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 deleted file mode 100644 index dc7ea2606..000000000 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkVerifyingJwtAccessTokenConverter.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2012-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.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.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; - -/** - * @author Joe Grandja - */ -class JwkVerifyingJwtAccessTokenConverter extends JwtAccessTokenConverter { - private final JwkDefinitionSource jwkDefinitionSource; - private final JwtHeaderConverter jwtHeaderConverter = new JwtHeaderConverter(); - private final JsonParser jsonParser = JsonParserFactory.create(); - - JwkVerifyingJwtAccessTokenConverter(JwkDefinitionSource jwkDefinitionSource) { - this.jwkDefinitionSource = jwkDefinitionSource; - } - - @Override - protected Map decode(String token) { - try { - Map headers = this.jwtHeaderConverter.convert(token); - - // Validate "kid" header - String keyIdHeader = headers.get(KEY_ID); - if (keyIdHeader == null) { - throw new JwkException("Invalid JWT/JWS: \"" + KEY_ID + "\" is a required JOSE Header."); - } - JwkDefinition jwkDefinition = this.jwkDefinitionSource.getDefinitionRefreshIfNecessary(keyIdHeader); - if (jwkDefinition == null) { - throw new JwkException("Invalid JOSE Header \"" + KEY_ID + "\" (" + keyIdHeader + ")"); - } - - // Validate "alg" header - String algorithmHeader = headers.get(ALGORITHM); - if (algorithmHeader == null) { - throw new JwkException("Invalid JWT/JWS: \"" + ALGORITHM + "\" is a required JOSE Header."); - } - if (!algorithmHeader.equals(jwkDefinition.getAlgorithm().headerParamValue())) { - throw new JwkException("Invalid JOSE Header \"" + ALGORITHM + "\" (" + algorithmHeader + ")" + - " does not match algorithm associated 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; - - } catch (Exception ex) { - throw new JwkException("Failed to decode/verify the JWT/JWS: " + ex.getMessage(), ex); - } - } - - @Override - protected String encode(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { - throw new JwkException("JWT/JWS (signing) is currently 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 deleted file mode 100644 index 2afa65a8d..000000000 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwtHeaderConverter.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2012-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.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 java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -/** - * @author Joe Grandja - */ -class JwtHeaderConverter implements Converter> { - private final JsonFactory factory = new JsonFactory(); - - @Override - public Map convert(String token) { - Map headers; - - int headerEndIndex = token.indexOf('.'); - if (headerEndIndex == -1) { - throw new JwkException("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 JwkException("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 deleted file mode 100644 index ef8d1d06e..000000000 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/RSAJwkDefinition.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2012-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.security.oauth2.provider.token.store.jwk; - -/** - * @author Joe Grandja - */ -final class RSAJwkDefinition extends JwkDefinition { - private final String modulus; - private final String exponent; - - RSAJwkDefinition(String keyId, - JwkDefinition.PublicKeyUse publicKeyUse, - JwkDefinition.CryptoAlgorithm algorithm, - String modulus, - String exponent) { - - super(keyId, JwkDefinition.KeyType.RSA, publicKeyUse, algorithm); - this.modulus = modulus; - this.exponent = exponent; - } - - String getModulus() { - return this.modulus; - } - - String getExponent() { - return this.exponent; - } -} \ No newline at end of file From d15f6f6e6608601231786bf31f1823a4fc6aac86 Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Mon, 13 Feb 2017 16:09:22 -0500 Subject: [PATCH 561/831] Add TokenStore supporting Jwk verification Fixes gh-977 --- .../token/store/jwk/JwkAttributes.java | 35 ++++ .../token/store/jwk/JwkDefinition.java | 168 ++++++++++++++++++ .../token/store/jwk/JwkDefinitionSource.java | 117 ++++++++++++ .../token/store/jwk/JwkException.java | 42 +++++ .../token/store/jwk/JwkSetConverter.java | 144 +++++++++++++++ .../token/store/jwk/JwkTokenStore.java | 109 ++++++++++++ .../JwkVerifyingJwtAccessTokenConverter.java | 91 ++++++++++ .../token/store/jwk/JwtHeaderConverter.java | 68 +++++++ .../token/store/jwk/RSAJwkDefinition.java | 43 +++++ 9 files changed, 817 insertions(+) create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkAttributes.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkDefinition.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkDefinitionSource.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkException.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkSetConverter.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkTokenStore.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkVerifyingJwtAccessTokenConverter.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwtHeaderConverter.java create mode 100644 spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/RSAJwkDefinition.java 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..72769bbc0 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkAttributes.java @@ -0,0 +1,35 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.security.oauth2.provider.token.store.jwk; + +/** + * @author Joe Grandja + */ +final class JwkAttributes { + static final String KEY_ID = "kid"; + + static final String KEY_TYPE = "kty"; + + static final String ALGORITHM = "alg"; + + static final String PUBLIC_KEY_USE = "use"; + + static final String RSA_PUBLIC_KEY_MODULUS = "n"; + + static final String RSA_PUBLIC_KEY_EXPONENT = "e"; + + 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..93caa5a5c --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkDefinition.java @@ -0,0 +1,168 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.security.oauth2.provider.token.store.jwk; + +/** + * @author Joe Grandja + */ +abstract class JwkDefinition { + private final String keyId; + private final KeyType keyType; + private final PublicKeyUse publicKeyUse; + private final CryptoAlgorithm algorithm; + + protected JwkDefinition(String keyId, + KeyType keyType, + PublicKeyUse publicKeyUse, + CryptoAlgorithm algorithm) { + this.keyId = keyId; + this.keyType = keyType; + this.publicKeyUse = publicKeyUse; + this.algorithm = algorithm; + } + + String getKeyId() { + return this.keyId; + } + + KeyType getKeyType() { + return this.keyType; + } + + PublicKeyUse getPublicKeyUse() { + return this.publicKeyUse; + } + + 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; + } + + 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; + } + } + + 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; + } + } + + enum CryptoAlgorithm { + RS256("SHA256withRSA", "RS256", "RSASSA-PKCS1-v1_5 using SHA-256"), + RS384("SHA384withRSA", "RS384", "RSASSA-PKCS1-v1_5 using SHA-384"), + RS512("SHA512withRSA", "RS512", "RSASSA-PKCS1-v1_5 using SHA-512"); + + private final String standardName; // JCA Standard Name + private final String headerParamValue; + private final String description; + + CryptoAlgorithm(String standardName, String headerParamValue, String description) { + this.standardName = standardName; + this.headerParamValue = headerParamValue; + this.description = description; + } + + String standardName() { + return this.standardName; + } + + String headerParamValue() { + return this.headerParamValue; + } + + String description() { + return this.description; + } + + static CryptoAlgorithm fromStandardName(String standardName) { + CryptoAlgorithm result = null; + for (CryptoAlgorithm algorithm : values()) { + if (algorithm.standardName().equals(standardName)) { + 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..a9f241f92 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkDefinitionSource.java @@ -0,0 +1,117 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.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.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.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; + +/** + * @author Joe Grandja + */ +class JwkDefinitionSource { + private final URL jwkSetUrl; + private final JwkSetConverter jwkSetConverter = new JwkSetConverter(); + private final AtomicReference> jwkDefinitions = + new AtomicReference>(new HashMap()); + + JwkDefinitionSource(String jwkSetUrl) { + try { + this.jwkSetUrl = new URL(jwkSetUrl); + } catch (MalformedURLException ex) { + throw new IllegalArgumentException("Invalid JWK Set URL: " + ex.getMessage(), ex); + } + } + + JwkDefinition getDefinition(String keyId) { + JwkDefinition result = null; + for (JwkDefinition jwkDefinition : this.jwkDefinitions.get().keySet()) { + if (jwkDefinition.getKeyId().equals(keyId)) { + result = jwkDefinition; + break; + } + } + return result; + } + + JwkDefinition getDefinitionRefreshIfNecessary(String keyId) { + JwkDefinition result = this.getDefinition(keyId); + if (result != null) { + return result; + } + this.refreshJwkDefinitions(); + return this.getDefinition(keyId); + } + + SignatureVerifier getVerifier(String keyId) { + SignatureVerifier result = null; + JwkDefinition jwkDefinition = this.getDefinitionRefreshIfNecessary(keyId); + if (jwkDefinition != null) { + result = this.jwkDefinitions.get().get(jwkDefinition); + } + return result; + } + + private void refreshJwkDefinitions() { + Set jwkDefinitionSet; + try { + jwkDefinitionSet = this.jwkSetConverter.convert(this.jwkSetUrl.openStream()); + } catch (IOException ex) { + throw new JwkException("An I/O error occurred while refreshing the JWK Set: " + ex.getMessage(), ex); + } + + Map refreshedJwkDefinitions = new LinkedHashMap(); + + for (JwkDefinition jwkDefinition : jwkDefinitionSet) { + if (JwkDefinition.KeyType.RSA.equals(jwkDefinition.getKeyType())) { + refreshedJwkDefinitions.put(jwkDefinition, this.createRSAVerifier((RSAJwkDefinition)jwkDefinition)); + } + } + + this.jwkDefinitions.set(refreshedJwkDefinitions); + } + + private 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; + } +} 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..f9a5e0032 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkException.java @@ -0,0 +1,42 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.security.oauth2.provider.token.store.jwk; + +import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; + +/** + * @author Joe Grandja + */ +public class JwkException extends OAuth2Exception { + + public JwkException(String message) { + super(message); + } + + public JwkException(String message, Throwable cause) { + super(message, cause); + } + + @Override + public String getOAuth2ErrorCode() { + return "server_error"; + } + + @Override + public int getHttpErrorCode() { + return 500; + } +} \ 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..1b6964adb --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkSetConverter.java @@ -0,0 +1,144 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.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.*; + + +/** + * @author Joe Grandja + */ +class JwkSetConverter implements Converter> { + private final JsonFactory factory = new JsonFactory(); + + @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; + } + + 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."); + } + + return this.createRSAJwkDefinition(attributes); + } + + 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.fromStandardName(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..cbfd1696f --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkTokenStore.java @@ -0,0 +1,109 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.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.JwtTokenStore; +import org.springframework.util.Assert; + +import java.util.Collection; + +/** + * @author Joe Grandja + */ +public class JwkTokenStore implements TokenStore { + private final JwtTokenStore delegate; + + 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); + } + + @Override + public OAuth2Authentication readAuthentication(OAuth2AccessToken token) { + return this.delegate.readAuthentication(token); + } + + @Override + public OAuth2Authentication readAuthentication(String token) { + return this.delegate.readAuthentication(token); + } + + @Override + public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) { + throw this.operationNotSupported(); + } + + @Override + public OAuth2AccessToken readAccessToken(String tokenValue) { + return this.delegate.readAccessToken(tokenValue); + } + + @Override + public void removeAccessToken(OAuth2AccessToken token) { + throw this.operationNotSupported(); + } + + @Override + public void storeRefreshToken(OAuth2RefreshToken refreshToken, OAuth2Authentication authentication) { + throw this.operationNotSupported(); + } + + @Override + public OAuth2RefreshToken readRefreshToken(String tokenValue) { + throw this.operationNotSupported(); + } + + @Override + public OAuth2Authentication readAuthenticationForRefreshToken(OAuth2RefreshToken token) { + throw this.operationNotSupported(); + } + + @Override + public void removeRefreshToken(OAuth2RefreshToken token) { + throw this.operationNotSupported(); + } + + @Override + public void removeAccessTokenUsingRefreshToken(OAuth2RefreshToken refreshToken) { + throw this.operationNotSupported(); + } + + @Override + public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) { + throw this.operationNotSupported(); + } + + @Override + public Collection findTokensByClientIdAndUserName(String clientId, String userName) { + throw this.operationNotSupported(); + } + + @Override + public Collection findTokensByClientId(String clientId) { + throw this.operationNotSupported(); + } + + private JwkException operationNotSupported() { + return new JwkException("This operation is currently 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..dc7ea2606 --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkVerifyingJwtAccessTokenConverter.java @@ -0,0 +1,91 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.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.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; + +/** + * @author Joe Grandja + */ +class JwkVerifyingJwtAccessTokenConverter extends JwtAccessTokenConverter { + private final JwkDefinitionSource jwkDefinitionSource; + private final JwtHeaderConverter jwtHeaderConverter = new JwtHeaderConverter(); + private final JsonParser jsonParser = JsonParserFactory.create(); + + JwkVerifyingJwtAccessTokenConverter(JwkDefinitionSource jwkDefinitionSource) { + this.jwkDefinitionSource = jwkDefinitionSource; + } + + @Override + protected Map decode(String token) { + try { + Map headers = this.jwtHeaderConverter.convert(token); + + // Validate "kid" header + String keyIdHeader = headers.get(KEY_ID); + if (keyIdHeader == null) { + throw new JwkException("Invalid JWT/JWS: \"" + KEY_ID + "\" is a required JOSE Header."); + } + JwkDefinition jwkDefinition = this.jwkDefinitionSource.getDefinitionRefreshIfNecessary(keyIdHeader); + if (jwkDefinition == null) { + throw new JwkException("Invalid JOSE Header \"" + KEY_ID + "\" (" + keyIdHeader + ")"); + } + + // Validate "alg" header + String algorithmHeader = headers.get(ALGORITHM); + if (algorithmHeader == null) { + throw new JwkException("Invalid JWT/JWS: \"" + ALGORITHM + "\" is a required JOSE Header."); + } + if (!algorithmHeader.equals(jwkDefinition.getAlgorithm().headerParamValue())) { + throw new JwkException("Invalid JOSE Header \"" + ALGORITHM + "\" (" + algorithmHeader + ")" + + " does not match algorithm associated 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; + + } catch (Exception ex) { + throw new JwkException("Failed to decode/verify the JWT/JWS: " + ex.getMessage(), ex); + } + } + + @Override + protected String encode(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { + throw new JwkException("JWT/JWS (signing) is currently 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..2afa65a8d --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwtHeaderConverter.java @@ -0,0 +1,68 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.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 java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +/** + * @author Joe Grandja + */ +class JwtHeaderConverter implements Converter> { + private final JsonFactory factory = new JsonFactory(); + + @Override + public Map convert(String token) { + Map headers; + + int headerEndIndex = token.indexOf('.'); + if (headerEndIndex == -1) { + throw new JwkException("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 JwkException("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..6361784af --- /dev/null +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/RSAJwkDefinition.java @@ -0,0 +1,43 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.security.oauth2.provider.token.store.jwk; + +/** + * @author Joe Grandja + */ +final class RSAJwkDefinition extends JwkDefinition { + private final String modulus; + private final String exponent; + + RSAJwkDefinition(String keyId, + PublicKeyUse publicKeyUse, + CryptoAlgorithm algorithm, + String modulus, + String exponent) { + + super(keyId, KeyType.RSA, publicKeyUse, algorithm); + this.modulus = modulus; + this.exponent = exponent; + } + + String getModulus() { + return this.modulus; + } + + String getExponent() { + return this.exponent; + } +} \ No newline at end of file From 5ad171060b8018ffaf80233106c494b258578238 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 20 Feb 2017 16:30:22 +0000 Subject: [PATCH 562/831] Add test for ambiguous token services --- .../TokenServicesMultipleBeansTests.java | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/TokenServicesMultipleBeansTests.java 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..a993afbf9 --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/TokenServicesMultipleBeansTests.java @@ -0,0 +1,56 @@ +/* + * 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 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.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 + private ResourceServerTokenServices tokenServices; + + @Test + public void test() { + assertNotNull(tokenServices); + } + + @Configuration + @EnableAuthorizationServer + @EnableWebSecurity + protected static class BrokenOAuthApplication extends AuthorizationServerConfigurerAdapter { + } +} From df2466a9b78b5c6e9ab4cbe3ab97643c5cb6a244 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 21 Feb 2017 15:17:31 +0000 Subject: [PATCH 563/831] Use FactoryBean to expose @Beans of different TokenServices flavours There is one for ConsumerTokenServices and one for AuthorizationServerTokenServices. Fixes gh-984 --- ...orizationServerEndpointsConfiguration.java | 53 +++++++++++++++++-- .../TokenServicesMultipleBeansTests.java | 17 +++++- .../src/test/java/demo/ApplicationTests.java | 6 +-- .../java/demo/RefreshTokenSupportTests.java | 6 +-- 4 files changed, 67 insertions(+), 15 deletions(-) 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/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 index a993afbf9..d38593d54 100644 --- 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 @@ -17,6 +17,7 @@ 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; @@ -26,6 +27,9 @@ 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; @@ -40,16 +44,25 @@ @WebAppConfiguration public class TokenServicesMultipleBeansTests { - @Autowired + @Autowired(required=false) private ResourceServerTokenServices tokenServices; + @Autowired + private AuthorizationServerTokenServices authServerTokenServices; + + @Autowired + private ConsumerTokenServices consumerTokenServices; + @Test public void test() { - assertNotNull(tokenServices); + assertNull(tokenServices); + assertNotNull(authServerTokenServices); + assertNotNull(consumerTokenServices); } @Configuration @EnableAuthorizationServer + @EnableResourceServer @EnableWebSecurity protected static class BrokenOAuthApplication extends AuthorizationServerConfigurerAdapter { } diff --git a/tests/annotation/jwt/src/test/java/demo/ApplicationTests.java b/tests/annotation/jwt/src/test/java/demo/ApplicationTests.java index 82a5ffee6..13b37ed7a 100644 --- a/tests/annotation/jwt/src/test/java/demo/ApplicationTests.java +++ b/tests/annotation/jwt/src/test/java/demo/ApplicationTests.java @@ -6,13 +6,12 @@ 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.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; @@ -28,8 +27,7 @@ public class ApplicationTests { 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/RefreshTokenSupportTests.java b/tests/annotation/jwt/src/test/java/demo/RefreshTokenSupportTests.java index 295fbdabf..141d73969 100644 --- a/tests/annotation/jwt/src/test/java/demo/RefreshTokenSupportTests.java +++ b/tests/annotation/jwt/src/test/java/demo/RefreshTokenSupportTests.java @@ -3,11 +3,10 @@ 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; @@ -21,8 +20,7 @@ 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. From c9b2bbab23a4676cf909e76674b401b6d867e40c Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 21 Feb 2017 17:28:37 +0000 Subject: [PATCH 564/831] Update to Spring Boot 1.5.1 --- .../src/main/java/demo/Application.java | 7 ++----- .../src/main/resources/application.yml | 3 +++ .../src/test/java/demo/ApplicationTests.java | 13 +++++-------- .../demo/AuthorizationCodeProviderTests.java | 3 --- .../demo/ClientCredentialsProviderTests.java | 3 --- .../test/java/demo/ImplicitProviderTests.java | 3 --- .../java/demo/ProtectedResourceTests.java | 3 --- .../java/demo/RefreshTokenSupportTests.java | 3 --- .../ResourceOwnerPasswordProviderTests.java | 3 --- .../client/src/main/resources/application.yml | 3 +++ .../test/java/client/ApplicationTests.java | 13 +++++-------- .../client/ClientServerInteractionTests.java | 8 +++++--- tests/annotation/common/pom.xml | 9 --------- .../common/AbstractIntegrationTests.java | 14 +++++++------- .../java/sparklr/common/HttpTestUtils.java | 4 ++-- .../src/main/java/demo/Application.java | 5 ++--- .../src/main/resources/application.yml | 3 +++ .../src/test/java/demo/ApplicationTests.java | 12 ++++-------- .../demo/ClientCredentialsProviderTests.java | 2 -- .../src/main/java/demo/Application.java | 5 ++--- .../src/main/resources/application.yml | 3 +++ .../src/test/java/demo/ApplicationTests.java | 12 ++++-------- .../demo/AuthorizationCodeProviderTests.java | 2 -- .../demo/ClientCredentialsProviderTests.java | 3 --- .../test/java/demo/CustomProviderTests.java | 4 +--- .../test/java/demo/ImplicitProviderTests.java | 4 +--- .../java/demo/ProtectedResourceTests.java | 3 --- .../java/demo/RefreshTokenSupportTests.java | 3 --- .../ResourceOwnerPasswordProviderTests.java | 3 --- .../form/src/main/java/demo/Application.java | 7 ++----- .../form/src/main/resources/application.yml | 3 +++ .../src/test/java/demo/ApplicationTests.java | 12 ++++-------- .../demo/AuthorizationCodeProviderTests.java | 3 --- .../demo/ClientCredentialsProviderTests.java | 2 -- .../test/java/demo/ImplicitProviderTests.java | 3 --- .../java/demo/ProtectedResourceTests.java | 3 --- .../java/demo/RefreshTokenSupportTests.java | 3 --- .../ResourceOwnerPasswordProviderTests.java | 2 -- .../jaxb/src/main/java/demo/Application.java | 7 ++----- .../jaxb/src/main/resources/application.yml | 3 +++ .../src/test/java/demo/ApplicationTests.java | 12 ++++-------- .../demo/AuthorizationCodeProviderTests.java | 2 -- .../demo/ClientCredentialsProviderTests.java | 2 -- .../test/java/demo/ImplicitProviderTests.java | 4 +--- .../java/demo/ProtectedResourceTests.java | 2 -- .../java/demo/RefreshTokenSupportTests.java | 2 -- .../ResourceOwnerPasswordProviderTests.java | 2 -- .../jdbc/src/main/java/demo/Application.java | 2 +- .../jdbc/src/main/resources/application.yml | 4 ++++ .../src/test/java/demo/ApplicationTests.java | 15 +++++---------- .../demo/AuthorizationCodeProviderTests.java | 4 ++-- .../demo/ClientCredentialsProviderTests.java | 4 ++-- .../test/java/demo/ImplicitProviderTests.java | 4 ++-- .../java/demo/ProtectedResourceTests.java | 4 ++-- .../java/demo/RefreshTokenSupportTests.java | 4 ++-- .../ResourceOwnerPasswordProviderTests.java | 4 ++-- .../jpa/src/main/java/demo/Application.java | 2 +- .../jpa/src/main/resources/application.yml | 3 +++ .../src/test/java/demo/ApplicationTests.java | 12 ++++-------- .../AuthorizationCodeProviderCookieTests.java | 2 -- .../demo/AuthorizationCodeProviderTests.java | 2 -- .../demo/ClientCredentialsProviderTests.java | 3 --- .../test/java/demo/ImplicitProviderTests.java | 4 +--- .../java/demo/ProtectedResourceTests.java | 3 --- .../java/demo/RefreshTokenSupportTests.java | 3 --- .../ResourceOwnerPasswordProviderTests.java | 4 +--- .../jwt/src/main/java/demo/Application.java | 7 ++----- .../jwt/src/main/resources/application.yml | 3 +++ .../src/test/java/demo/ApplicationTests.java | 19 ++++++++----------- .../demo/AuthorizationCodeProviderTests.java | 3 --- .../demo/ClientCredentialsProviderTests.java | 4 +--- .../test/java/demo/ImplicitProviderTests.java | 3 --- .../java/demo/ProtectedResourceTests.java | 3 --- .../java/demo/RefreshTokenSupportTests.java | 2 -- .../ResourceOwnerPasswordProviderTests.java | 4 +--- .../src/main/resources/application.yml | 3 +++ .../src/test/java/demo/ApplicationTests.java | 12 ++++-------- .../demo/AuthorizationCodeProviderTests.java | 2 -- .../demo/ClientCredentialsProviderTests.java | 4 +--- .../test/java/demo/ImplicitProviderTests.java | 3 --- .../java/demo/ProtectedResourceTests.java | 2 -- .../java/demo/RefreshTokenSupportTests.java | 3 --- .../ResourceOwnerPasswordProviderTests.java | 3 --- ...letPathClientCredentialsProviderTests.java | 11 ++++------- .../multi/src/main/java/demo/Application.java | 4 +++- .../src/test/java/demo/ApplicationTests.java | 12 ++++-------- .../demo/AuthorizationCodeProviderTests.java | 3 --- .../demo/ClientCredentialsProviderTests.java | 3 --- .../test/java/demo/ImplicitProviderTests.java | 3 --- .../java/demo/ProtectedResourceTests.java | 2 -- .../java/demo/RefreshTokenSupportTests.java | 3 --- .../ResourceOwnerPasswordProviderTests.java | 2 -- tests/annotation/pom.xml | 4 ++-- .../src/main/java/demo/Application.java | 8 ++------ .../src/main/resources/application.yml | 3 +++ .../src/test/java/demo/ApplicationTests.java | 12 ++++-------- .../java/demo/ProtectedResourceTests.java | 3 --- .../src/main/resources/application.yml | 3 +++ .../src/test/java/demo/ApplicationTests.java | 9 +++------ .../AuthorizationCodeProviderCookieTests.java | 2 -- .../demo/AuthorizationCodeProviderTests.java | 2 -- .../demo/ClientCredentialsProviderTests.java | 3 --- .../java/demo/GlobalMethodSecurityTests.java | 12 ++++++------ .../test/java/demo/ImplicitProviderTests.java | 4 +--- .../java/demo/ProtectedResourceTests.java | 3 --- .../java/demo/RefreshTokenSupportTests.java | 3 --- .../ResourceOwnerPasswordProviderTests.java | 4 +--- 107 files changed, 162 insertions(+), 349 deletions(-) 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/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..ec1d24e93 100644 --- a/tests/annotation/common/pom.xml +++ b/tests/annotation/common/pom.xml @@ -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/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/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/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/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/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/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/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 13b37ed7a..1bb5192c6 100644 --- a/tests/annotation/jwt/src/test/java/demo/ApplicationTests.java +++ b/tests/annotation/jwt/src/test/java/demo/ApplicationTests.java @@ -6,24 +6,21 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; -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.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 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 141d73969..28349045f 100644 --- a/tests/annotation/jwt/src/test/java/demo/RefreshTokenSupportTests.java +++ b/tests/annotation/jwt/src/test/java/demo/RefreshTokenSupportTests.java @@ -3,7 +3,6 @@ import static org.junit.Assert.assertEquals; import org.springframework.beans.factory.annotation.Autowired; -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.AuthorizationServerTokenServices; @@ -16,7 +15,6 @@ * @author Ryan Heaton * @author Dave Syer */ -@SpringApplicationConfiguration(classes=Application.class) public class RefreshTokenSupportTests extends AbstractRefreshTokenSupportTests { @Autowired 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/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/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..6f139dded 100644 --- a/tests/annotation/pom.xml +++ b/tests/annotation/pom.xml @@ -30,7 +30,7 @@ org.springframework.boot spring-boot-starter-parent - 1.3.5.RELEASE + 1.5.1.RELEASE @@ -50,7 +50,7 @@ org.springframework.security spring-security-jwt - 1.0.3.RELEASE + 1.0.7.RELEASE
    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/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 From 2bea96bbce38ce1e764b6b23a7a00203bf49e948 Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Wed, 22 Feb 2017 12:38:04 -0500 Subject: [PATCH 565/831] Polish TokenStore supporting Jwk verification Add tests Add javadoc Fix bug to work with UAA 3.11.0 Issue gh-977 --- .../token/store/jwk/JwkAttributes.java | 27 ++ .../token/store/jwk/JwkDefinition.java | 38 ++- .../token/store/jwk/JwkDefinitionSource.java | 55 +++- .../token/store/jwk/JwkException.java | 21 +- .../token/store/jwk/JwkSetConverter.java | 45 ++- .../token/store/jwk/JwkTokenStore.java | 151 +++++++++- .../JwkVerifyingJwtAccessTokenConverter.java | 121 +++++--- .../token/store/jwk/JwtHeaderConverter.java | 17 +- .../token/store/jwk/RSAJwkDefinition.java | 20 ++ .../store/jwk/JwkDefinitionSourceTest.java | 40 +++ .../token/store/jwk/JwkSetConverterTest.java | 284 ++++++++++++++++++ .../token/store/jwk/JwkTokenStoreTest.java | 87 ++++++ ...kVerifyingJwtAccessTokenConverterTest.java | 109 +++++++ .../store/jwk/JwtHeaderConverterTest.java | 58 ++++ .../provider/token/store/jwk/JwtTestUtil.java | 86 ++++++ 15 files changed, 1103 insertions(+), 56 deletions(-) create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkDefinitionSourceTest.java create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkSetConverterTest.java create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkTokenStoreTest.java create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkVerifyingJwtAccessTokenConverterTest.java create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwtHeaderConverterTest.java create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwtTestUtil.java 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 index 72769bbc0..75343999a 100644 --- 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 @@ -16,20 +16,47 @@ 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 index 93caa5a5c..ac33281bd 100644 --- 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 @@ -16,6 +16,10 @@ 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 { @@ -24,6 +28,14 @@ abstract class JwkDefinition { 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, @@ -34,18 +46,31 @@ protected JwkDefinition(String keyId, 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; } @@ -74,6 +99,9 @@ public int hashCode() { return result; } + /** + * The defined Key Type ("kty") values. + */ enum KeyType { RSA("RSA"), EC("EC"), @@ -101,6 +129,9 @@ static KeyType fromValue(String value) { } } + /** + * The defined Public Key Use ("use") values. + */ enum PublicKeyUse { SIG("sig"), ENC("enc"); @@ -127,6 +158,9 @@ static PublicKeyUse fromValue(String value) { } } + /** + * The defined Algorithm ("alg") values. + */ enum CryptoAlgorithm { RS256("SHA256withRSA", "RS256", "RSASSA-PKCS1-v1_5 using SHA-256"), RS384("SHA384withRSA", "RS384", "RSASSA-PKCS1-v1_5 using SHA-384"), @@ -154,10 +188,10 @@ String description() { return this.description; } - static CryptoAlgorithm fromStandardName(String standardName) { + static CryptoAlgorithm fromHeaderParamValue(String headerParamValue) { CryptoAlgorithm result = null; for (CryptoAlgorithm algorithm : values()) { - if (algorithm.standardName().equals(standardName)) { + if (algorithm.headerParamValue().equals(headerParamValue)) { result = algorithm; break; } 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 index a9f241f92..83bf4b85f 100644 --- 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 @@ -20,6 +20,7 @@ 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; @@ -33,6 +34,14 @@ import java.util.concurrent.atomic.AtomicReference; /** + * 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 { @@ -41,6 +50,11 @@ class JwkDefinitionSource { private final AtomicReference> jwkDefinitions = new AtomicReference>(new HashMap()); + /** + * 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); @@ -49,6 +63,12 @@ class JwkDefinitionSource { } } + /** + * 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; for (JwkDefinition jwkDefinition : this.jwkDefinitions.get().keySet()) { @@ -60,6 +80,14 @@ JwkDefinition getDefinition(String keyId) { return result; } + /** + * Returns the JWK definition matching the provided keyId ("kid"). + * If the JWK definition is not available in the internal cache then {@link #refreshJwkDefinitions()} + * will be called (to refresh 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 getDefinitionRefreshIfNecessary(String keyId) { JwkDefinition result = this.getDefinition(keyId); if (result != null) { @@ -69,6 +97,12 @@ JwkDefinition getDefinitionRefreshIfNecessary(String keyId) { 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.getDefinitionRefreshIfNecessary(keyId); @@ -78,14 +112,23 @@ SignatureVerifier getVerifier(String keyId) { return result; } - private void refreshJwkDefinitions() { - Set jwkDefinitionSet; + /** + * Refreshes the internal cache of association(s) between {@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 mapped to it's {@link JwkDefinition}. + * + * @see JwkSetConverter + */ + void refreshJwkDefinitions() { + InputStream jwkSetSource; try { - jwkDefinitionSet = this.jwkSetConverter.convert(this.jwkSetUrl.openStream()); + jwkSetSource = this.jwkSetUrl.openStream(); } catch (IOException ex) { - throw new JwkException("An I/O error occurred while refreshing the JWK Set: " + ex.getMessage(), ex); + throw new JwkException("An I/O error occurred while reading from the JWK Set source: " + ex.getMessage(), ex); } + Set jwkDefinitionSet = this.jwkSetConverter.convert(jwkSetSource); + Map refreshedJwkDefinitions = new LinkedHashMap(); for (JwkDefinition jwkDefinition : jwkDefinitionSet) { @@ -109,8 +152,8 @@ private RsaVerifier createRSAVerifier(RSAJwkDefinition rsaDefinition) { 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); + throw new JwkException("An error occurred while creating a RSA Public Key Verifier for " + + rsaDefinition.getKeyId() + " : " + ex.getMessage(), ex); } return result; } 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 index f9a5e0032..f47ef672a 100644 --- 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 @@ -18,9 +18,14 @@ 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); @@ -30,13 +35,25 @@ 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 "server_error"; + 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 500; + 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 index 1b6964adb..2a31e37b6 100644 --- 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 @@ -30,13 +30,32 @@ 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; @@ -52,7 +71,7 @@ public Set convert(InputStream jwkSetSource) { 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."); + 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)."); @@ -87,6 +106,13 @@ public Set convert(InputStream jwkSetSource) { 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)); @@ -99,11 +125,18 @@ private JwkDefinition createJwkDefinition(Map attributes) { 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."); + throw new JwkException(KEY_ID + " is a required attribute for a JWK."); } // use @@ -116,7 +149,7 @@ private JwkDefinition createRSAJwkDefinition(Map attributes) { // alg JwkDefinition.CryptoAlgorithm algorithm = - JwkDefinition.CryptoAlgorithm.fromStandardName(attributes.get(ALGORITHM)); + JwkDefinition.CryptoAlgorithm.fromHeaderParamValue(attributes.get(ALGORITHM)); if (!JwkDefinition.CryptoAlgorithm.RS256.equals(algorithm) && !JwkDefinition.CryptoAlgorithm.RS384.equals(algorithm) && !JwkDefinition.CryptoAlgorithm.RS512.equals(algorithm)) { @@ -127,13 +160,13 @@ private JwkDefinition createRSAJwkDefinition(Map attributes) { // 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."); + 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."); + throw new JwkException(RSA_PUBLIC_KEY_EXPONENT + " is a required attribute for a RSA JWK."); } RSAJwkDefinition jwkDefinition = new RSAJwkDefinition( 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 index cbfd1696f..1f62f6467 100644 --- 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 @@ -15,21 +15,88 @@ */ package org.springframework.security.oauth2.provider.token.store.jwk; +import org.springframework.security.jwt.crypto.sign.SignatureVerifier; 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}, specifically, {@link JwkVerifyingJwtAccessTokenConverter}. + * The {@link JwkVerifyingJwtAccessTokenConverter} is associated with a {@link JwkDefinitionSource} which is responsible + * for fetching (and caching) the JWK Set (a set of JWKs) from the URL supplied to the constructor of this implementation. + *
    + *
    + * + * The {@link JwkVerifyingJwtAccessTokenConverter} will verify the JWS in the following step sequence: + *
    + *
    + *
      + *
    1. Extract the "kid" parameter from the JWT header.
    2. + *
    3. Find the matching {@link JwkDefinition} from the {@link JwkDefinitionSource} with the corresponding "kid" attribute.
    4. + *
    5. Obtain the {@link SignatureVerifier} associated with the {@link JwkDefinition} via the {@link JwkDefinitionSource} and verify the signature.
    6. + *
    + *
    + * NOTE: The algorithms currently supported by this implementation are: RS256, RS384 and RS512. + *
    + *
    + * + * @see JwtTokenStore + * @see JwkVerifyingJwtAccessTokenConverter + * @see JwkDefinitionSource + * @see JwkDefinition + * @see JSON Web Key (JWK) + * @see JSON Web Token (JWT) + * @see JSON Web Signature (JWS) + * * @author Joe Grandja */ public 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); @@ -38,72 +105,150 @@ public JwkTokenStore(String jwkSetUrl) { 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 token) { - return this.delegate.readAuthentication(token); + 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 currently not supported."); + 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 index dc7ea2606..f9a1a7e35 100644 --- 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 @@ -19,6 +19,7 @@ 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; @@ -30,6 +31,41 @@ 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: + *
    + *
    + *
      + *
    1. Extract the "kid" parameter from the JWT header.
    2. + *
    3. Find the matching {@link JwkDefinition} from the {@link JwkDefinitionSource} with the corresponding "kid" attribute.
    4. + *
    5. Obtain the {@link SignatureVerifier} associated with the {@link JwkDefinition} via the {@link JwkDefinitionSource} and verify the signature.
    6. + *
    + *
    + * 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 { @@ -37,55 +73,70 @@ class JwkVerifyingJwtAccessTokenConverter extends JwtAccessTokenConverter { 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) { - try { - Map headers = this.jwtHeaderConverter.convert(token); - - // Validate "kid" header - String keyIdHeader = headers.get(KEY_ID); - if (keyIdHeader == null) { - throw new JwkException("Invalid JWT/JWS: \"" + KEY_ID + "\" is a required JOSE Header."); - } - JwkDefinition jwkDefinition = this.jwkDefinitionSource.getDefinitionRefreshIfNecessary(keyIdHeader); - if (jwkDefinition == null) { - throw new JwkException("Invalid JOSE Header \"" + KEY_ID + "\" (" + keyIdHeader + ")"); - } - - // Validate "alg" header - String algorithmHeader = headers.get(ALGORITHM); - if (algorithmHeader == null) { - throw new JwkException("Invalid JWT/JWS: \"" + ALGORITHM + "\" is a required JOSE Header."); - } - if (!algorithmHeader.equals(jwkDefinition.getAlgorithm().headerParamValue())) { - throw new JwkException("Invalid JOSE Header \"" + ALGORITHM + "\" (" + algorithmHeader + ")" + - " does not match algorithm associated with \"" + KEY_ID + "\" (" + keyIdHeader + ")"); - } + Map headers = this.jwtHeaderConverter.convert(token); - // Verify signature - SignatureVerifier verifier = this.jwkDefinitionSource.getVerifier(keyIdHeader); - Jwt jwt = JwtHelper.decode(token); - jwt.verifySignature(verifier); + // 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.getDefinitionRefreshIfNecessary(keyIdHeader); + if (jwkDefinition == null) { + throw new InvalidTokenException("Invalid JOSE Header " + KEY_ID + " (" + keyIdHeader + ")"); + } - 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)); - } + // 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 + ")"); + } - return claims; + // Verify signature + SignatureVerifier verifier = this.jwkDefinitionSource.getVerifier(keyIdHeader); + Jwt jwt = JwtHelper.decode(token); + jwt.verifySignature(verifier); - } catch (Exception ex) { - throw new JwkException("Failed to decode/verify the JWT/JWS: " + ex.getMessage(), ex); + 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/JWS (signing) is currently not supported."); + 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 index 2afa65a8d..1fb2daf27 100644 --- 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 @@ -20,24 +20,37 @@ 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 JwkException("Invalid JWT. Missing JOSE Header."); + throw new InvalidTokenException("Invalid JWT. Missing JOSE Header."); } byte[] decodedHeader = Codecs.b64UrlDecode(token.substring(0, headerEndIndex)); @@ -56,7 +69,7 @@ public Map convert(String token) { } } catch (IOException ex) { - throw new JwkException("An I/O error occurred while reading the JWT: " + ex.getMessage(), ex); + throw new InvalidTokenException("An I/O error occurred while reading the JWT: " + ex.getMessage(), ex); } finally { try { if (parser != null) parser.close(); 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 index 6361784af..d94ebfb6e 100644 --- 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 @@ -16,12 +16,26 @@ 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, @@ -33,10 +47,16 @@ final class RSAJwkDefinition extends JwkDefinition { 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; } 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..36b1bb459 --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkDefinitionSourceTest.java @@ -0,0 +1,40 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.security.oauth2.provider.token.store.jwk; + +import org.junit.Test; + +import static org.mockito.Mockito.*; + +/** + * @author jgrandja + */ +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 getDefinitionRefreshIfNecessaryWhenKeyIdNotFoundThenRefreshJwkDefinitions() throws Exception { + JwkDefinitionSource jwkDefinitionSource = spy(new JwkDefinitionSource(DEFAULT_JWK_SET_URL)); + doNothing().when(jwkDefinitionSource).refreshJwkDefinitions(); + jwkDefinitionSource.getDefinitionRefreshIfNecessary("invalid-key-id"); + verify(jwkDefinitionSource).refreshJwkDefinitions(); + } +} \ 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..834f9e559 --- /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-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.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 jgrandja + */ +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..34353d37d --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkTokenStoreTest.java @@ -0,0 +1,87 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.security.oauth2.provider.token.store.jwk; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +/** + * @author jgrandja + */ +public class JwkTokenStoreTest { + private JwkTokenStore jwkTokenStore = new JwkTokenStore("https://identity.server1.io/token_keys"); + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Before + public void setUp() throws Exception { + this.thrown.expect(JwkException.class); + this.thrown.expectMessage("This operation is not supported."); + } + + @Test + public void storeAccessTokenWhenCalledThenThrowJwkException() throws Exception { + this.jwkTokenStore.storeAccessToken(null, null); + } + + @Test + public void removeAccessTokenWhenCalledThenThrowJwkException() throws Exception { + this.jwkTokenStore.removeAccessToken(null); + } + + @Test + public void storeRefreshTokenWhenCalledThenThrowJwkException() throws Exception { + this.jwkTokenStore.storeRefreshToken(null, null); + } + + @Test + public void readRefreshTokenWhenCalledThenThrowJwkException() throws Exception { + this.jwkTokenStore.readRefreshToken(null); + } + + @Test + public void readAuthenticationForRefreshTokenWhenCalledThenThrowJwkException() throws Exception { + this.jwkTokenStore.readAuthenticationForRefreshToken(null); + } + + @Test + public void removeRefreshTokenWhenCalledThenThrowJwkException() throws Exception { + this.jwkTokenStore.removeRefreshToken(null); + } + + @Test + public void removeAccessTokenUsingRefreshTokenWhenCalledThenThrowJwkException() throws Exception { + this.jwkTokenStore.removeAccessTokenUsingRefreshToken(null); + } + + @Test + public void getAccessTokenWhenCalledThenThrowJwkException() throws Exception { + this.jwkTokenStore.getAccessToken(null); + } + + @Test + public void findTokensByClientIdAndUserNameWhenCalledThenThrowJwkException() throws Exception { + this.jwkTokenStore.findTokensByClientIdAndUserName(null, null); + } + + @Test + public void findTokensByClientIdWhenCalledThenThrowJwkException() throws Exception { + this.jwkTokenStore.findTokensByClientId(null); + } +} \ 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..a27db63f8 --- /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-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.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 jgrandja + */ +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.getDefinitionRefreshIfNecessary("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.getDefinitionRefreshIfNecessary("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.getDefinitionRefreshIfNecessary("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..f652e61c7 --- /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-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.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 jgrandja + */ +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..b8df0e87b --- /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-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.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 From 44c97375ce756a2bfa576f79c0da1f28879247d8 Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Wed, 1 Mar 2017 11:44:46 -0500 Subject: [PATCH 566/831] Polish gh-977 Fixes gh-994 --- .../token/store/jwk/JwkAttributes.java | 2 +- .../token/store/jwk/JwkDefinition.java | 16 ++-- .../token/store/jwk/JwkDefinitionSource.java | 74 ++++++++++------- .../token/store/jwk/JwkException.java | 2 +- .../token/store/jwk/JwkSetConverter.java | 15 ++-- .../token/store/jwk/JwkTokenStore.java | 20 ++--- .../JwkVerifyingJwtAccessTokenConverter.java | 4 +- .../token/store/jwk/JwtHeaderConverter.java | 2 +- ...kDefinition.java => RsaJwkDefinition.java} | 6 +- .../store/jwk/JwkDefinitionSourceTest.java | 26 ++++-- .../token/store/jwk/JwkDefinitionTest.java | 51 ++++++++++++ .../token/store/jwk/JwkSetConverterTest.java | 4 +- .../token/store/jwk/JwkTokenStoreTest.java | 80 +++++++++++++++++-- ...kVerifyingJwtAccessTokenConverterTest.java | 12 +-- .../store/jwk/JwtHeaderConverterTest.java | 4 +- .../provider/token/store/jwk/JwtTestUtil.java | 2 +- .../token/store/jwk/RsaJwkDefinitionTest.java | 45 +++++++++++ 17 files changed, 275 insertions(+), 90 deletions(-) rename spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/{RSAJwkDefinition.java => RsaJwkDefinition.java} (92%) create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkDefinitionTest.java create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/RsaJwkDefinitionTest.java 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 index 75343999a..642dcc430 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2016 the original author or authors. + * 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. 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 index ac33281bd..2768ca3f1 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2016 the original author or authors. + * 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. @@ -162,18 +162,16 @@ static PublicKeyUse fromValue(String value) { * The defined Algorithm ("alg") values. */ enum CryptoAlgorithm { - RS256("SHA256withRSA", "RS256", "RSASSA-PKCS1-v1_5 using SHA-256"), - RS384("SHA384withRSA", "RS384", "RSASSA-PKCS1-v1_5 using SHA-384"), - RS512("SHA512withRSA", "RS512", "RSASSA-PKCS1-v1_5 using SHA-512"); + RS256("SHA256withRSA", "RS256"), + RS384("SHA384withRSA", "RS384"), + RS512("SHA512withRSA", "RS512"); private final String standardName; // JCA Standard Name private final String headerParamValue; - private final String description; - CryptoAlgorithm(String standardName, String headerParamValue, String description) { + CryptoAlgorithm(String standardName, String headerParamValue) { this.standardName = standardName; this.headerParamValue = headerParamValue; - this.description = description; } String standardName() { @@ -184,10 +182,6 @@ String headerParamValue() { return this.headerParamValue; } - String description() { - return this.description; - } - static CryptoAlgorithm fromHeaderParamValue(String headerParamValue) { CryptoAlgorithm result = null; for (CryptoAlgorithm algorithm : values()) { 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 index 83bf4b85f..de643ff03 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2016 the original author or authors. + * 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. @@ -27,11 +27,10 @@ import java.security.KeyFactory; import java.security.interfaces.RSAPublicKey; import java.security.spec.RSAPublicKeySpec; -import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; -import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.ConcurrentHashMap; /** * A source for JSON Web Key(s) (JWK) that is solely responsible for fetching (and caching) @@ -46,9 +45,8 @@ */ class JwkDefinitionSource { private final URL jwkSetUrl; - private final JwkSetConverter jwkSetConverter = new JwkSetConverter(); - private final AtomicReference> jwkDefinitions = - new AtomicReference>(new HashMap()); + 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. @@ -71,29 +69,28 @@ class JwkDefinitionSource { */ JwkDefinition getDefinition(String keyId) { JwkDefinition result = null; - for (JwkDefinition jwkDefinition : this.jwkDefinitions.get().keySet()) { - if (jwkDefinition.getKeyId().equals(keyId)) { - result = jwkDefinition; - break; - } + 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 #refreshJwkDefinitions()} - * will be called (to refresh the cache) and then followed-up with a second attempt to locate the JWK definition. + * 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 getDefinitionRefreshIfNecessary(String keyId) { + JwkDefinition getDefinitionLoadIfNecessary(String keyId) { JwkDefinition result = this.getDefinition(keyId); if (result != null) { return result; } - this.refreshJwkDefinitions(); + this.jwkDefinitions.clear(); + this.jwkDefinitions.putAll(loadJwkDefinitions(this.jwkSetUrl)); return this.getDefinition(keyId); } @@ -105,42 +102,47 @@ JwkDefinition getDefinitionRefreshIfNecessary(String keyId) { */ SignatureVerifier getVerifier(String keyId) { SignatureVerifier result = null; - JwkDefinition jwkDefinition = this.getDefinitionRefreshIfNecessary(keyId); + JwkDefinition jwkDefinition = this.getDefinitionLoadIfNecessary(keyId); if (jwkDefinition != null) { - result = this.jwkDefinitions.get().get(jwkDefinition); + result = this.jwkDefinitions.get(keyId).getSignatureVerifier(); } return result; } /** - * Refreshes the internal cache of association(s) between {@link JwkDefinition} and {@link SignatureVerifier}. + * 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 mapped to it's {@link JwkDefinition}. + * 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 */ - void refreshJwkDefinitions() { + static Map loadJwkDefinitions(URL jwkSetUrl) { InputStream jwkSetSource; try { - jwkSetSource = this.jwkSetUrl.openStream(); + 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 = this.jwkSetConverter.convert(jwkSetSource); + Set jwkDefinitionSet = jwkSetConverter.convert(jwkSetSource); - Map refreshedJwkDefinitions = new LinkedHashMap(); + Map jwkDefinitions = new LinkedHashMap(); for (JwkDefinition jwkDefinition : jwkDefinitionSet) { if (JwkDefinition.KeyType.RSA.equals(jwkDefinition.getKeyType())) { - refreshedJwkDefinitions.put(jwkDefinition, this.createRSAVerifier((RSAJwkDefinition)jwkDefinition)); + jwkDefinitions.put(jwkDefinition.getKeyId(), + new JwkDefinitionHolder(jwkDefinition, createRsaVerifier((RsaJwkDefinition) jwkDefinition))); } } - this.jwkDefinitions.set(refreshedJwkDefinitions); + return jwkDefinitions; } - private RsaVerifier createRSAVerifier(RSAJwkDefinition rsaDefinition) { + private static RsaVerifier createRsaVerifier(RsaJwkDefinition rsaDefinition) { RsaVerifier result; try { BigInteger modulus = new BigInteger(Codecs.b64UrlDecode(rsaDefinition.getModulus())); @@ -157,4 +159,22 @@ private RsaVerifier createRSAVerifier(RSAJwkDefinition rsaDefinition) { } 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 index f47ef672a..1d3211dfb 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2016 the original author or authors. + * 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. 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 index 2a31e37b6..e0284261c 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2016 the original author or authors. + * 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. @@ -119,20 +119,21 @@ private JwkDefinition createJwkDefinition(Map attributes) { if (!JwkDefinition.KeyType.RSA.equals(keyType)) { throw new JwkException((keyType != null ? keyType.value() : "unknown") + - " (" + KEY_TYPE + ") is currently not supported."); + " (" + KEY_TYPE + ") is currently not supported." + + " Valid values for '" + KEY_TYPE + "' are: " + JwkDefinition.KeyType.RSA.value()); } - return this.createRSAJwkDefinition(attributes); + return this.createRsaJwkDefinition(attributes); } /** - * Creates a {@link RSAJwkDefinition} based on the supplied attributes. + * Creates a {@link RsaJwkDefinition} based on the supplied attributes. * - * @param attributes the attributes used to create the {@link RSAJwkDefinition} + * @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) { + private JwkDefinition createRsaJwkDefinition(Map attributes) { // kid String keyId = attributes.get(KEY_ID); if (!StringUtils.hasText(keyId)) { @@ -169,7 +170,7 @@ private JwkDefinition createRSAJwkDefinition(Map attributes) { throw new JwkException(RSA_PUBLIC_KEY_EXPONENT + " is a required attribute for a RSA JWK."); } - RSAJwkDefinition jwkDefinition = new RSAJwkDefinition( + RsaJwkDefinition jwkDefinition = new RsaJwkDefinition( keyId, publicKeyUse, algorithm, modulus, exponent); return jwkDefinition; 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 index 1f62f6467..85706ba4a 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2016 the original author or authors. + * 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. @@ -15,7 +15,6 @@ */ package org.springframework.security.oauth2.provider.token.store.jwk; -import org.springframework.security.jwt.crypto.sign.SignatureVerifier; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2RefreshToken; import org.springframework.security.oauth2.provider.OAuth2Authentication; @@ -60,19 +59,19 @@ *
    * * This implementation delegates to an internal instance of a {@link JwtTokenStore} which uses a - * specialized extension of {@link JwtAccessTokenConverter}, specifically, {@link JwkVerifyingJwtAccessTokenConverter}. - * The {@link JwkVerifyingJwtAccessTokenConverter} is associated with a {@link JwkDefinitionSource} which is responsible - * for fetching (and caching) the JWK Set (a set of JWKs) from the URL supplied to the constructor of this implementation. + * 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 JwkVerifyingJwtAccessTokenConverter} will verify the JWS in the following step sequence: + * The {@link JwtAccessTokenConverter} will verify the JWS in the following step sequence: *
    *
    *
      *
    1. Extract the "kid" parameter from the JWT header.
    2. - *
    3. Find the matching {@link JwkDefinition} from the {@link JwkDefinitionSource} with the corresponding "kid" attribute.
    4. - *
    5. Obtain the {@link SignatureVerifier} associated with the {@link JwkDefinition} via the {@link JwkDefinitionSource} and verify the signature.
    6. + *
    7. Find the matching JWK with the corresponding "kid" attribute.
    8. + *
    9. Obtain the SignatureVerifier associated with the JWK and verify the signature.
    10. *
    *
    * NOTE: The algorithms currently supported by this implementation are: RS256, RS384 and RS512. @@ -80,16 +79,13 @@ *
    * * @see JwtTokenStore - * @see JwkVerifyingJwtAccessTokenConverter - * @see JwkDefinitionSource - * @see JwkDefinition * @see JSON Web Key (JWK) * @see JSON Web Token (JWT) * @see JSON Web Signature (JWS) * * @author Joe Grandja */ -public class JwkTokenStore implements TokenStore { +public final class JwkTokenStore implements TokenStore { private final JwtTokenStore delegate; /** 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 index f9a1a7e35..431ade84a 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2016 the original author or authors. + * 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. @@ -100,7 +100,7 @@ protected Map decode(String token) { if (keyIdHeader == null) { throw new InvalidTokenException("Invalid JWT/JWS: " + KEY_ID + " is a required JOSE Header"); } - JwkDefinition jwkDefinition = this.jwkDefinitionSource.getDefinitionRefreshIfNecessary(keyIdHeader); + JwkDefinition jwkDefinition = this.jwkDefinitionSource.getDefinitionLoadIfNecessary(keyIdHeader); if (jwkDefinition == null) { throw new InvalidTokenException("Invalid JOSE Header " + KEY_ID + " (" + keyIdHeader + ")"); } 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 index 1fb2daf27..62981f33b 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2016 the original author or authors. + * 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. 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 similarity index 92% rename from spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/RSAJwkDefinition.java rename to spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/RsaJwkDefinition.java index d94ebfb6e..41655c7af 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2016 the original author or authors. + * 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. @@ -23,7 +23,7 @@ * * @author Joe Grandja */ -final class RSAJwkDefinition extends JwkDefinition { +final class RsaJwkDefinition extends JwkDefinition { private final String modulus; private final String exponent; @@ -36,7 +36,7 @@ final class RSAJwkDefinition extends JwkDefinition { * @param modulus the modulus value for the Public Key * @param exponent the exponent value for the Public Key */ - RSAJwkDefinition(String keyId, + RsaJwkDefinition(String keyId, PublicKeyUse publicKeyUse, CryptoAlgorithm algorithm, String modulus, 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 index 36b1bb459..75a545379 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2016 the original author or authors. + * 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. @@ -16,12 +16,23 @@ 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.*; -import static org.mockito.Mockito.*; /** - * @author jgrandja + * @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"; @@ -31,10 +42,11 @@ public void constructorWhenInvalidJwkSetUrlThenThrowIllegalArgumentException() t } @Test - public void getDefinitionRefreshIfNecessaryWhenKeyIdNotFoundThenRefreshJwkDefinitions() throws Exception { + public void getDefinitionLoadIfNecessaryWhenKeyIdNotFoundThenLoadJwkDefinitions() throws Exception { JwkDefinitionSource jwkDefinitionSource = spy(new JwkDefinitionSource(DEFAULT_JWK_SET_URL)); - doNothing().when(jwkDefinitionSource).refreshJwkDefinitions(); - jwkDefinitionSource.getDefinitionRefreshIfNecessary("invalid-key-id"); - verify(jwkDefinitionSource).refreshJwkDefinitions(); + 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 index 834f9e559..233385aeb 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2016 the original author or authors. + * 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. @@ -31,7 +31,7 @@ import static org.springframework.security.oauth2.provider.token.store.jwk.JwkAttributes.KEYS; /** - * @author jgrandja + * @author Joe Grandja */ public class JwkSetConverterTest { private final JwkSetConverter converter = new JwkSetConverter(); 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 index 34353d37d..28ea3b528 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2016 the original author or authors. + * 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. @@ -15,73 +15,139 @@ */ package org.springframework.security.oauth2.provider.token.store.jwk; -import org.junit.Before; 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 jgrandja + * @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(); - @Before - public void setUp() throws Exception { - this.thrown.expect(JwkException.class); - this.thrown.expectMessage("This operation is not supported."); + @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 index a27db63f8..3c830838e 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2016 the original author or authors. + * 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. @@ -26,7 +26,7 @@ import static org.springframework.security.oauth2.provider.token.store.jwk.JwtTestUtil.createJwtHeader; /** - * @author jgrandja + * @author Joe Grandja */ public class JwkVerifyingJwtAccessTokenConverterTest { @@ -58,7 +58,7 @@ public void decodeWhenKeyIdHeaderInvalidThenThrowJwkException() throws Exception 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.getDefinitionRefreshIfNecessary("key-id-1")).thenReturn(jwkDefinition); + when(jwkDefinitionSource.getDefinitionLoadIfNecessary("key-id-1")).thenReturn(jwkDefinition); JwkVerifyingJwtAccessTokenConverter accessTokenConverter = new JwkVerifyingJwtAccessTokenConverter(jwkDefinitionSource); String jwt = createJwt(createJwtHeader("invalid-key-id", JwkDefinition.CryptoAlgorithm.RS256)); @@ -71,7 +71,7 @@ public void decodeWhenAlgorithmHeaderMissingThenThrowJwkException() throws Excep 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.getDefinitionRefreshIfNecessary("key-id-1")).thenReturn(jwkDefinition); + when(jwkDefinitionSource.getDefinitionLoadIfNecessary("key-id-1")).thenReturn(jwkDefinition); JwkVerifyingJwtAccessTokenConverter accessTokenConverter = new JwkVerifyingJwtAccessTokenConverter(jwkDefinitionSource); String jwt = createJwt(createJwtHeader("key-id-1", null)); @@ -85,7 +85,7 @@ public void decodeWhenAlgorithmHeaderDoesNotMatchJwkAlgorithmThenThrowJwkExcepti "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.getDefinitionRefreshIfNecessary("key-id-1")).thenReturn(jwkDefinition); + when(jwkDefinitionSource.getDefinitionLoadIfNecessary("key-id-1")).thenReturn(jwkDefinition); JwkVerifyingJwtAccessTokenConverter accessTokenConverter = new JwkVerifyingJwtAccessTokenConverter(jwkDefinitionSource); String jwt = createJwt(createJwtHeader("key-id-1", JwkDefinition.CryptoAlgorithm.RS512)); @@ -104,6 +104,6 @@ private JwkDefinition createRSAJwkDefinition(JwkDefinition.KeyType keyType, String modulus, String exponent) { - return new RSAJwkDefinition(keyId, publicKeyUse, algorithm, modulus, 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 index f652e61c7..a7689d5c3 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2016 the original author or authors. + * 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. @@ -27,7 +27,7 @@ import static org.springframework.security.oauth2.provider.token.store.jwk.JwtTestUtil.createJwt; /** - * @author jgrandja + * @author Joe Grandja */ public class JwtHeaderConverterTest { private final JwtHeaderConverter converter = new JwtHeaderConverter(); 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 index b8df0e87b..5aab5d5e9 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2016 the original author or authors. + * 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. 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 From 220183d8cf56860cddae2def4efdb1a552b60d69 Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Wed, 1 Mar 2017 19:59:41 -0500 Subject: [PATCH 567/831] Release version 2.1.0.RELEASE --- pom.xml | 2 +- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- tests/annotation/approval/pom.xml | 2 +- tests/annotation/client/pom.xml | 2 +- tests/annotation/common/pom.xml | 2 +- tests/annotation/custom-authentication/pom.xml | 2 +- tests/annotation/custom-grant/pom.xml | 2 +- tests/annotation/form/pom.xml | 2 +- tests/annotation/jaxb/pom.xml | 2 +- tests/annotation/jdbc/pom.xml | 2 +- tests/annotation/jpa/pom.xml | 2 +- tests/annotation/jwt/pom.xml | 2 +- tests/annotation/mappings/pom.xml | 2 +- tests/annotation/multi/pom.xml | 2 +- tests/annotation/pom.xml | 4 ++-- tests/annotation/resource/pom.xml | 2 +- tests/annotation/ssl/pom.xml | 2 +- tests/annotation/vanilla/pom.xml | 2 +- tests/pom.xml | 2 +- tests/xml/approval/pom.xml | 2 +- tests/xml/client/pom.xml | 2 +- tests/xml/common/pom.xml | 2 +- tests/xml/form/pom.xml | 2 +- tests/xml/jdbc/pom.xml | 2 +- tests/xml/jwt/pom.xml | 2 +- tests/xml/mappings/pom.xml | 2 +- tests/xml/pom.xml | 4 ++-- tests/xml/vanilla/pom.xml | 2 +- 34 files changed, 36 insertions(+), 36 deletions(-) diff --git a/pom.xml b/pom.xml index 3d5e79f56..bd0477f35 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.0.RELEASE http://static.springframework.org/spring-security/oauth diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index 4cc3debd2..91e000ecd 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.0.RELEASE ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index 570abf329..6d48cf227 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.0.RELEASE ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index fa285f8af..cca907196 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.0.RELEASE ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 1131e00b1..5c5de38d2 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.0.RELEASE ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index 2c56b940a..2ff069739 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.0.RELEASE spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index 7dd4a4c1d..aa4bbe97a 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.0.RELEASE spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 4949b5ba2..cd9cd7c0e 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.0.RELEASE spring-security-oauth2 diff --git a/tests/annotation/approval/pom.xml b/tests/annotation/approval/pom.xml index 2dc67ad4d..02a45f1a3 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.0.RELEASE diff --git a/tests/annotation/client/pom.xml b/tests/annotation/client/pom.xml index 555854c6d..8854f5fab 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.0.RELEASE diff --git a/tests/annotation/common/pom.xml b/tests/annotation/common/pom.xml index ec1d24e93..f67e73cd5 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.0.RELEASE diff --git a/tests/annotation/custom-authentication/pom.xml b/tests/annotation/custom-authentication/pom.xml index f2f8cb481..d524766ee 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.0.RELEASE diff --git a/tests/annotation/custom-grant/pom.xml b/tests/annotation/custom-grant/pom.xml index 3ef3ac2de..1f1c65f98 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.0.RELEASE diff --git a/tests/annotation/form/pom.xml b/tests/annotation/form/pom.xml index 311156648..c6baa174e 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.0.RELEASE diff --git a/tests/annotation/jaxb/pom.xml b/tests/annotation/jaxb/pom.xml index 05fc8f4cd..5d2bc2cd1 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.0.RELEASE diff --git a/tests/annotation/jdbc/pom.xml b/tests/annotation/jdbc/pom.xml index b38274a78..51c136659 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.0.RELEASE diff --git a/tests/annotation/jpa/pom.xml b/tests/annotation/jpa/pom.xml index b82319fc0..a7ba7a4ac 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.0.RELEASE diff --git a/tests/annotation/jwt/pom.xml b/tests/annotation/jwt/pom.xml index 6d92b9026..e2364ddee 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.0.RELEASE diff --git a/tests/annotation/mappings/pom.xml b/tests/annotation/mappings/pom.xml index 8346ed914..b2b1a2765 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.0.RELEASE diff --git a/tests/annotation/multi/pom.xml b/tests/annotation/multi/pom.xml index e2634b7c1..25cee2368 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.0.RELEASE diff --git a/tests/annotation/pom.xml b/tests/annotation/pom.xml index 6f139dded..ebb378cf7 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.0.RELEASE pom @@ -39,7 +39,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.0.13.BUILD-SNAPSHOT + 2.1.0.RELEASE jackson-mapper-asl diff --git a/tests/annotation/resource/pom.xml b/tests/annotation/resource/pom.xml index 6d3b500f1..bbe5e3288 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.0.RELEASE diff --git a/tests/annotation/ssl/pom.xml b/tests/annotation/ssl/pom.xml index 13dbe9cd3..3c2ae4c67 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.0.RELEASE diff --git a/tests/annotation/vanilla/pom.xml b/tests/annotation/vanilla/pom.xml index 590597180..99dd26ae0 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.0.RELEASE diff --git a/tests/pom.xml b/tests/pom.xml index 4d58bbcb0..770460930 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.0.RELEASE spring-security-oauth-tests diff --git a/tests/xml/approval/pom.xml b/tests/xml/approval/pom.xml index f66b6a0f6..9c209c065 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.0.RELEASE diff --git a/tests/xml/client/pom.xml b/tests/xml/client/pom.xml index 349d602a2..b604409eb 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.0.RELEASE diff --git a/tests/xml/common/pom.xml b/tests/xml/common/pom.xml index 654689b20..f4b5da6e3 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.0.RELEASE diff --git a/tests/xml/form/pom.xml b/tests/xml/form/pom.xml index e6302c055..83f7a4481 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.0.RELEASE diff --git a/tests/xml/jdbc/pom.xml b/tests/xml/jdbc/pom.xml index e777afb3d..bd3ef53f1 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.0.RELEASE diff --git a/tests/xml/jwt/pom.xml b/tests/xml/jwt/pom.xml index 965689999..17fe67982 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.0.RELEASE diff --git a/tests/xml/mappings/pom.xml b/tests/xml/mappings/pom.xml index 84d9a32d9..9297aebc1 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.0.RELEASE diff --git a/tests/xml/pom.xml b/tests/xml/pom.xml index 421c0c48a..21fa83142 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.0.RELEASE pom @@ -33,7 +33,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.0.13.BUILD-SNAPSHOT + 2.1.0.RELEASE jackson-mapper-asl diff --git a/tests/xml/vanilla/pom.xml b/tests/xml/vanilla/pom.xml index f64a2d1f2..3f3ffe999 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.0.RELEASE From 5dbb8a220ea45a9053638d50975d1b41a9c6ca5f Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Thu, 2 Mar 2017 17:46:55 -0500 Subject: [PATCH 568/831] Next development version --- pom.xml | 2 +- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- tests/annotation/approval/pom.xml | 2 +- tests/annotation/client/pom.xml | 2 +- tests/annotation/common/pom.xml | 2 +- tests/annotation/custom-authentication/pom.xml | 2 +- tests/annotation/custom-grant/pom.xml | 2 +- tests/annotation/form/pom.xml | 2 +- tests/annotation/jaxb/pom.xml | 2 +- tests/annotation/jdbc/pom.xml | 2 +- tests/annotation/jpa/pom.xml | 2 +- tests/annotation/jwt/pom.xml | 2 +- tests/annotation/mappings/pom.xml | 2 +- tests/annotation/multi/pom.xml | 2 +- tests/annotation/pom.xml | 4 ++-- tests/annotation/resource/pom.xml | 2 +- tests/annotation/ssl/pom.xml | 2 +- tests/annotation/vanilla/pom.xml | 2 +- tests/pom.xml | 2 +- tests/xml/approval/pom.xml | 2 +- tests/xml/client/pom.xml | 2 +- tests/xml/common/pom.xml | 2 +- tests/xml/form/pom.xml | 2 +- tests/xml/jdbc/pom.xml | 2 +- tests/xml/jwt/pom.xml | 2 +- tests/xml/mappings/pom.xml | 2 +- tests/xml/pom.xml | 4 ++-- tests/xml/vanilla/pom.xml | 2 +- 34 files changed, 36 insertions(+), 36 deletions(-) diff --git a/pom.xml b/pom.xml index bd0477f35..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.1.0.RELEASE + 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 91e000ecd..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.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index 6d48cf227..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.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index cca907196..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.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 5c5de38d2..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.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index 2ff069739..96c07851c 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index aa4bbe97a..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.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index cd9cd7c0e..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.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT spring-security-oauth2 diff --git a/tests/annotation/approval/pom.xml b/tests/annotation/approval/pom.xml index 02a45f1a3..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.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT diff --git a/tests/annotation/client/pom.xml b/tests/annotation/client/pom.xml index 8854f5fab..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.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT diff --git a/tests/annotation/common/pom.xml b/tests/annotation/common/pom.xml index f67e73cd5..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.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT diff --git a/tests/annotation/custom-authentication/pom.xml b/tests/annotation/custom-authentication/pom.xml index d524766ee..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.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT diff --git a/tests/annotation/custom-grant/pom.xml b/tests/annotation/custom-grant/pom.xml index 1f1c65f98..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.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT diff --git a/tests/annotation/form/pom.xml b/tests/annotation/form/pom.xml index c6baa174e..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.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT diff --git a/tests/annotation/jaxb/pom.xml b/tests/annotation/jaxb/pom.xml index 5d2bc2cd1..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.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT diff --git a/tests/annotation/jdbc/pom.xml b/tests/annotation/jdbc/pom.xml index 51c136659..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.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT diff --git a/tests/annotation/jpa/pom.xml b/tests/annotation/jpa/pom.xml index a7ba7a4ac..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.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT diff --git a/tests/annotation/jwt/pom.xml b/tests/annotation/jwt/pom.xml index e2364ddee..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.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT diff --git a/tests/annotation/mappings/pom.xml b/tests/annotation/mappings/pom.xml index b2b1a2765..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.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT diff --git a/tests/annotation/multi/pom.xml b/tests/annotation/multi/pom.xml index 25cee2368..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.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT diff --git a/tests/annotation/pom.xml b/tests/annotation/pom.xml index ebb378cf7..065a54434 100644 --- a/tests/annotation/pom.xml +++ b/tests/annotation/pom.xml @@ -4,7 +4,7 @@ org.demo spring-oauth2-tests-parent - 2.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT pom @@ -39,7 +39,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT jackson-mapper-asl diff --git a/tests/annotation/resource/pom.xml b/tests/annotation/resource/pom.xml index bbe5e3288..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.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT diff --git a/tests/annotation/ssl/pom.xml b/tests/annotation/ssl/pom.xml index 3c2ae4c67..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.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT diff --git a/tests/annotation/vanilla/pom.xml b/tests/annotation/vanilla/pom.xml index 99dd26ae0..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.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT diff --git a/tests/pom.xml b/tests/pom.xml index 770460930..234e3141c 100644 --- a/tests/pom.xml +++ b/tests/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT spring-security-oauth-tests diff --git a/tests/xml/approval/pom.xml b/tests/xml/approval/pom.xml index 9c209c065..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.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT diff --git a/tests/xml/client/pom.xml b/tests/xml/client/pom.xml index b604409eb..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.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT diff --git a/tests/xml/common/pom.xml b/tests/xml/common/pom.xml index f4b5da6e3..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.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT diff --git a/tests/xml/form/pom.xml b/tests/xml/form/pom.xml index 83f7a4481..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.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT diff --git a/tests/xml/jdbc/pom.xml b/tests/xml/jdbc/pom.xml index bd3ef53f1..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.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT diff --git a/tests/xml/jwt/pom.xml b/tests/xml/jwt/pom.xml index 17fe67982..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.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT diff --git a/tests/xml/mappings/pom.xml b/tests/xml/mappings/pom.xml index 9297aebc1..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.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT diff --git a/tests/xml/pom.xml b/tests/xml/pom.xml index 21fa83142..887dca74e 100644 --- a/tests/xml/pom.xml +++ b/tests/xml/pom.xml @@ -4,7 +4,7 @@ org.demo spring-oauth2-tests-xml-parent - 2.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT pom @@ -33,7 +33,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT jackson-mapper-asl diff --git a/tests/xml/vanilla/pom.xml b/tests/xml/vanilla/pom.xml index 3f3ffe999..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.1.0.RELEASE + 2.1.1.BUILD-SNAPSHOT From 0651688c5ef21c85a3a58576380b04870c47b12c Mon Sep 17 00:00:00 2001 From: Guillaume Wallet Date: Wed, 8 Mar 2017 08:07:42 +0100 Subject: [PATCH 569/831] Read RSA PK modulus/exponent as unsigned int from JWK Fixes gh-1010 --- .../token/store/jwk/JwkDefinitionSource.java | 4 +- .../store/jwk/JwkDefinitionSourceTest.java | 37 +++++++++++++++++++ .../provider/token/store/jwk/jwk-set.json | 12 ++++++ .../oauth2/provider/token/store/jwk/token.jwt | 1 + 4 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/provider/token/store/jwk/jwk-set.json create mode 100644 spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/provider/token/store/jwk/token.jwt 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 index de643ff03..08ea6f807 100644 --- 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 @@ -145,8 +145,8 @@ static Map loadJwkDefinitions(URL jwkSetUrl) { 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())); + BigInteger modulus = new BigInteger(1, Codecs.b64UrlDecode(rsaDefinition.getModulus())); + BigInteger exponent = new BigInteger(1, Codecs.b64UrlDecode(rsaDefinition.getExponent())); RSAPublicKey rsaPublicKey = (RSAPublicKey) KeyFactory.getInstance("RSA") .generatePublic(new RSAPublicKeySpec(modulus, exponent)); 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 index 75a545379..195531157 100644 --- 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 @@ -15,11 +15,16 @@ */ package org.springframework.security.oauth2.provider.token.store.jwk; +import org.apache.commons.codec.Charsets; import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; +import org.springframework.security.jwt.codec.Codecs; +import org.springframework.security.jwt.crypto.sign.SignatureVerifier; +import java.io.IOException; +import java.io.InputStream; import java.net.URL; import java.util.Collections; @@ -49,4 +54,36 @@ public void getDefinitionLoadIfNecessaryWhenKeyIdNotFoundThenLoadJwkDefinitions( jwkDefinitionSource.getDefinitionLoadIfNecessary("invalid-key-id"); verifyStatic(); } + + // gh-1010 + @Test + public void getVerifierWhenModulusMostSignificantBitIs1ThenVerifierStillVerifyContentSignature() throws Exception { + String jwkSetUrl = JwkDefinitionSourceTest.class.getResource("jwk-set.json").toString(); + JwkDefinitionSource jwkDefinitionSource = new JwkDefinitionSource(jwkSetUrl); + SignatureVerifier verifier = jwkDefinitionSource.getVerifier("_Ci3-VfV_N0YAG22NQOgOUpFBDDcDe_rJxpu5JK702o"); + String token = this.readToken("token.jwt"); + int secondPeriodIndex = token.indexOf('.', token.indexOf('.') + 1); + String contentString = token.substring(0, secondPeriodIndex); + byte[] content = contentString.getBytes(Charsets.UTF_8); + String signatureString = token.substring(secondPeriodIndex + 1); + byte[] signature = Codecs.b64UrlDecode(signatureString); + verifier.verify(content, signature); + } + + private String readToken(String resource) throws IOException { + StringBuilder sb = new StringBuilder(); + InputStream in = null; + try { + in = JwkDefinitionSourceTest.class.getResourceAsStream(resource); + int ch; + while ((ch = in.read()) != -1) { + sb.append((char) ch); + } + } finally { + if (in != null) { + in.close(); + } + } + return sb.toString(); + } } \ No newline at end of file diff --git a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/provider/token/store/jwk/jwk-set.json b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/provider/token/store/jwk/jwk-set.json new file mode 100644 index 000000000..4879780fe --- /dev/null +++ b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/provider/token/store/jwk/jwk-set.json @@ -0,0 +1,12 @@ +{ + "keys": [ + { + "kid": "_Ci3-VfV_N0YAG22NQOgOUpFBDDcDe_rJxpu5JK702o", + "kty": "RSA", + "alg": "RS256", + "use": "sig", + "n": "rne3dowbQHcFCzg2ejWb6az5QNxWFiv6kRpd34VDzYNMhWeewfeEL5Pf5clE8Xh1KlllrDYSxtnzUQm-t9p92yEBASfV96ydTYG-ITfxfJzKtJUN-iIS5K9WGYXnDNS4eYZ_ygW-zBU_9NwFMXdwSTzRqHeJmLJrfbmmjoIuuWyfh2Ko52KzyidceR5SJxGeW0ckeyWka1lDf4cr7fv-s093Y_sd2wrNvg0-9IAkXotbxWWXcfMgXFyw0qHFT_5LrKmiwkY3HCaiV5NgEFJmC6fBIG2EOZG4rqjBoYV6LZwrfTMHknaeel9MOZesW6SR2bswtuuWN3DGq2zg0KamLw", + "e": "AQAB" + } + ] +} diff --git a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/provider/token/store/jwk/token.jwt b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/provider/token/store/jwk/token.jwt new file mode 100644 index 000000000..72469e7e0 --- /dev/null +++ b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/provider/token/store/jwk/token.jwt @@ -0,0 +1 @@ +eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJfQ2kzLVZmVl9OMFlBRzIyTlFPZ09VcEZCRERjRGVfckp4cHU1Sks3MDJvIn0.eyJqdGkiOiIzOWQxMmU1NC00MjliLTRkZjUtOTM2OS01YWVlOTFkNzAwZjgiLCJleHAiOjE0ODg5MDk1NzMsIm5iZiI6MCwiaWF0IjoxNDg4OTA5MjczLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgxODAvYXV0aC9yZWFsbXMvRGVtbyIsImF1ZCI6ImJvb3QtYXBwIiwic3ViIjoiNGM5NjE5NDQtN2VkZC00ZDZiLTg2MGUtYmJiZGNhODk0MDU4IiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiYm9vdC1hcHAiLCJhdXRoX3RpbWUiOjE0ODg5MDkyNzMsInNlc3Npb25fc3RhdGUiOiJiMjdjMDZlNi02ODgwLTQxZTEtOTM2MS1jZmEzYzY2ZjYyNjAiLCJhY3IiOiIxIiwiY2xpZW50X3Nlc3Npb24iOiIyYjA5NTFiOC1iMjdkLTRlYWMtYjUxOC1kZTQ5OTA5OTY2ZDgiLCJhbGxvd2VkLW9yaWdpbnMiOltdLCJyZXNvdXJjZV9hY2Nlc3MiOnsiYm9vdC1hcGkiOnsicm9sZXMiOlsiYm9vdC1hcGktcm9sZSJdfSwiYm9vdC1hcHAiOnsicm9sZXMiOlsiYm9vdC1yb2xlIl19fSwibmFtZSI6IkFsaWNlICIsInByZWZlcnJlZF91c2VybmFtZSI6ImFsaWNlIiwiZ2l2ZW5fbmFtZSI6IkFsaWNlIiwiZmFtaWx5X25hbWUiOiIiLCJlbWFpbCI6ImFsaWNlQGV4YW1wbGUubmV0In0.NfF5rPMabu8gaigUHZnX3gIzNGAxKpmPP206U5keNtexNqsmQEFO4KT2i1JYLwvNVFnRWCa8FmYokAtzeHgLvHk2B8CZXqL6GSMGQ26wPS5RIFTak9HjfHMhodqSIdy4wZTKmEcum_uYTaCdrVRSfWU8l94xAY6OzwElZX5ulkucvgWQnpFs0HB7X54kB07OqpN8L3i1jeQoEV0iJchtxZiEOSipqMNO7cujMqB_6lf9i78URPuyExfeLzAWyDbMWSJBp3zUoS7HakwE_4oC3eVEYTxDtMRL2yl2_8R0C0g2Dc0Qb9aezFxo3-SDNuy9aicDmibEEOpIoetlrIYbNA \ No newline at end of file From 536de80971a74f76e9eebef921cbdadc5144d46c Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Mon, 8 May 2017 15:46:13 -0400 Subject: [PATCH 570/831] Call delegate when JwkTokenStore.removeAccessToken() called Fixes gh-1055 --- .../token/store/jwk/JwkTokenStore.java | 7 +++---- .../token/store/jwk/JwkTokenStoreTest.java | 19 ++++++++++++++----- 2 files changed, 17 insertions(+), 9 deletions(-) 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 index 85706ba4a..f021b5536 100644 --- 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 @@ -146,14 +146,13 @@ public OAuth2AccessToken readAccessToken(String tokenValue) { } /** - * This operation is not applicable for a Resource Server - * and if called, will throw a {@link JwkException}. + * Delegates to the internal instance {@link JwtTokenStore#removeAccessToken(OAuth2AccessToken)}. * - * @throws JwkException reporting this operation is not supported + * @param token the access token */ @Override public void removeAccessToken(OAuth2AccessToken token) { - throw this.operationNotSupported(); + this.delegate.removeAccessToken(token); } /** 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 index 28ea3b528..d6914ad5d 100644 --- 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 @@ -87,15 +87,24 @@ public void readAccessTokenWhenCalledThenDelegateCalled() throws Exception { } @Test - public void storeAccessTokenWhenCalledThenThrowJwkException() throws Exception { - this.setUpExpectedJwkException(); - this.jwkTokenStore.storeAccessToken(null, null); + public void removeAccessTokenWhenCalledThenDelegateCalled() throws Exception { + JwkTokenStore spy = spy(this.jwkTokenStore); + JwtTokenStore delegate = mock(JwtTokenStore.class); + + doNothing().when(delegate).removeAccessToken(any(OAuth2AccessToken.class)); + + Field field = ReflectionUtils.findField(spy.getClass(), "delegate"); + field.setAccessible(true); + ReflectionUtils.setField(field, spy, delegate); + + spy.removeAccessToken(any(OAuth2AccessToken.class)); + verify(delegate).removeAccessToken(any(OAuth2AccessToken.class)); } @Test - public void removeAccessTokenWhenCalledThenThrowJwkException() throws Exception { + public void storeAccessTokenWhenCalledThenThrowJwkException() throws Exception { this.setUpExpectedJwkException(); - this.jwkTokenStore.removeAccessToken(null); + this.jwkTokenStore.storeAccessToken(null, null); } @Test From 3ae2d7ee966406b8fdb6de33ca160e92a71aef78 Mon Sep 17 00:00:00 2001 From: denis Date: Thu, 15 Sep 2016 20:49:23 -0300 Subject: [PATCH 571/831] Fix NPE on evicted authentication Fixes gh-844 --- .../token/store/redis/RedisTokenStore.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/redis/RedisTokenStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/redis/RedisTokenStore.java index 343326c2b..fb3708f3c 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/redis/RedisTokenStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/redis/RedisTokenStore.java @@ -97,12 +97,15 @@ public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) { conn.close(); } OAuth2AccessToken accessToken = deserializeAccessToken(bytes); - if (accessToken != null - && !key.equals(authenticationKeyGenerator.extractKey(readAuthentication(accessToken.getValue())))) { - // Keep the stores consistent (maybe the same user is - // represented by this authentication but the details have - // changed) - storeAccessToken(accessToken, authentication); + if (accessToken != null) { + OAuth2Authentication storedAuthentication = readAuthentication(accessToken.getValue()); + if ((storedAuthentication == null || !key.equals(authenticationKeyGenerator.extractKey(storedAuthentication)))) { + // Keep the stores consistent (maybe the same user is + // represented by this authentication but the details have + // changed) + storeAccessToken(accessToken, authentication); + } + } return accessToken; } From 1cb6ce40d9d2a2524b1f8473989d7459a8e5bb81 Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Fri, 12 May 2017 10:29:07 -0400 Subject: [PATCH 572/831] Upgrade bcpkix-jdk15on to 1.5.6 Fixes gh-1046 --- spring-security-jwt/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-security-jwt/pom.xml b/spring-security-jwt/pom.xml index 12aaf8300..49db4c907 100755 --- a/spring-security-jwt/pom.xml +++ b/spring-security-jwt/pom.xml @@ -29,7 +29,7 @@ org.bouncycastle bcpkix-jdk15on - 1.55 + 1.56 From b418cab1f64c3a3dd6def25c75c9fcea26b19b53 Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Mon, 15 May 2017 12:02:56 -0400 Subject: [PATCH 573/831] CheckTokenEndpoint returns 'active' attribute Fixes gh-1070 --- .../provider/endpoint/CheckTokenEndpoint.java | 9 ++- .../endpoint/CheckTokenEndpointTest.java | 64 +++++++++++++++++++ 2 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/CheckTokenEndpointTest.java diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/CheckTokenEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/CheckTokenEndpoint.java index 8c2315614..0639f893c 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/CheckTokenEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/CheckTokenEndpoint.java @@ -12,8 +12,6 @@ *******************************************************************************/ package org.springframework.security.oauth2.provider.endpoint; -import java.util.Map; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.http.ResponseEntity; @@ -31,6 +29,8 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; +import java.util.Map; + /** * Controller which decodes access tokens for clients who are not able to do so (or where opaque token values are used). * @@ -81,7 +81,10 @@ public void setAccessTokenConverter(AccessTokenConverter accessTokenConverter) { OAuth2Authentication authentication = resourceServerTokenServices.loadAuthentication(token.getValue()); - Map response = accessTokenConverter.convertAccessToken(token, authentication); + Map response = (Map)accessTokenConverter.convertAccessToken(token, authentication); + + // gh-1070 + response.put("active", true); // Always true if token exists and not expired return response; } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/CheckTokenEndpointTest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/CheckTokenEndpointTest.java new file mode 100644 index 000000000..87fc2ffb7 --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/CheckTokenEndpointTest.java @@ -0,0 +1,64 @@ +/* + * 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.endpoint; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.token.AccessTokenConverter; +import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * @author Joe Grandja + */ +public class CheckTokenEndpointTest { + private CheckTokenEndpoint checkTokenEndpoint; + + @Before + public void setUp() { + ResourceServerTokenServices resourceServerTokenServices = mock(ResourceServerTokenServices.class); + OAuth2AccessToken accessToken = mock(OAuth2AccessToken.class); + OAuth2Authentication authentication = mock(OAuth2Authentication.class); + when(resourceServerTokenServices.readAccessToken(anyString())).thenReturn(accessToken); + when(accessToken.isExpired()).thenReturn(false); + when(accessToken.getValue()).thenReturn("access-token-1234"); + when(resourceServerTokenServices.loadAuthentication(accessToken.getValue())).thenReturn(authentication); + this.checkTokenEndpoint = new CheckTokenEndpoint(resourceServerTokenServices); + + AccessTokenConverter accessTokenConverter = mock(AccessTokenConverter.class); + when(accessTokenConverter.convertAccessToken(accessToken, authentication)).thenReturn(new HashMap()); + this.checkTokenEndpoint.setAccessTokenConverter(accessTokenConverter); + } + + // gh-1070 + @Test + public void checkTokenWhenTokenValidThenReturnActiveAttribute() throws Exception { + Map response = this.checkTokenEndpoint.checkToken("access-token-1234"); + Object active = response.get("active"); + assertNotNull("active is null", active); + assertEquals("active not true", Boolean.TRUE, active); + } +} \ No newline at end of file From f1a9b976389672ff94dfe697d8315256eabc5bf3 Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Fri, 12 May 2017 17:19:50 -0400 Subject: [PATCH 574/831] RemoteTokenServices validates 'active' attribute Fixes gh-838 --- .../provider/token/RemoteTokenServices.java | 8 +- .../token/RemoteTokenServicesTest.java | 92 +++++++++++++++++++ 2 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/RemoteTokenServicesTest.java diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/RemoteTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/RemoteTokenServices.java index e0ba9c525..9af98ab6e 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/RemoteTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/RemoteTokenServices.java @@ -24,7 +24,6 @@ import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.util.Assert; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.DefaultResponseErrorHandler; @@ -111,7 +110,12 @@ public OAuth2Authentication loadAuthentication(String accessToken) throws Authen throw new InvalidTokenException(accessToken); } - Assert.state(map.containsKey("client_id"), "Client id must be present in response from auth server"); + // gh-838 + if (!Boolean.TRUE.equals(map.get("active"))) { + logger.debug("check_token returned active attribute: " + map.get("active")); + throw new InvalidTokenException(accessToken); + } + return tokenConverter.extractAuthentication(map); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/RemoteTokenServicesTest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/RemoteTokenServicesTest.java new file mode 100644 index 000000000..709755ff5 --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/RemoteTokenServicesTest.java @@ -0,0 +1,92 @@ +/* + * 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; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.web.client.RestTemplate; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertNotNull; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * @author Joe Grandja + */ +public class RemoteTokenServicesTest { + private static final String DEFAULT_CLIENT_ID = "client-id-1234"; + private static final String DEFAULT_CLIENT_SECRET = "client-secret-1234"; + private static final String DEFAULT_CHECK_TOKEN_ENDPOINT_URI = "/oauth/check_token"; + private RemoteTokenServices remoteTokenServices; + + @Before + public void setUp() { + this.remoteTokenServices = new RemoteTokenServices(); + this.remoteTokenServices.setClientId(DEFAULT_CLIENT_ID); + this.remoteTokenServices.setClientSecret(DEFAULT_CLIENT_SECRET); + this.remoteTokenServices.setCheckTokenEndpointUrl(DEFAULT_CHECK_TOKEN_ENDPOINT_URI); + } + + // gh-838 + @Test + public void loadAuthenticationWhenIntrospectionResponseContainsActiveTrueThenReturnAuthentication() throws Exception { + Map responseAttrs = new HashMap(); + responseAttrs.put("active", true); // "active" is the only required attribute as per RFC 7662 (https://tools.ietf.org/search/rfc7662#section-2.2) + ResponseEntity response = new ResponseEntity(responseAttrs, HttpStatus.OK); + RestTemplate restTemplate = mock(RestTemplate.class); + when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(HttpEntity.class), any(Class.class))).thenReturn(response); + this.remoteTokenServices.setRestTemplate(restTemplate); + + OAuth2Authentication authentication = this.remoteTokenServices.loadAuthentication("access-token-1234"); + assertNotNull(authentication); + } + + // gh-838 + @Test(expected = InvalidTokenException.class) + public void loadAuthenticationWhenIntrospectionResponseContainsActiveFalseThenThrowInvalidTokenException() throws Exception { + Map responseAttrs = new HashMap(); + responseAttrs.put("active", false); // "active" is the only required attribute as per RFC 7662 (https://tools.ietf.org/search/rfc7662#section-2.2) + ResponseEntity response = new ResponseEntity(responseAttrs, HttpStatus.OK); + RestTemplate restTemplate = mock(RestTemplate.class); + when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(HttpEntity.class), any(Class.class))).thenReturn(response); + this.remoteTokenServices.setRestTemplate(restTemplate); + + this.remoteTokenServices.loadAuthentication("access-token-1234"); + } + + // gh-838 + @Test(expected = InvalidTokenException.class) + public void loadAuthenticationWhenIntrospectionResponseMissingActiveAttributeThenThrowInvalidTokenException() throws Exception { + Map responseAttrs = new HashMap(); + ResponseEntity response = new ResponseEntity(responseAttrs, HttpStatus.OK); + RestTemplate restTemplate = mock(RestTemplate.class); + when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(HttpEntity.class), any(Class.class))).thenReturn(response); + this.remoteTokenServices.setRestTemplate(restTemplate); + + this.remoteTokenServices.loadAuthentication("access-token-1234"); + } +} \ No newline at end of file From e286111e4f6665f16eacdd5b781c5bf21a5f3477 Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Tue, 9 May 2017 14:34:43 -0400 Subject: [PATCH 575/831] Build against Spring Framework 5 Fixes gh-1069 --- pom.xml | 86 +++++++++++++------ samples/oauth2/sparklr/pom.xml | 17 +++- .../AuthorizationCodeProviderTests.java | 19 +--- .../provider/ImplicitProviderTests.java | 29 +++---- samples/oauth2/tonr/pom.xml | 17 +++- spring-security-oauth/pom.xml | 19 +++- .../security/oauth/config/ConfigUtils.java | 16 +++- ...erverBeanDefinitionParserTests-context.xml | 2 +- ...rviceBeanDefinitionParserTests-context.xml | 2 +- ...FilterChainInitializationTests-context.xml | 2 +- spring-security-oauth2/pom.xml | 23 ++++- .../token/DefaultAccessTokenRequest.java | 6 ++ .../oauth2/config/xml/ConfigUtils.java | 15 +++- .../OAuth2ClientContextFilterTests.java | 10 ++- .../token/OAuth2AccessTokenSupportTests.java | 4 + ...ccessTokenProviderWithConversionTests.java | 4 + .../client/BaseClientDetailsTests.java | 3 +- .../error/OAuth2AccessDeniedHandlerTests.java | 3 +- .../OAuth2AuthenticationEntryPointTests.java | 4 +- ...er-client-credentials-password-invalid.xml | 25 +++++- ...rver-client-credentials-password-valid.xml | 25 +++++- 21 files changed, 241 insertions(+), 90 deletions(-) diff --git a/pom.xml b/pom.xml index b05c742dc..3c797edbb 100644 --- a/pom.xml +++ b/pom.xml @@ -162,6 +162,64 @@ + + springframework-build + + 5.0.0.BUILD-SNAPSHOT + 4.2.3.BUILD-SNAPSHOT + + + + repo.spring.io-milestone + Spring Framework Milestone Repository + http://repo.spring.io/libs-milestone-local + + + repo.spring.io-snapshot + Spring Framework Maven Snapshot Repository + http://repo.spring.io/libs-snapshot-local + true + + + + + default + + true + + + + + org.codehaus.mojo + animal-sniffer-maven-plugin + 1.6 + + + org.codehaus.mojo.signature + java16 + 1.0 + + + + + enforce-java-6 + test + + check + + + + + sun.net.www.protocol.http.* + sun.net.www.protocol.https.* + + + + + + + + @@ -314,34 +372,6 @@ - - - org.codehaus.mojo - animal-sniffer-maven-plugin - 1.6 - - - org.codehaus.mojo.signature - java16 - 1.0 - - - - - enforce-java-6 - test - - check - - - - - sun.net.www.protocol.http.* - sun.net.www.protocol.https.* - - - - - 3.0.1 + ${servlet-api.version} true junit junit - 4.11 + ${junit.version} test diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/ConfigUtils.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/ConfigUtils.java index 2f2b8e434..7d5e17c96 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/ConfigUtils.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/ConfigUtils.java @@ -1,5 +1,6 @@ package org.springframework.security.oauth.config; +import java.lang.reflect.Method; import java.util.Collections; import java.util.List; @@ -13,16 +14,23 @@ import org.springframework.security.config.BeanIds; import org.springframework.security.config.http.MatcherType; import org.springframework.security.web.access.intercept.DefaultFilterInvocationSecurityMetadataSource; +import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; + /** * Common place for OAuth namespace configuration utils. * * @author Ryan Heaton */ public class ConfigUtils { + private static final Method createMatcherMethod3x = ReflectionUtils.findMethod( + MatcherType.class, "createMatcher", String.class, String.class); + private static final Method createMatcherMethod4x = ReflectionUtils.findMethod( + MatcherType.class, "createMatcher", ParserContext.class, String.class, String.class); + private ConfigUtils() { } @@ -56,7 +64,13 @@ public static BeanDefinition createSecurityMetadataSource(Element element, Parse String access = filterPattern.getAttribute("resources"); if (StringUtils.hasText(access)) { - BeanDefinition matcher = matcherType.createMatcher(path, method); + BeanDefinition matcher; + if (createMatcherMethod4x != null) { + matcher = (BeanDefinition)ReflectionUtils.invokeMethod(createMatcherMethod4x, matcherType, pc, path, method); + } else { + matcher = (BeanDefinition)ReflectionUtils.invokeMethod(createMatcherMethod3x, matcherType, path, method); + } + if (access.equals("none")) { invocationDefinitionMap.put(matcher, BeanDefinitionBuilder.rootBeanDefinition(Collections.class).setFactoryMethod("emptyList").getBeanDefinition()); } diff --git a/spring-security-oauth/src/test/resources/org/springframework/security/oauth/config/AuthorizationServerBeanDefinitionParserTests-context.xml b/spring-security-oauth/src/test/resources/org/springframework/security/oauth/config/AuthorizationServerBeanDefinitionParserTests-context.xml index 3cfacc02d..74ae58447 100644 --- a/spring-security-oauth/src/test/resources/org/springframework/security/oauth/config/AuthorizationServerBeanDefinitionParserTests-context.xml +++ b/spring-security-oauth/src/test/resources/org/springframework/security/oauth/config/AuthorizationServerBeanDefinitionParserTests-context.xml @@ -6,7 +6,7 @@ http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd http://www.springframework.org/schema/security/oauth http://www.springframework.org/schema/security/spring-security-oauth-1.0.xsd"> - + diff --git a/spring-security-oauth/src/test/resources/org/springframework/security/oauth/config/ConsumerServiceBeanDefinitionParserTests-context.xml b/spring-security-oauth/src/test/resources/org/springframework/security/oauth/config/ConsumerServiceBeanDefinitionParserTests-context.xml index 6a00a1361..a80ba48ba 100644 --- a/spring-security-oauth/src/test/resources/org/springframework/security/oauth/config/ConsumerServiceBeanDefinitionParserTests-context.xml +++ b/spring-security-oauth/src/test/resources/org/springframework/security/oauth/config/ConsumerServiceBeanDefinitionParserTests-context.xml @@ -6,7 +6,7 @@ http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd http://www.springframework.org/schema/security/oauth http://www.springframework.org/schema/security/spring-security-oauth-1.0.xsd"> - + diff --git a/spring-security-oauth/src/test/resources/org/springframework/security/oauth/config/FilterChainInitializationTests-context.xml b/spring-security-oauth/src/test/resources/org/springframework/security/oauth/config/FilterChainInitializationTests-context.xml index dd55adb30..4ee38a579 100644 --- a/spring-security-oauth/src/test/resources/org/springframework/security/oauth/config/FilterChainInitializationTests-context.xml +++ b/spring-security-oauth/src/test/resources/org/springframework/security/oauth/config/FilterChainInitializationTests-context.xml @@ -10,7 +10,7 @@ - + diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index a850142f0..c0a1b9813 100644 --- a/spring-security-oauth2/pom.xml +++ b/spring-security-oauth2/pom.xml @@ -15,9 +15,24 @@ 1.9.13 2.3.2 + 3.0.1 1.0.2.RELEASE + 4.11 + 1.5.4 + + + springframework-build + + 2.9.0.pr3 + 3.1.0 + 4.12 + 1.6.1 + + + + @@ -59,7 +74,7 @@ javax.servlet javax.servlet-api - 3.0.1 + ${servlet-api.version} true @@ -181,7 +196,7 @@ junit junit - 4.11 + ${junit.version} compile true @@ -189,14 +204,14 @@ org.powermock powermock-module-junit4 - 1.5.4 + ${powermock.version} test org.powermock powermock-api-mockito - 1.5.4 + ${powermock.version} test diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/DefaultAccessTokenRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/DefaultAccessTokenRequest.java index 559e02e9c..c40154ca3 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/DefaultAccessTokenRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/DefaultAccessTokenRequest.java @@ -139,6 +139,12 @@ public void add(String key, String value) { parameters.add(key, value); } + public void addAll(String key, List values) { + for (String value : values) { + this.add(key, value); + } + } + public void set(String key, String value) { parameters.set(key, value); } diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ConfigUtils.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ConfigUtils.java index 88004ef60..77fde32c3 100755 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ConfigUtils.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ConfigUtils.java @@ -1,5 +1,6 @@ package org.springframework.security.oauth2.config.xml; +import java.lang.reflect.Method; import java.util.Collections; import java.util.List; @@ -13,6 +14,7 @@ import org.springframework.security.config.BeanIds; import org.springframework.security.config.http.MatcherType; import org.springframework.security.web.access.intercept.DefaultFilterInvocationSecurityMetadataSource; +import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; @@ -23,6 +25,11 @@ * @author Ryan Heaton */ public class ConfigUtils { + private static final Method createMatcherMethod3x = ReflectionUtils.findMethod( + MatcherType.class, "createMatcher", String.class, String.class); + private static final Method createMatcherMethod4x = ReflectionUtils.findMethod( + MatcherType.class, "createMatcher", ParserContext.class, String.class, String.class); + private ConfigUtils() { } @@ -57,7 +64,13 @@ public static BeanDefinition createSecurityMetadataSource(Element element, Parse String access = filterPattern.getAttribute("resources"); if (StringUtils.hasText(access)) { - BeanDefinition matcher = matcherType.createMatcher(path, method); + BeanDefinition matcher; + if (createMatcherMethod4x != null) { + matcher = (BeanDefinition)ReflectionUtils.invokeMethod(createMatcherMethod4x, matcherType, pc, path, method); + } else { + matcher = (BeanDefinition)ReflectionUtils.invokeMethod(createMatcherMethod3x, matcherType, path, method); + } + if (access.equals("none")) { invocationDefinitionMap.put(matcher, BeanDefinitionBuilder.rootBeanDefinition(Collections.class).setFactoryMethod("emptyList").getBeanDefinition()); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilterTests.java index ed10052c6..d0938781a 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientContextFilterTests.java @@ -125,6 +125,14 @@ public void testCurrentUriWithInvalidQueryString() throws Exception { OAuth2ClientContextFilter filter = new OAuth2ClientContextFilter(); MockHttpServletRequest request = new MockHttpServletRequest(); request.setQueryString("foo=bar&code=XXXX&parm=%xx"); - assertEquals(null, filter.calculateCurrentUri(request)); + try { + assertEquals(null, filter.calculateCurrentUri(request)); + } catch (IllegalStateException ex) { + // OAuth2ClientContextFilter.calculateCurrentUri() internally uses + // ServletUriComponentsBuilder.fromRequest(), which behaves differently in Spring Framework 5 + // and throws an IllegalStateException for a malformed URI. + // Previous to Spring Framework 5, 'null' would be returned by OAuth2ClientContextFilter.calculateCurrentUri() + // instead of the thrown IllegalStateException. + } } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/OAuth2AccessTokenSupportTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/OAuth2AccessTokenSupportTests.java index 924f68b78..783df39e0 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/OAuth2AccessTokenSupportTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/OAuth2AccessTokenSupportTests.java @@ -187,6 +187,10 @@ public HttpMethod getMethod() { return HttpMethod.GET; } + public String getMethodValue() { + return getMethod().name(); + } + public URI getURI() { return null; } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProviderWithConversionTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProviderWithConversionTests.java index 568a2ebee..bf09ee61e 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProviderWithConversionTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProviderWithConversionTests.java @@ -103,6 +103,10 @@ public HttpMethod getMethod() { return HttpMethod.POST; } + public String getMethodValue() { + return getMethod().name(); + } + public ClientHttpResponse execute() throws IOException { return new ClientHttpResponse() { diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/BaseClientDetailsTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/BaseClientDetailsTests.java index 9ea52d430..d80e9b773 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/BaseClientDetailsTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/BaseClientDetailsTests.java @@ -21,6 +21,7 @@ import static org.junit.Assert.assertTrue; import java.util.Collections; +import java.util.TreeSet; import org.codehaus.jackson.map.ObjectMapper; import org.junit.Test; @@ -52,7 +53,7 @@ public void testBaseClientDetailsDefaultConstructor() { public void testBaseClientDetailsConvenienceConstructor() { BaseClientDetails details = new BaseClientDetails("foo", "", "foo,bar", "authorization_code", "ROLE_USER"); assertEquals("[]", details.getResourceIds().toString()); - assertEquals("[bar, foo]", details.getScope().toString()); + assertEquals("[bar, foo]", new TreeSet(details.getScope()).toString()); assertEquals("[authorization_code]", details.getAuthorizedGrantTypes().toString()); assertEquals("[ROLE_USER]", details.getAuthorities().toString()); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/OAuth2AccessDeniedHandlerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/OAuth2AccessDeniedHandlerTests.java index 969c1c8d5..b03239049 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/OAuth2AccessDeniedHandlerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/OAuth2AccessDeniedHandlerTests.java @@ -13,6 +13,7 @@ package org.springframework.security.oauth2.provider.error; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import javax.servlet.http.HttpServletResponse; @@ -39,7 +40,7 @@ public void testHandleWithJson() throws Exception { request.addHeader("Accept", MediaType.APPLICATION_JSON_VALUE); handler.handle(request, response, new AccessDeniedException("Bad")); assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus()); - assertEquals(MediaType.APPLICATION_JSON_VALUE, response.getContentType()); + assertTrue(response.getContentType().contains(MediaType.APPLICATION_JSON_VALUE)); assertEquals(null, response.getErrorMessage()); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/OAuth2AuthenticationEntryPointTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/OAuth2AuthenticationEntryPointTests.java index 7c437cfc6..cba776763 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/OAuth2AuthenticationEntryPointTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/OAuth2AuthenticationEntryPointTests.java @@ -46,7 +46,7 @@ public void testCommenceWithJson() throws Exception { entryPoint.commence(request, response, new BadCredentialsException("Bad")); assertEquals(HttpServletResponse.SC_UNAUTHORIZED, response.getStatus()); assertEquals("{\"error\":\"unauthorized\",\"error_description\":\"Bad\"}", response.getContentAsString()); - assertEquals(MediaType.APPLICATION_JSON_VALUE, response.getContentType()); + assertTrue(response.getContentType().contains(MediaType.APPLICATION_JSON_VALUE)); assertEquals(null, response.getErrorMessage()); } @@ -57,7 +57,7 @@ public void testCommenceWithOAuth2Exception() throws Exception { "Bad client"))); assertEquals(HttpServletResponse.SC_UNAUTHORIZED, response.getStatus()); assertEquals("{\"error\":\"invalid_client\",\"error_description\":\"Bad client\"}", response.getContentAsString()); - assertEquals(MediaType.APPLICATION_JSON_VALUE, response.getContentType()); + assertTrue(response.getContentType().contains(MediaType.APPLICATION_JSON_VALUE)); assertEquals(null, response.getErrorMessage()); } diff --git a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-client-credentials-password-invalid.xml b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-client-credentials-password-invalid.xml index 1ec6e2d06..e488b9719 100644 --- a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-client-credentials-password-invalid.xml +++ b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-client-credentials-password-invalid.xml @@ -4,9 +4,9 @@ xmlns:b="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:oauth2="http://www.springframework.org/schema/security/oauth2" - xsi:schemaLocation="http://www.springframework.org/schema/security%20http://www.springframework.org/schema/security/spring-security-3.2.xsd-http://www.springframework.org/schema/beans%20http://www.springframework.org/schema/beans/spring-beans-4.0.xsd-http://www.springframework.org/schema/mvc%20http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd+%20xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2.xsd"> + + + + + + + diff --git a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-client-credentials-password-valid.xml b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-client-credentials-password-valid.xml index 1622316b3..ead090030 100644 --- a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-client-credentials-password-valid.xml +++ b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-client-credentials-password-valid.xml @@ -4,15 +4,34 @@ xmlns:b="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:oauth2="http://www.springframework.org/schema/security/oauth2" - xsi:schemaLocation="http://www.springframework.org/schema/security%20http://www.springframework.org/schema/security/spring-security-3.2.xsd-http://www.springframework.org/schema/beans%20http://www.springframework.org/schema/beans/spring-beans-4.0.xsd-http://www.springframework.org/schema/mvc%20http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd+%20xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2.xsd"> + + + + + + + From f065d8d4d39e4113a9b58bba9911a15a668e3324 Mon Sep 17 00:00:00 2001 From: liumian Date: Thu, 6 Apr 2017 16:17:52 +0800 Subject: [PATCH 576/831] Fix typo Fixes gh-1037 --- .../config/annotation/web/configuration/EnableOAuth2Client.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableOAuth2Client.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableOAuth2Client.java index 30abe3155..b19b31858 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableOAuth2Client.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableOAuth2Client.java @@ -46,7 +46,7 @@ * * Client apps that use client credentials grants do not need the AccessTokenRequest or the scoped RestOperations (the * state is global for the app), but they should still use the filter to trigger the OAuth2RestOperations to obtain a - * token when necessary. Apps that us password grants need to set the authentication properties in the + * token when necessary. Apps that use password grants need to set the authentication properties in the * OAuth2ProtectedResourceDetails before using the RestOperations, and this means the resource details themselves also * have to be per session (assuming there are multiple users in the system). * From a2ced3977de350bf6f7ad1ba9d0bfc23d39dc300 Mon Sep 17 00:00:00 2001 From: Nick Ebbitt Date: Thu, 25 May 2017 16:31:48 +0100 Subject: [PATCH 577/831] Fix minor typo Fixes gh-1075 --- docs/oauth2.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/oauth2.md b/docs/oauth2.md index 3d14228ef..12c6f88a0 100644 --- a/docs/oauth2.md +++ b/docs/oauth2.md @@ -153,7 +153,7 @@ A Resource Server (can be the same as the Authorization Server or a separate app * `tokenServices`: the bean that defines the token services (instance of `ResourceServerTokenServices`). * `resourceId`: the id for the resource (optional, but recommended and will be validated by the auth server if present). -* other extension points for the resourecs server (e.g. `tokenExtractor` for extracting the tokens from incoming requests) +* other extension points for the resources server (e.g. `tokenExtractor` for extracting the tokens from incoming requests) * request matchers for protected resources (defaults to all) * access rules for protected resources (defaults to plain "authenticated") * other customizations for the protected resources permitted by the `HttpSecurity` configurer in Spring Security From 8da411576b1b8b34c1445d74d498b5c60b7835b3 Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Mon, 29 May 2017 12:48:26 -0400 Subject: [PATCH 578/831] Revert to snapshots for JWT --- spring-security-jwt/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-security-jwt/pom.xml b/spring-security-jwt/pom.xml index 49db4c907..75334b89c 100755 --- a/spring-security-jwt/pom.xml +++ b/spring-security-jwt/pom.xml @@ -5,7 +5,7 @@ org.springframework.security spring-security-jwt - 1.0.8.RELEASE + 1.0.9.BUILD-SNAPSHOT jar Spring Security JWT Library From d8eb4f4bc54d7c42aa63dc15b14689016d2639b8 Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Mon, 29 May 2017 12:53:07 -0400 Subject: [PATCH 579/831] Upgrade spring.security.jwt to 1.0.8.RELEASE Fixes gh-1078 --- spring-security-oauth2/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index c0a1b9813..6cf25a7d0 100644 --- a/spring-security-oauth2/pom.xml +++ b/spring-security-oauth2/pom.xml @@ -16,7 +16,7 @@ 1.9.13 2.3.2 3.0.1 - 1.0.2.RELEASE + 1.0.8.RELEASE 4.11 1.5.4 From 0d9036078cfb672726cf64f9c1e26845b9bb4e19 Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Mon, 29 May 2017 14:28:21 -0400 Subject: [PATCH 580/831] Release version 2.1.1.RELEASE --- pom.xml | 2 +- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- tests/annotation/approval/pom.xml | 2 +- tests/annotation/client/pom.xml | 2 +- tests/annotation/common/pom.xml | 2 +- tests/annotation/custom-authentication/pom.xml | 2 +- tests/annotation/custom-grant/pom.xml | 2 +- tests/annotation/form/pom.xml | 2 +- tests/annotation/jaxb/pom.xml | 2 +- tests/annotation/jdbc/pom.xml | 2 +- tests/annotation/jpa/pom.xml | 2 +- tests/annotation/jwt/pom.xml | 2 +- tests/annotation/mappings/pom.xml | 2 +- tests/annotation/multi/pom.xml | 2 +- tests/annotation/pom.xml | 4 ++-- tests/annotation/resource/pom.xml | 2 +- tests/annotation/ssl/pom.xml | 2 +- tests/annotation/vanilla/pom.xml | 2 +- tests/pom.xml | 2 +- tests/xml/approval/pom.xml | 2 +- tests/xml/client/pom.xml | 2 +- tests/xml/common/pom.xml | 2 +- tests/xml/form/pom.xml | 2 +- tests/xml/jdbc/pom.xml | 2 +- tests/xml/jwt/pom.xml | 2 +- tests/xml/mappings/pom.xml | 2 +- tests/xml/pom.xml | 4 ++-- tests/xml/vanilla/pom.xml | 2 +- 34 files changed, 36 insertions(+), 36 deletions(-) diff --git a/pom.xml b/pom.xml index 3c797edbb..13ea1b49e 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.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE http://static.springframework.org/spring-security/oauth diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index d5985dc6d..4088bf30b 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.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index 283337497..eb226ffaa 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.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 78dee58c1..a06ab465c 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.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 99a03f865..254eb2d18 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.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index 96c07851c..22738da3a 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index a4a443e91..41a4ebcfe 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.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 6cf25a7d0..c21552b4e 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.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE spring-security-oauth2 diff --git a/tests/annotation/approval/pom.xml b/tests/annotation/approval/pom.xml index d1110a48a..1ce4602ba 100644 --- a/tests/annotation/approval/pom.xml +++ b/tests/annotation/approval/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE diff --git a/tests/annotation/client/pom.xml b/tests/annotation/client/pom.xml index d2aebd623..660ddcbcf 100644 --- a/tests/annotation/client/pom.xml +++ b/tests/annotation/client/pom.xml @@ -11,7 +11,7 @@ org.demo spring-oauth2-tests-parent - 2.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE diff --git a/tests/annotation/common/pom.xml b/tests/annotation/common/pom.xml index dc24d1048..45f5808d3 100644 --- a/tests/annotation/common/pom.xml +++ b/tests/annotation/common/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE diff --git a/tests/annotation/custom-authentication/pom.xml b/tests/annotation/custom-authentication/pom.xml index 38884d6b4..1ed46534d 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.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE diff --git a/tests/annotation/custom-grant/pom.xml b/tests/annotation/custom-grant/pom.xml index 648084bea..3eb8aff49 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.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE diff --git a/tests/annotation/form/pom.xml b/tests/annotation/form/pom.xml index 0170024a6..fbaeaad8f 100644 --- a/tests/annotation/form/pom.xml +++ b/tests/annotation/form/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE diff --git a/tests/annotation/jaxb/pom.xml b/tests/annotation/jaxb/pom.xml index 6b76b5c08..047c77594 100644 --- a/tests/annotation/jaxb/pom.xml +++ b/tests/annotation/jaxb/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE diff --git a/tests/annotation/jdbc/pom.xml b/tests/annotation/jdbc/pom.xml index 2035871b8..096db4420 100644 --- a/tests/annotation/jdbc/pom.xml +++ b/tests/annotation/jdbc/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE diff --git a/tests/annotation/jpa/pom.xml b/tests/annotation/jpa/pom.xml index e973072a1..d078b5a00 100644 --- a/tests/annotation/jpa/pom.xml +++ b/tests/annotation/jpa/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE diff --git a/tests/annotation/jwt/pom.xml b/tests/annotation/jwt/pom.xml index 46c3a4609..b5e857820 100644 --- a/tests/annotation/jwt/pom.xml +++ b/tests/annotation/jwt/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE diff --git a/tests/annotation/mappings/pom.xml b/tests/annotation/mappings/pom.xml index eff643328..0effeda91 100644 --- a/tests/annotation/mappings/pom.xml +++ b/tests/annotation/mappings/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE diff --git a/tests/annotation/multi/pom.xml b/tests/annotation/multi/pom.xml index 554119314..f1125d231 100644 --- a/tests/annotation/multi/pom.xml +++ b/tests/annotation/multi/pom.xml @@ -9,7 +9,7 @@ org.demo spring-oauth2-tests-parent - 2.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE diff --git a/tests/annotation/pom.xml b/tests/annotation/pom.xml index 065a54434..f0a0a86f6 100644 --- a/tests/annotation/pom.xml +++ b/tests/annotation/pom.xml @@ -4,7 +4,7 @@ org.demo spring-oauth2-tests-parent - 2.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE pom @@ -39,7 +39,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE jackson-mapper-asl diff --git a/tests/annotation/resource/pom.xml b/tests/annotation/resource/pom.xml index df34736a2..d9b8e1085 100644 --- a/tests/annotation/resource/pom.xml +++ b/tests/annotation/resource/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE diff --git a/tests/annotation/ssl/pom.xml b/tests/annotation/ssl/pom.xml index 9a6a8a01a..468dff9df 100644 --- a/tests/annotation/ssl/pom.xml +++ b/tests/annotation/ssl/pom.xml @@ -11,7 +11,7 @@ org.demo spring-oauth2-tests-parent - 2.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE diff --git a/tests/annotation/vanilla/pom.xml b/tests/annotation/vanilla/pom.xml index 7b31b952a..15786f50b 100644 --- a/tests/annotation/vanilla/pom.xml +++ b/tests/annotation/vanilla/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE diff --git a/tests/pom.xml b/tests/pom.xml index 234e3141c..a5bfe7081 100644 --- a/tests/pom.xml +++ b/tests/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE spring-security-oauth-tests diff --git a/tests/xml/approval/pom.xml b/tests/xml/approval/pom.xml index c8569a5d2..aa10af282 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.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE diff --git a/tests/xml/client/pom.xml b/tests/xml/client/pom.xml index 049f30793..56ddda8f4 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.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE diff --git a/tests/xml/common/pom.xml b/tests/xml/common/pom.xml index 4d15848f3..42200fbb6 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.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE diff --git a/tests/xml/form/pom.xml b/tests/xml/form/pom.xml index 37d5a50f7..a023d5cff 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.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE diff --git a/tests/xml/jdbc/pom.xml b/tests/xml/jdbc/pom.xml index 1c130362a..cf061bfdf 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.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE diff --git a/tests/xml/jwt/pom.xml b/tests/xml/jwt/pom.xml index 0275e803f..37b428f04 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.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE diff --git a/tests/xml/mappings/pom.xml b/tests/xml/mappings/pom.xml index f55d557c9..06a77ddb1 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.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE diff --git a/tests/xml/pom.xml b/tests/xml/pom.xml index 887dca74e..e714a052c 100644 --- a/tests/xml/pom.xml +++ b/tests/xml/pom.xml @@ -4,7 +4,7 @@ org.demo spring-oauth2-tests-xml-parent - 2.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE pom @@ -33,7 +33,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE jackson-mapper-asl diff --git a/tests/xml/vanilla/pom.xml b/tests/xml/vanilla/pom.xml index abe8c9fa1..aaeac2fea 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.1.1.BUILD-SNAPSHOT + 2.1.1.RELEASE From 064dbfdc6883792475dffe08142b19b309d5c602 Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Mon, 29 May 2017 15:04:22 -0400 Subject: [PATCH 581/831] Next development version --- pom.xml | 2 +- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- tests/annotation/approval/pom.xml | 2 +- tests/annotation/client/pom.xml | 2 +- tests/annotation/common/pom.xml | 2 +- tests/annotation/custom-authentication/pom.xml | 2 +- tests/annotation/custom-grant/pom.xml | 2 +- tests/annotation/form/pom.xml | 2 +- tests/annotation/jaxb/pom.xml | 2 +- tests/annotation/jdbc/pom.xml | 2 +- tests/annotation/jpa/pom.xml | 2 +- tests/annotation/jwt/pom.xml | 2 +- tests/annotation/mappings/pom.xml | 2 +- tests/annotation/multi/pom.xml | 2 +- tests/annotation/pom.xml | 4 ++-- tests/annotation/resource/pom.xml | 2 +- tests/annotation/ssl/pom.xml | 2 +- tests/annotation/vanilla/pom.xml | 2 +- tests/pom.xml | 2 +- tests/xml/approval/pom.xml | 2 +- tests/xml/client/pom.xml | 2 +- tests/xml/common/pom.xml | 2 +- tests/xml/form/pom.xml | 2 +- tests/xml/jdbc/pom.xml | 2 +- tests/xml/jwt/pom.xml | 2 +- tests/xml/mappings/pom.xml | 2 +- tests/xml/pom.xml | 4 ++-- tests/xml/vanilla/pom.xml | 2 +- 34 files changed, 36 insertions(+), 36 deletions(-) diff --git a/pom.xml b/pom.xml index 13ea1b49e..97aa98094 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.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT http://static.springframework.org/spring-security/oauth diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index 4088bf30b..dcda0323c 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.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index eb226ffaa..59466c233 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.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index a06ab465c..9b164fea9 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.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 254eb2d18..bf5cb2ece 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.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index 22738da3a..72f07104a 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index 41a4ebcfe..09d4b53ca 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.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index c21552b4e..0a4ea9043 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.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT spring-security-oauth2 diff --git a/tests/annotation/approval/pom.xml b/tests/annotation/approval/pom.xml index 1ce4602ba..7223d7ded 100644 --- a/tests/annotation/approval/pom.xml +++ b/tests/annotation/approval/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT diff --git a/tests/annotation/client/pom.xml b/tests/annotation/client/pom.xml index 660ddcbcf..3177145df 100644 --- a/tests/annotation/client/pom.xml +++ b/tests/annotation/client/pom.xml @@ -11,7 +11,7 @@ org.demo spring-oauth2-tests-parent - 2.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT diff --git a/tests/annotation/common/pom.xml b/tests/annotation/common/pom.xml index 45f5808d3..b5228fd3c 100644 --- a/tests/annotation/common/pom.xml +++ b/tests/annotation/common/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT diff --git a/tests/annotation/custom-authentication/pom.xml b/tests/annotation/custom-authentication/pom.xml index 1ed46534d..ee50731b4 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.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT diff --git a/tests/annotation/custom-grant/pom.xml b/tests/annotation/custom-grant/pom.xml index 3eb8aff49..9da160286 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.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT diff --git a/tests/annotation/form/pom.xml b/tests/annotation/form/pom.xml index fbaeaad8f..0440ac9b8 100644 --- a/tests/annotation/form/pom.xml +++ b/tests/annotation/form/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT diff --git a/tests/annotation/jaxb/pom.xml b/tests/annotation/jaxb/pom.xml index 047c77594..7284a6484 100644 --- a/tests/annotation/jaxb/pom.xml +++ b/tests/annotation/jaxb/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT diff --git a/tests/annotation/jdbc/pom.xml b/tests/annotation/jdbc/pom.xml index 096db4420..7be66ab4b 100644 --- a/tests/annotation/jdbc/pom.xml +++ b/tests/annotation/jdbc/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT diff --git a/tests/annotation/jpa/pom.xml b/tests/annotation/jpa/pom.xml index d078b5a00..3b507b3e0 100644 --- a/tests/annotation/jpa/pom.xml +++ b/tests/annotation/jpa/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT diff --git a/tests/annotation/jwt/pom.xml b/tests/annotation/jwt/pom.xml index b5e857820..b90bafe6e 100644 --- a/tests/annotation/jwt/pom.xml +++ b/tests/annotation/jwt/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT diff --git a/tests/annotation/mappings/pom.xml b/tests/annotation/mappings/pom.xml index 0effeda91..a6081ed7d 100644 --- a/tests/annotation/mappings/pom.xml +++ b/tests/annotation/mappings/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT diff --git a/tests/annotation/multi/pom.xml b/tests/annotation/multi/pom.xml index f1125d231..c52287b17 100644 --- a/tests/annotation/multi/pom.xml +++ b/tests/annotation/multi/pom.xml @@ -9,7 +9,7 @@ org.demo spring-oauth2-tests-parent - 2.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT diff --git a/tests/annotation/pom.xml b/tests/annotation/pom.xml index f0a0a86f6..53994f7ac 100644 --- a/tests/annotation/pom.xml +++ b/tests/annotation/pom.xml @@ -4,7 +4,7 @@ org.demo spring-oauth2-tests-parent - 2.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT pom @@ -39,7 +39,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT jackson-mapper-asl diff --git a/tests/annotation/resource/pom.xml b/tests/annotation/resource/pom.xml index d9b8e1085..82f769f49 100644 --- a/tests/annotation/resource/pom.xml +++ b/tests/annotation/resource/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT diff --git a/tests/annotation/ssl/pom.xml b/tests/annotation/ssl/pom.xml index 468dff9df..1cbdc39d4 100644 --- a/tests/annotation/ssl/pom.xml +++ b/tests/annotation/ssl/pom.xml @@ -11,7 +11,7 @@ org.demo spring-oauth2-tests-parent - 2.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT diff --git a/tests/annotation/vanilla/pom.xml b/tests/annotation/vanilla/pom.xml index 15786f50b..edd058617 100644 --- a/tests/annotation/vanilla/pom.xml +++ b/tests/annotation/vanilla/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT diff --git a/tests/pom.xml b/tests/pom.xml index a5bfe7081..841e51a04 100644 --- a/tests/pom.xml +++ b/tests/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT spring-security-oauth-tests diff --git a/tests/xml/approval/pom.xml b/tests/xml/approval/pom.xml index aa10af282..4953e30d3 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.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT diff --git a/tests/xml/client/pom.xml b/tests/xml/client/pom.xml index 56ddda8f4..8fd60ec52 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.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT diff --git a/tests/xml/common/pom.xml b/tests/xml/common/pom.xml index 42200fbb6..72cf2b5ed 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.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT diff --git a/tests/xml/form/pom.xml b/tests/xml/form/pom.xml index a023d5cff..d3a8760a7 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.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT diff --git a/tests/xml/jdbc/pom.xml b/tests/xml/jdbc/pom.xml index cf061bfdf..6dbe9e847 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.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT diff --git a/tests/xml/jwt/pom.xml b/tests/xml/jwt/pom.xml index 37b428f04..24bf55f47 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.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT diff --git a/tests/xml/mappings/pom.xml b/tests/xml/mappings/pom.xml index 06a77ddb1..d4e718841 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.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT diff --git a/tests/xml/pom.xml b/tests/xml/pom.xml index e714a052c..b9f43c993 100644 --- a/tests/xml/pom.xml +++ b/tests/xml/pom.xml @@ -4,7 +4,7 @@ org.demo spring-oauth2-tests-xml-parent - 2.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT pom @@ -33,7 +33,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT jackson-mapper-asl diff --git a/tests/xml/vanilla/pom.xml b/tests/xml/vanilla/pom.xml index aaeac2fea..a856b7808 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.1.1.RELEASE + 2.1.2.BUILD-SNAPSHOT From 65f54ebc8b155b832b24786317cf55529dda95a9 Mon Sep 17 00:00:00 2001 From: Neale Upstone Date: Thu, 15 Jun 2017 09:00:12 +0100 Subject: [PATCH 582/831] JwkSetConverter should handle arrays Fixes gh-1082 --- .../token/store/jwk/JwkSetConverter.java | 10 +++++++--- .../token/store/jwk/JwkSetConverterTest.java | 19 ++++++++++++++++++- 2 files changed, 25 insertions(+), 4 deletions(-) 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 index e0284261c..e35dde176 100644 --- 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 @@ -83,9 +83,13 @@ public Set convert(InputStream jwkSetSource) { 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); + // gh-1082 - skip arrays such as x5c as we can't deal with them yet + if (parser.nextToken() == JsonToken.START_ARRAY) { + while (parser.nextToken() != JsonToken.END_ARRAY) { + } + } else { + attributes.put(attributeName, parser.getValueAsString()); + } } JwkDefinition jwkDefinition = this.createJwkDefinition(attributes); if (!jwkDefinitions.add(jwkDefinition)) { 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 index 233385aeb..9e250710b 100644 --- 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 @@ -199,7 +199,8 @@ public void convertWhenJwkSetStreamIsValidThenReturnJwkSet() throws Exception { 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"); + JwkDefinition.PublicKeyUse.SIG, JwkDefinition.CryptoAlgorithm.RS512, + "AMh-pGAj9vX2gwFDyrXot1f2YfHgh8h0Qx6w9IqLL", "AQAB", new String[] {"chain1", "chain2"}); jwkSetObject.put(JwkAttributes.KEYS, new Map[] {jwkObject, jwkObject2}); jwkSet = this.converter.convert(this.asInputStream(jwkSetObject)); assertNotNull(jwkSet); @@ -256,6 +257,17 @@ private Map createJwkObject(JwkDefinition.KeyType keyType, String rsaModulus, String rsaExponent) { + return this.createJwkObject(keyType, keyId, publicKeyUse, algorithm, rsaModulus, rsaExponent, null); + } + + private Map createJwkObject(JwkDefinition.KeyType keyType, + String keyId, + JwkDefinition.PublicKeyUse publicKeyUse, + JwkDefinition.CryptoAlgorithm algorithm, + String rsaModulus, + String rsaExponent, + String[] x5c) { + Map jwkObject = new HashMap(); jwkObject.put(JwkAttributes.KEY_TYPE, keyType.value()); if (keyId != null) { @@ -273,6 +285,11 @@ private Map createJwkObject(JwkDefinition.KeyType keyType, if (rsaExponent != null) { jwkObject.put(JwkAttributes.RSA_PUBLIC_KEY_EXPONENT, rsaExponent); } + // gh-1082 - parser should be able to handle arrays + if (x5c != null) { + // x5c (X.509 certificate chain) + jwkObject.put("x5c", x5c); + } return jwkObject; } From fe5df2f3e14ef9c276dfba72d951aa66416a59ce Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Mon, 26 Jun 2017 11:08:40 -0400 Subject: [PATCH 583/831] Resolve compile error Spring 5 MultiValueMap.addAll(MultiValueMap) Fixes gh-1100 --- .../token/DefaultAccessTokenRequest.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/DefaultAccessTokenRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/DefaultAccessTokenRequest.java index c40154ca3..90c445af1 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/DefaultAccessTokenRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/DefaultAccessTokenRequest.java @@ -15,17 +15,13 @@ */ package org.springframework.security.oauth2.client.token; -import java.io.Serializable; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; - import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; +import java.io.Serializable; +import java.util.*; + /** * Local context for an access token request encapsulating the parameters that are sent by the client requesting the * token, as opposed to the more static variables representing the client itself and the resource being targeted. @@ -139,12 +135,18 @@ public void add(String key, String value) { parameters.add(key, value); } - public void addAll(String key, List values) { + public void addAll(String key, List values) { for (String value : values) { this.add(key, value); } } + public void addAll(MultiValueMap map) { + for (Entry> entry : map.entrySet()) { + this.addAll(entry.getKey(), entry.getValue()); + } + } + public void set(String key, String value) { parameters.set(key, value); } From a9990f4b818a3ac399272e85a4e52d20e165f58b Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Mon, 26 Jun 2017 11:44:55 -0400 Subject: [PATCH 584/831] Add build profile against Spring Security 5 Fixes gh-1101 --- .travis.yml | 6 +++--- pom.xml | 4 ++-- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- ...ization-server-client-credentials-password-invalid.xml | 8 ++++---- ...orization-server-client-credentials-password-valid.xml | 8 ++++---- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.travis.yml b/.travis.yml index c6252a7c9..f960d5568 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,6 @@ services: - redis-server install: ./mvnw -U install --quiet -DskipTests=true -P bootstrap -script: ./mvnw clean test -P bootstrap - - +script: +- ./mvnw clean test -P bootstrap +- ./mvnw -U clean test -P spring5 diff --git a/pom.xml b/pom.xml index 97aa98094..dd1017546 100644 --- a/pom.xml +++ b/pom.xml @@ -163,10 +163,10 @@ - springframework-build + spring5 5.0.0.BUILD-SNAPSHOT - 4.2.3.BUILD-SNAPSHOT + 5.0.0.BUILD-SNAPSHOT diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 9b164fea9..e234b2f09 100644 --- a/samples/oauth2/sparklr/pom.xml +++ b/samples/oauth2/sparklr/pom.xml @@ -22,7 +22,7 @@ - springframework-build + spring5 2.9.0.pr3 3.1.0 diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index bf5cb2ece..b6974e11f 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -23,7 +23,7 @@ - springframework-build + spring5 2.9.0.pr3 3.1.0 diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index 09d4b53ca..e4524b481 100644 --- a/spring-security-oauth/pom.xml +++ b/spring-security-oauth/pom.xml @@ -18,7 +18,7 @@ - springframework-build + spring5 3.1.0 4.12 diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 0a4ea9043..dbb44ca47 100644 --- a/spring-security-oauth2/pom.xml +++ b/spring-security-oauth2/pom.xml @@ -23,7 +23,7 @@ - springframework-build + spring5 2.9.0.pr3 3.1.0 diff --git a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-client-credentials-password-invalid.xml b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-client-credentials-password-invalid.xml index e488b9719..5927e0a93 100644 --- a/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-client-credentials-password-invalid.xml +++ b/spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/xml/authorization-server-client-credentials-password-invalid.xml @@ -19,14 +19,14 @@ + +### Summary + + + +### Actual Behavior + + + +### Expected Behavior + + + +### Configuration + + + +### Version + + + +### Sample + + From be7e5c3dad9d3d13b845d222395000bcb92511f6 Mon Sep 17 00:00:00 2001 From: Rob Winch Date: Wed, 30 Jan 2019 11:09:21 -0600 Subject: [PATCH 664/831] Create PULL_REQUEST_TEMPLATE.md --- .github/PULL_REQUEST_TEMPLATE.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .github/PULL_REQUEST_TEMPLATE.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..70c6c946d --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,7 @@ + + + From 3927321fbf9e57a6093b1cef99b53dfa49575196 Mon Sep 17 00:00:00 2001 From: Fabien Crespel Date: Wed, 21 Nov 2018 17:25:23 +0100 Subject: [PATCH 665/831] Allow missing "active" field in check_token/introspect response. Also support both Boolean and String values for this field. Fixes gh-1533 --- .../provider/token/RemoteTokenServices.java | 2 +- .../token/RemoteTokenServicesTest.java | 22 +++++++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/RemoteTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/RemoteTokenServices.java index f6555613c..7ba183ad1 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/RemoteTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/RemoteTokenServices.java @@ -113,7 +113,7 @@ public OAuth2Authentication loadAuthentication(String accessToken) throws Authen } // gh-838 - if (!Boolean.TRUE.equals(map.get("active"))) { + if (map.containsKey("active") && !"true".equals(String.valueOf(map.get("active")))) { logger.debug("check_token returned active attribute: " + map.get("active")); throw new InvalidTokenException(accessToken); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/RemoteTokenServicesTest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/RemoteTokenServicesTest.java index 709755ff5..5d156fbeb 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/RemoteTokenServicesTest.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/RemoteTokenServicesTest.java @@ -53,7 +53,7 @@ public void setUp() { // gh-838 @Test - public void loadAuthenticationWhenIntrospectionResponseContainsActiveTrueThenReturnAuthentication() throws Exception { + public void loadAuthenticationWhenIntrospectionResponseContainsActiveTrueBooleanThenReturnAuthentication() throws Exception { Map responseAttrs = new HashMap(); responseAttrs.put("active", true); // "active" is the only required attribute as per RFC 7662 (https://tools.ietf.org/search/rfc7662#section-2.2) ResponseEntity response = new ResponseEntity(responseAttrs, HttpStatus.OK); @@ -65,6 +65,19 @@ public void loadAuthenticationWhenIntrospectionResponseContainsActiveTrueThenRet assertNotNull(authentication); } + @Test + public void loadAuthenticationWhenIntrospectionResponseContainsActiveTrueStringThenReturnAuthentication() throws Exception { + Map responseAttrs = new HashMap(); + responseAttrs.put("active", "true"); // "active" is the only required attribute as per RFC 7662 (https://tools.ietf.org/search/rfc7662#section-2.2) + ResponseEntity response = new ResponseEntity(responseAttrs, HttpStatus.OK); + RestTemplate restTemplate = mock(RestTemplate.class); + when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(HttpEntity.class), any(Class.class))).thenReturn(response); + this.remoteTokenServices.setRestTemplate(restTemplate); + + OAuth2Authentication authentication = this.remoteTokenServices.loadAuthentication("access-token-1234"); + assertNotNull(authentication); + } + // gh-838 @Test(expected = InvalidTokenException.class) public void loadAuthenticationWhenIntrospectionResponseContainsActiveFalseThenThrowInvalidTokenException() throws Exception { @@ -79,14 +92,15 @@ public void loadAuthenticationWhenIntrospectionResponseContainsActiveFalseThenTh } // gh-838 - @Test(expected = InvalidTokenException.class) - public void loadAuthenticationWhenIntrospectionResponseMissingActiveAttributeThenThrowInvalidTokenException() throws Exception { + @Test + public void loadAuthenticationWhenIntrospectionResponseMissingActiveAttributeThenReturnAuthentication() throws Exception { Map responseAttrs = new HashMap(); ResponseEntity response = new ResponseEntity(responseAttrs, HttpStatus.OK); RestTemplate restTemplate = mock(RestTemplate.class); when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(HttpEntity.class), any(Class.class))).thenReturn(response); this.remoteTokenServices.setRestTemplate(restTemplate); - this.remoteTokenServices.loadAuthentication("access-token-1234"); + OAuth2Authentication authentication = this.remoteTokenServices.loadAuthentication("access-token-1234"); + assertNotNull(authentication); } } \ No newline at end of file From ec78c7ba22e4c321ba24ff3b2b9f354faa212a7d Mon Sep 17 00:00:00 2001 From: Michael Holtermann Date: Sat, 12 Jan 2019 21:11:58 +0100 Subject: [PATCH 666/831] Log generic Exceptions to ERROR with stack trace Log Exceptions to ERROR. Protocol Exceptions are treated in separate ExceptionHandlers, but generic Exceptions like NPEs must be logged with full stack trace Fixes gh-1545 --- .../security/oauth2/provider/endpoint/TokenEndpoint.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java index af46865d5..2fb806176 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java @@ -165,8 +165,8 @@ public ResponseEntity handleHttpRequestMethodNotSupportedExcept @ExceptionHandler(Exception.class) public ResponseEntity handleException(Exception e) throws Exception { - if (logger.isWarnEnabled()) { - logger.warn("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage()); + if (logger.isErrorEnabled()) { + logger.error("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage(), e); } return getExceptionTranslator().translate(e); } From 1e5536af65d76696908fc277432f0399e31acc33 Mon Sep 17 00:00:00 2001 From: masm22 Date: Fri, 21 Dec 2018 11:02:00 +0300 Subject: [PATCH 667/831] JwkSetConverter excludes enc keys skip unsupported public key use (enc) without discarding the entire set Fixes gh-1470 --- .../token/store/jwk/JwkSetConverter.java | 11 +++++++++-- .../token/store/jwk/JwkSetConverterTest.java | 16 +++++++--------- 2 files changed, 16 insertions(+), 11 deletions(-) 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 index 0054de7c9..2962e977a 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * Copyright 2012-2019 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. @@ -83,6 +83,7 @@ public Set convert(InputStream jwkSetSource) { Map attributes = new HashMap(); while (parser.nextToken() == JsonToken.START_OBJECT) { + attributes.clear(); while (parser.nextToken() == JsonToken.FIELD_NAME) { String attributeName = parser.getCurrentName(); // gh-1082 - skip arrays such as x5c as we can't deal with them yet @@ -94,6 +95,13 @@ public Set convert(InputStream jwkSetSource) { } } + // gh-1470 - skip unsupported public key use (enc) without discarding the entire set + JwkDefinition.PublicKeyUse publicKeyUse = + JwkDefinition.PublicKeyUse.fromValue(attributes.get(PUBLIC_KEY_USE)); + if (JwkDefinition.PublicKeyUse.ENC.equals(publicKeyUse)) { + continue; + } + JwkDefinition jwkDefinition = null; JwkDefinition.KeyType keyType = JwkDefinition.KeyType.fromValue(attributes.get(KEY_TYPE)); @@ -108,7 +116,6 @@ public Set convert(InputStream jwkSetSource) { jwkDefinition.getKeyId() + " (" + KEY_ID + ")"); } } - attributes.clear(); } } catch (IOException ex) { 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 index 068e759a6..df1620318 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * Copyright 2012-2019 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. @@ -138,13 +138,12 @@ public void convertWhenJwkSetStreamHasRSAJwkElementWithMissingPublicKeyUseAttrib } @Test - public void convertWhenJwkSetStreamHasRSAJwkElementWithENCPublicKeyUseAttributeThenThrowJwkException() throws Exception { - this.thrown.expect(JwkException.class); - this.thrown.expectMessage("enc (use) is currently not supported."); + public void convertWhenJwkSetStreamHasRSAJwkElementWithENCPublicKeyUseAttributeThenReturnEmptyJwkSet() throws Exception { 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)); + Set jwkSet = this.converter.convert(this.asInputStream(jwkSetObject)); + assertTrue("JWK Set NOT empty", jwkSet.isEmpty()); } @Test @@ -190,13 +189,12 @@ public void convertWhenJwkSetStreamHasECJwkElementWithMissingPublicKeyUseAttribu } @Test - public void convertWhenJwkSetStreamHasECJwkElementWithENCPublicKeyUseAttributeThenThrowJwkException() throws Exception { - this.thrown.expect(JwkException.class); - this.thrown.expectMessage("enc (use) is currently not supported."); + public void convertWhenJwkSetStreamHasECJwkElementWithENCPublicKeyUseAttributeThenReturnEmptyJwkSet() throws Exception { Map jwkSetObject = new HashMap(); Map jwkObject = this.createEllipticCurveJwkObject("key-id-1", JwkDefinition.PublicKeyUse.ENC, null); jwkSetObject.put(JwkAttributes.KEYS, new Map[] {jwkObject}); - this.converter.convert(this.asInputStream(jwkSetObject)); + Set jwkSet = this.converter.convert(this.asInputStream(jwkSetObject)); + assertTrue("JWK Set NOT empty", jwkSet.isEmpty()); } @Test From 97e0b4ab282acbed3588e05be03d5a0c4dbf3367 Mon Sep 17 00:00:00 2001 From: Dirk Koehler Date: Mon, 28 Jan 2019 23:13:55 -0800 Subject: [PATCH 668/831] DefaultRedirectResolver matches on userinfo and query Fixes gh-1585 --- .../endpoint/DefaultRedirectResolver.java | 98 +++++++++++--- .../code/SubdomainRedirectResolverTests.java | 6 +- .../DefaultRedirectResolverTests.java | 128 ++++++++++++++++-- .../AuthorizationCodeProviderCookieTests.java | 2 +- .../AuthorizationCodeProviderCookieTests.java | 2 +- 5 files changed, 202 insertions(+), 34 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolver.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolver.java index 72953311e..9f12b27f1 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolver.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 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. @@ -21,6 +21,7 @@ import org.springframework.security.oauth2.common.exceptions.RedirectMismatchException; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.util.Assert; +import org.springframework.util.MultiValueMap; import org.springframework.util.StringUtils; import org.springframework.web.util.UriComponents; import org.springframework.web.util.UriComponentsBuilder; @@ -28,6 +29,8 @@ import java.util.Arrays; import java.util.Collection; import java.util.HashSet; +import java.util.Iterator; +import java.util.List; import java.util.Set; /** @@ -47,7 +50,7 @@ public class DefaultRedirectResolver implements RedirectResolver { /** * Flag to indicate that requested URIs will match if they are a subdomain of the registered value. * - * @param matchSubdomains the flag value to set (deafult true) + * @param matchSubdomains the flag value to set (default true) */ public void setMatchSubdomains(boolean matchSubdomains) { this.matchSubdomains = matchSubdomains; @@ -105,7 +108,8 @@ private boolean containsRedirectGrantType(Set grantTypes) { /** * Whether the requested redirect URI "matches" the specified redirect URI. For a URL, this implementation tests if * the user requested redirect starts with the registered redirect, so it would have the same host and root path if - * it is an HTTP URL. The port is also matched. + * it is an HTTP URL. The port, userinfo, query params also matched. Request redirect uri path can include + * additional parameters which are ignored for the match *

    * For other (non-URL) cases, such as for some implicit clients, the redirect_uri must be an exact match. * @@ -115,22 +119,65 @@ private boolean containsRedirectGrantType(Set grantTypes) { */ protected boolean redirectMatches(String requestedRedirect, String redirectUri) { UriComponents requestedRedirectUri = UriComponentsBuilder.fromUriString(requestedRedirect).build(); - String requestedRedirectUriScheme = (requestedRedirectUri.getScheme() != null ? requestedRedirectUri.getScheme() : ""); - String requestedRedirectUriHost = (requestedRedirectUri.getHost() != null ? requestedRedirectUri.getHost() : ""); - String requestedRedirectUriPath = (requestedRedirectUri.getPath() != null ? requestedRedirectUri.getPath() : ""); - UriComponents registeredRedirectUri = UriComponentsBuilder.fromUriString(redirectUri).build(); - String registeredRedirectUriScheme = (registeredRedirectUri.getScheme() != null ? registeredRedirectUri.getScheme() : ""); - String registeredRedirectUriHost = (registeredRedirectUri.getHost() != null ? registeredRedirectUri.getHost() : ""); - String registeredRedirectUriPath = (registeredRedirectUri.getPath() != null ? registeredRedirectUri.getPath() : ""); - boolean portsMatch = this.matchPorts ? (registeredRedirectUri.getPort() == requestedRedirectUri.getPort()) : true; + boolean schemeMatch = isEqual(registeredRedirectUri.getScheme(), requestedRedirectUri.getScheme()); + boolean userInfoMatch = isEqual(registeredRedirectUri.getUserInfo(), requestedRedirectUri.getUserInfo()); + boolean hostMatch = hostMatches(registeredRedirectUri.getHost(), requestedRedirectUri.getHost()); + boolean portMatch = matchPorts ? registeredRedirectUri.getPort() == requestedRedirectUri.getPort() : true; + boolean pathMatch = isEqual(registeredRedirectUri.getPath(), + StringUtils.cleanPath(requestedRedirectUri.getPath())); + boolean queryParamMatch = matchQueryParams(registeredRedirectUri.getQueryParams(), + requestedRedirectUri.getQueryParams()); + + return schemeMatch && userInfoMatch && hostMatch && portMatch && pathMatch && queryParamMatch; + } + + + /** + * Checks whether the registered redirect uri query params key and values contains match the requested set + * + * The requested redirect uri query params are allowed to contain additional params which will be retained + * + * @param registeredRedirectUriQueryParams + * @param requestedRedirectUriQueryParams + * @return whether the params match + */ + private boolean matchQueryParams(MultiValueMap registeredRedirectUriQueryParams, + MultiValueMap requestedRedirectUriQueryParams) { + + + Iterator iter = registeredRedirectUriQueryParams.keySet().iterator(); + while (iter.hasNext()) { + String key = iter.next(); + List registeredRedirectUriQueryParamsValues = registeredRedirectUriQueryParams.get(key); + List requestedRedirectUriQueryParamsValues = requestedRedirectUriQueryParams.get(key); + + if (!registeredRedirectUriQueryParamsValues.equals(requestedRedirectUriQueryParamsValues)) { + return false; + } + } + + return true; + } + + - return registeredRedirectUriScheme.equals(requestedRedirectUriScheme) && - hostMatches(registeredRedirectUriHost, requestedRedirectUriHost) && - portsMatch && - // Ensure exact path matching - registeredRedirectUriPath.equals(StringUtils.cleanPath(requestedRedirectUriPath)); + /** + * Compares two strings but treats empty string or null equal + * + * @param str1 + * @param str2 + * @return true if strings are equal, false otherwise + */ + private boolean isEqual(String str1, String str2) { + if (StringUtils.isEmpty(str1) && StringUtils.isEmpty(str2)) { + return true; + } else if (!StringUtils.isEmpty(str1)) { + return str1.equals(str2); + } else { + return false; + } } /** @@ -152,7 +199,7 @@ protected boolean hostMatches(String registered, String requested) { * * @param redirectUris the set of the registered URIs to try and find a match. This cannot be null or empty. * @param requestedRedirect the URI used as part of the request - * @return the matching URI + * @return redirect uri * @throws RedirectMismatchException if no match was found */ private String obtainMatchingRedirect(Set redirectUris, String requestedRedirect) { @@ -161,11 +208,26 @@ private String obtainMatchingRedirect(Set redirectUris, String requested if (redirectUris.size() == 1 && requestedRedirect == null) { return redirectUris.iterator().next(); } + for (String redirectUri : redirectUris) { if (requestedRedirect != null && redirectMatches(requestedRedirect, redirectUri)) { - return requestedRedirect; + // Initialize with the registered redirect-uri + UriComponentsBuilder redirectUriBuilder = UriComponentsBuilder.fromUriString(redirectUri); + + UriComponents requestedRedirectUri = UriComponentsBuilder.fromUriString(requestedRedirect).build(); + + if (this.matchSubdomains) { + redirectUriBuilder.host(requestedRedirectUri.getHost()); + } + if (!this.matchPorts) { + redirectUriBuilder.port(requestedRedirectUri.getPort()); + } + redirectUriBuilder.replaceQuery(requestedRedirectUri.getQuery()); // retain additional params (if any) + redirectUriBuilder.fragment(null); + return redirectUriBuilder.build().toUriString(); } } + throw new RedirectMismatchException("Invalid redirect: " + requestedRedirect + " does not match one of the registered values."); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/SubdomainRedirectResolverTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/SubdomainRedirectResolverTests.java index ebfd3fe2f..0f2f37196 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/SubdomainRedirectResolverTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/SubdomainRedirectResolverTests.java @@ -23,7 +23,7 @@ public class SubdomainRedirectResolverTests @Test - public void testRedirectWatchdox() throws Exception + public void testRedirectMatch() throws Exception { Set redirectUris = new HashSet(Arrays.asList("http://watchdox.com/")); client.setRegisteredRedirectUri(redirectUris); @@ -32,9 +32,9 @@ public void testRedirectWatchdox() throws Exception } @Test(expected=RedirectMismatchException.class) - public void testRedirectBadWatchdox() throws Exception + public void testRedirectNoMatch() throws Exception { - Set redirectUris = new HashSet(Arrays.asList("http//watchdox.com")); + Set redirectUris = new HashSet(Arrays.asList("http://watchdox.com/")); client.setRegisteredRedirectUri(redirectUris); String requestedRedirect = "http://anywhere.google.com/"; assertEquals(requestedRedirect, resolver.resolveRedirect(requestedRedirect, client)); diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolverTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolverTests.java index 1202036bb..b65967280 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolverTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolverTests.java @@ -1,14 +1,17 @@ /* - * Copyright 2006-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. + * Copyright 2002-2019 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.endpoint; @@ -195,4 +198,107 @@ public void testRedirectNotMatchingReturnsGenericErrorMessage() throws Exception assertEquals("Invalid redirect: http://anywhere.com/myendpoint does not match one of the registered values.", ex.getMessage()); } } -} \ No newline at end of file + + // gh-1566 + @Test(expected = RedirectMismatchException.class) + public void testRedirectRegisteredUserInfoNotMatching() throws Exception { + Set redirectUris = new HashSet(Arrays.asList("http://userinfo@anywhere.com/")); + client.setRegisteredRedirectUri(redirectUris); + resolver.resolveRedirect("http://otheruserinfo@anywhere.com/", client); + } + + // gh-1566 + @Test(expected = RedirectMismatchException.class) + public void testRedirectRegisteredNoUserInfoNotMatching() throws Exception { + Set redirectUris = new HashSet(Arrays.asList("http://userinfo@anywhere.com/")); + client.setRegisteredRedirectUri(redirectUris); + resolver.resolveRedirect("http://anywhere.com/", client); + } + + // gh-1566 + @Test() + public void testRedirectRegisteredUserInfoMatching() throws Exception { + Set redirectUris = new HashSet(Arrays.asList("http://userinfo@anywhere.com/")); + client.setRegisteredRedirectUri(redirectUris); + String requestedRedirect = "http://userinfo@anywhere.com/"; + assertEquals(requestedRedirect, resolver.resolveRedirect(requestedRedirect, client)); + } + + // gh-1566 + @Test() + public void testRedirectRegisteredFragmentIgnoredAndStripped() throws Exception { + Set redirectUris = new HashSet(Arrays.asList("http://userinfo@anywhere.com/foo/bar#baz")); + client.setRegisteredRedirectUri(redirectUris); + String requestedRedirect = "http://userinfo@anywhere.com/foo/bar"; + assertEquals(requestedRedirect, resolver.resolveRedirect(requestedRedirect + "#bar", client)); + } + + // gh-1566 + @Test() + public void testRedirectRegisteredQueryParamsMatching() throws Exception { + Set redirectUris = new HashSet(Arrays.asList("http://anywhere.com/?p1=v1&p2=v2")); + client.setRegisteredRedirectUri(redirectUris); + String requestedRedirect = "http://anywhere.com/?p1=v1&p2=v2"; + assertEquals(requestedRedirect, resolver.resolveRedirect(requestedRedirect, client)); + } + + // gh-1566 + @Test() + public void testRedirectRegisteredQueryParamsMatchingIgnoringAdditionalParams() throws Exception { + Set redirectUris = new HashSet(Arrays.asList("http://anywhere.com/?p1=v1&p2=v2")); + client.setRegisteredRedirectUri(redirectUris); + String requestedRedirect = "http://anywhere.com/?p1=v1&p2=v2&p3=v3"; + assertEquals(requestedRedirect, resolver.resolveRedirect(requestedRedirect, client)); + } + + // gh-1566 + @Test() + public void testRedirectRegisteredQueryParamsMatchingDifferentOrder() throws Exception { + Set redirectUris = new HashSet(Arrays.asList("http://anywhere.com/?p1=v1&p2=v2")); + client.setRegisteredRedirectUri(redirectUris); + String requestedRedirect = "http://anywhere.com/?p2=v2&p1=v1"; + assertEquals(requestedRedirect, resolver.resolveRedirect(requestedRedirect, client)); + } + + // gh-1566 + @Test(expected = RedirectMismatchException.class) + public void testRedirectRegisteredQueryParamsWithDifferentValues() throws Exception { + Set redirectUris = new HashSet(Arrays.asList("http://anywhere.com/?p1=v1&p2=v2")); + client.setRegisteredRedirectUri(redirectUris); + resolver.resolveRedirect("http://anywhere.com/?p1=v1&p2=v3", client); + } + + // gh-1566 + @Test(expected = RedirectMismatchException.class) + public void testRedirectRegisteredQueryParamsNotMatching() throws Exception { + Set redirectUris = new HashSet(Arrays.asList("http://anywhere.com/?p1=v1")); + client.setRegisteredRedirectUri(redirectUris); + resolver.resolveRedirect("http://anywhere.com/?p2=v2", client); + } + + // gh-1566 + @Test(expected = RedirectMismatchException.class) + public void testRedirectRegisteredQueryParamsPartiallyMatching() throws Exception { + Set redirectUris = new HashSet(Arrays.asList("http://anywhere.com/?p1=v1&p2=v2")); + client.setRegisteredRedirectUri(redirectUris); + resolver.resolveRedirect("http://anywhere.com/?p2=v2&p3=v3", client); + } + + // gh-1566 + @Test + public void testRedirectRegisteredQueryParamsMatchingWithMultipleValuesInRegistered() throws Exception { + Set redirectUris = new HashSet(Arrays.asList("http://anywhere.com/?p1=v11&p1=v12")); + client.setRegisteredRedirectUri(redirectUris); + String requestedRedirect = "http://anywhere.com/?p1=v11&p1=v12"; + assertEquals(requestedRedirect, resolver.resolveRedirect(requestedRedirect, client)); + } + + // gh-1566 + @Test + public void testRedirectRegisteredQueryParamsMatchingWithParamWithNoValue() throws Exception { + Set redirectUris = new HashSet(Arrays.asList("http://anywhere.com/?p1&p2=v2")); + client.setRegisteredRedirectUri(redirectUris); + String requestedRedirect = "http://anywhere.com/?p1&p2=v2"; + assertEquals(requestedRedirect, resolver.resolveRedirect(requestedRedirect, client)); + } +} diff --git a/tests/annotation/jpa/src/test/java/demo/AuthorizationCodeProviderCookieTests.java b/tests/annotation/jpa/src/test/java/demo/AuthorizationCodeProviderCookieTests.java index fdfae6dc2..26d88d46a 100644 --- a/tests/annotation/jpa/src/test/java/demo/AuthorizationCodeProviderCookieTests.java +++ b/tests/annotation/jpa/src/test/java/demo/AuthorizationCodeProviderCookieTests.java @@ -31,7 +31,7 @@ public class AuthorizationCodeProviderCookieTests extends AbstractEmptyAuthoriza @Test @OAuth2ContextConfiguration(resource = MyClientWithRegisteredRedirect.class, initialize = false) public void testPostToProtectedResource() throws Exception { - approveAccessTokenGrant("http://anywhere/", true); + approveAccessTokenGrant("http://anywhere/?key=value", true); assertNotNull(context.getAccessToken()); LinkedMultiValueMap form = new LinkedMultiValueMap<>(); form.set("foo", "bar"); diff --git a/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderCookieTests.java b/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderCookieTests.java index fdfae6dc2..26d88d46a 100644 --- a/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderCookieTests.java +++ b/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderCookieTests.java @@ -31,7 +31,7 @@ public class AuthorizationCodeProviderCookieTests extends AbstractEmptyAuthoriza @Test @OAuth2ContextConfiguration(resource = MyClientWithRegisteredRedirect.class, initialize = false) public void testPostToProtectedResource() throws Exception { - approveAccessTokenGrant("http://anywhere/", true); + approveAccessTokenGrant("http://anywhere/?key=value", true); assertNotNull(context.getAccessToken()); LinkedMultiValueMap form = new LinkedMultiValueMap<>(); form.set("foo", "bar"); From 852cec2b6d4b91db8e2e392d714a7bfec4cbf53e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Millon?= Date: Thu, 2 Aug 2018 15:47:18 +0200 Subject: [PATCH 669/831] Double-checked locking when loading Jwk definitions Fixes gh-1405 --- .../oauth2/provider/token/store/jwk/JwkDefinitionSource.java | 4 ++++ 1 file changed, 4 insertions(+) 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 index 8cea751e0..c60d29866 100644 --- 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 @@ -92,6 +92,10 @@ JwkDefinitionHolder getDefinitionLoadIfNecessary(String keyId) { return result; } synchronized (this.jwkDefinitions) { + result = this.getDefinition(keyId); + if (result != null) { + return result; + } this.jwkDefinitions.clear(); for (URL jwkSetUrl : jwkSetUrls) { this.jwkDefinitions.putAll(loadJwkDefinitions(jwkSetUrl)); From d8a0bb8fba7cee90a4c7991610b30ae779df6b8d Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Tue, 19 Feb 2019 13:06:05 -0500 Subject: [PATCH 670/831] Allow overriding 'active' attribute in CheckTokenEndpoint Fixes gh-1591 --- .../provider/endpoint/CheckTokenEndpoint.java | 63 ++++++++++++++----- .../endpoint/CheckTokenEndpointTest.java | 33 ++++++---- 2 files changed, 66 insertions(+), 30 deletions(-) diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/CheckTokenEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/CheckTokenEndpoint.java index ab1010725..75c978731 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/CheckTokenEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/CheckTokenEndpoint.java @@ -1,15 +1,18 @@ -/******************************************************************************* - * Cloud Foundry - * Copyright (c) [2009-2014] Pivotal Software, Inc. All Rights Reserved. +/* + * Copyright 2009-2019 the original author or authors. * - * This product is licensed to you under the Apache License, Version 2.0 (the "License"). - * You may not use this product except in compliance with the License. + * 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 * - * This product includes a number of subcomponents with - * separate copyright notices and license terms. Your use of these - * subcomponents is subject to the terms and conditions of the - * subcomponent's license, as noted in the LICENSE file. - *******************************************************************************/ + * 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.endpoint; import org.apache.commons.logging.Log; @@ -42,7 +45,7 @@ public class CheckTokenEndpoint { private ResourceServerTokenServices resourceServerTokenServices; - private AccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter(); + private AccessTokenConverter accessTokenConverter = new CheckTokenAccessTokenConverter(); protected final Log logger = LogFactory.getLog(getClass()); @@ -81,12 +84,7 @@ public void setAccessTokenConverter(AccessTokenConverter accessTokenConverter) { OAuth2Authentication authentication = resourceServerTokenServices.loadAuthentication(token.getValue()); - Map response = (Map)accessTokenConverter.convertAccessToken(token, authentication); - - // gh-1070 - response.put("active", true); // Always true if token exists and not expired - - return response; + return accessTokenConverter.convertAccessToken(token, authentication); } @ExceptionHandler(InvalidTokenException.class) @@ -106,4 +104,35 @@ public int getHttpErrorCode() { return exceptionTranslator.translate(e400); } + static class CheckTokenAccessTokenConverter implements AccessTokenConverter { + private final AccessTokenConverter accessTokenConverter; + + CheckTokenAccessTokenConverter() { + this(new DefaultAccessTokenConverter()); + } + + CheckTokenAccessTokenConverter(AccessTokenConverter accessTokenConverter) { + this.accessTokenConverter = accessTokenConverter; + } + + @Override + public Map convertAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) { + Map claims = (Map) this.accessTokenConverter.convertAccessToken(token, authentication); + + // gh-1070 + claims.put("active", true); // Always true if token exists and not expired + + return claims; + } + + @Override + public OAuth2AccessToken extractAccessToken(String value, Map map) { + return this.accessTokenConverter.extractAccessToken(value, map); + } + + @Override + public OAuth2Authentication extractAuthentication(Map map) { + return this.accessTokenConverter.extractAuthentication(map); + } + } } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/CheckTokenEndpointTest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/CheckTokenEndpointTest.java index 87fc2ffb7..5c7dfd093 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/CheckTokenEndpointTest.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/CheckTokenEndpointTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * Copyright 2012-2019 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. @@ -25,8 +25,8 @@ import java.util.HashMap; import java.util.Map; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.*; +import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -36,29 +36,36 @@ */ public class CheckTokenEndpointTest { private CheckTokenEndpoint checkTokenEndpoint; + private AccessTokenConverter accessTokenConverter; @Before public void setUp() { - ResourceServerTokenServices resourceServerTokenServices = mock(ResourceServerTokenServices.class); OAuth2AccessToken accessToken = mock(OAuth2AccessToken.class); - OAuth2Authentication authentication = mock(OAuth2Authentication.class); - when(resourceServerTokenServices.readAccessToken(anyString())).thenReturn(accessToken); when(accessToken.isExpired()).thenReturn(false); - when(accessToken.getValue()).thenReturn("access-token-1234"); - when(resourceServerTokenServices.loadAuthentication(accessToken.getValue())).thenReturn(authentication); + ResourceServerTokenServices resourceServerTokenServices = mock(ResourceServerTokenServices.class); + when(resourceServerTokenServices.readAccessToken(anyString())).thenReturn(accessToken); this.checkTokenEndpoint = new CheckTokenEndpoint(resourceServerTokenServices); - - AccessTokenConverter accessTokenConverter = mock(AccessTokenConverter.class); - when(accessTokenConverter.convertAccessToken(accessToken, authentication)).thenReturn(new HashMap()); - this.checkTokenEndpoint.setAccessTokenConverter(accessTokenConverter); + this.accessTokenConverter = mock(AccessTokenConverter.class); + when(this.accessTokenConverter.convertAccessToken(any(OAuth2AccessToken.class), any(OAuth2Authentication.class))).thenReturn(new HashMap()); + this.checkTokenEndpoint.setAccessTokenConverter(new CheckTokenEndpoint.CheckTokenAccessTokenConverter(this.accessTokenConverter)); } // gh-1070 @Test - public void checkTokenWhenTokenValidThenReturnActiveAttribute() throws Exception { + public void checkTokenWhenDefaultAccessTokenConverterThenActiveAttributeReturned() throws Exception { Map response = this.checkTokenEndpoint.checkToken("access-token-1234"); Object active = response.get("active"); assertNotNull("active is null", active); assertEquals("active not true", Boolean.TRUE, active); } + + // gh-1591 + @Test + public void checkTokenWhenCustomAccessTokenConverterThenActiveAttributeNotReturned() throws Exception { + this.accessTokenConverter = mock(AccessTokenConverter.class); + when(this.accessTokenConverter.convertAccessToken(any(OAuth2AccessToken.class), any(OAuth2Authentication.class))).thenReturn(new HashMap()); + this.checkTokenEndpoint.setAccessTokenConverter(this.accessTokenConverter); + Map response = this.checkTokenEndpoint.checkToken("access-token-1234"); + assertNull("active is not null", response.get("active")); + } } \ No newline at end of file From a453deac3b3fe2c380dde59aaebd9e220453a31c Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Tue, 19 Feb 2019 14:47:00 -0500 Subject: [PATCH 671/831] Release version 2.3.5.RELEASE --- pom.xml | 2 +- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- tests/annotation/approval/pom.xml | 2 +- tests/annotation/client/pom.xml | 2 +- tests/annotation/common/pom.xml | 2 +- tests/annotation/custom-authentication/pom.xml | 2 +- tests/annotation/custom-grant/pom.xml | 2 +- tests/annotation/form/pom.xml | 2 +- tests/annotation/jaxb/pom.xml | 2 +- tests/annotation/jdbc/pom.xml | 2 +- tests/annotation/jpa/pom.xml | 2 +- tests/annotation/jwt/pom.xml | 2 +- tests/annotation/mappings/pom.xml | 2 +- tests/annotation/multi/pom.xml | 2 +- tests/annotation/pom.xml | 4 ++-- tests/annotation/resource/pom.xml | 2 +- tests/annotation/ssl/pom.xml | 2 +- tests/annotation/vanilla/pom.xml | 2 +- tests/pom.xml | 2 +- tests/xml/approval/pom.xml | 2 +- tests/xml/client/pom.xml | 2 +- tests/xml/common/pom.xml | 2 +- tests/xml/form/pom.xml | 2 +- tests/xml/jdbc/pom.xml | 2 +- tests/xml/jwt/pom.xml | 2 +- tests/xml/mappings/pom.xml | 2 +- tests/xml/pom.xml | 4 ++-- tests/xml/vanilla/pom.xml | 2 +- 34 files changed, 36 insertions(+), 36 deletions(-) diff --git a/pom.xml b/pom.xml index 05585aaf0..0bf41e81f 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.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE http://static.springframework.org/spring-security/oauth diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index 518b1d4fe..81e507b5b 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.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index c7c5851bd..c530378d9 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.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 142246451..021b4cebe 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.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 52ae2ad59..48d83fc77 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.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index 51e5e4122..34aa5f2b6 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index 792c9174c..859688f76 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.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 28a1f44ad..e421c9b0b 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.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE spring-security-oauth2 diff --git a/tests/annotation/approval/pom.xml b/tests/annotation/approval/pom.xml index f889a32a7..b6580f3dd 100644 --- a/tests/annotation/approval/pom.xml +++ b/tests/annotation/approval/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE diff --git a/tests/annotation/client/pom.xml b/tests/annotation/client/pom.xml index cc42476aa..2a02b5e1d 100644 --- a/tests/annotation/client/pom.xml +++ b/tests/annotation/client/pom.xml @@ -11,7 +11,7 @@ org.demo spring-oauth2-tests-parent - 2.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE diff --git a/tests/annotation/common/pom.xml b/tests/annotation/common/pom.xml index 72bf74c92..4e5120ac1 100644 --- a/tests/annotation/common/pom.xml +++ b/tests/annotation/common/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE diff --git a/tests/annotation/custom-authentication/pom.xml b/tests/annotation/custom-authentication/pom.xml index 83714af4e..7c8795c43 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.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE diff --git a/tests/annotation/custom-grant/pom.xml b/tests/annotation/custom-grant/pom.xml index 4ef779184..fa788f66e 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.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE diff --git a/tests/annotation/form/pom.xml b/tests/annotation/form/pom.xml index 562d0680e..2f75e7fcc 100644 --- a/tests/annotation/form/pom.xml +++ b/tests/annotation/form/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE diff --git a/tests/annotation/jaxb/pom.xml b/tests/annotation/jaxb/pom.xml index 30232a017..ab4d5b89b 100644 --- a/tests/annotation/jaxb/pom.xml +++ b/tests/annotation/jaxb/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE diff --git a/tests/annotation/jdbc/pom.xml b/tests/annotation/jdbc/pom.xml index f18a32b14..14f0ad9ec 100644 --- a/tests/annotation/jdbc/pom.xml +++ b/tests/annotation/jdbc/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE diff --git a/tests/annotation/jpa/pom.xml b/tests/annotation/jpa/pom.xml index 8f186ab91..298044e61 100644 --- a/tests/annotation/jpa/pom.xml +++ b/tests/annotation/jpa/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE diff --git a/tests/annotation/jwt/pom.xml b/tests/annotation/jwt/pom.xml index f1428bed6..b58ccc76f 100644 --- a/tests/annotation/jwt/pom.xml +++ b/tests/annotation/jwt/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE diff --git a/tests/annotation/mappings/pom.xml b/tests/annotation/mappings/pom.xml index 06bf2ded5..1dc2e7831 100644 --- a/tests/annotation/mappings/pom.xml +++ b/tests/annotation/mappings/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE diff --git a/tests/annotation/multi/pom.xml b/tests/annotation/multi/pom.xml index fcfdf9888..e77f1a114 100644 --- a/tests/annotation/multi/pom.xml +++ b/tests/annotation/multi/pom.xml @@ -9,7 +9,7 @@ org.demo spring-oauth2-tests-parent - 2.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE diff --git a/tests/annotation/pom.xml b/tests/annotation/pom.xml index 4de9e3ba7..634d56f3b 100644 --- a/tests/annotation/pom.xml +++ b/tests/annotation/pom.xml @@ -4,7 +4,7 @@ org.demo spring-oauth2-tests-parent - 2.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE pom @@ -39,7 +39,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE jackson-mapper-asl diff --git a/tests/annotation/resource/pom.xml b/tests/annotation/resource/pom.xml index 6d39a6602..1fcc8a346 100644 --- a/tests/annotation/resource/pom.xml +++ b/tests/annotation/resource/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE diff --git a/tests/annotation/ssl/pom.xml b/tests/annotation/ssl/pom.xml index 5a88daa77..b87dee1ed 100644 --- a/tests/annotation/ssl/pom.xml +++ b/tests/annotation/ssl/pom.xml @@ -11,7 +11,7 @@ org.demo spring-oauth2-tests-parent - 2.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE diff --git a/tests/annotation/vanilla/pom.xml b/tests/annotation/vanilla/pom.xml index 12891f643..71d180769 100644 --- a/tests/annotation/vanilla/pom.xml +++ b/tests/annotation/vanilla/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE diff --git a/tests/pom.xml b/tests/pom.xml index c053c28bf..90eba8b08 100644 --- a/tests/pom.xml +++ b/tests/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE spring-security-oauth-tests diff --git a/tests/xml/approval/pom.xml b/tests/xml/approval/pom.xml index 46dc23330..8cb4a6412 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.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE diff --git a/tests/xml/client/pom.xml b/tests/xml/client/pom.xml index cba66893b..70324030a 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.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE diff --git a/tests/xml/common/pom.xml b/tests/xml/common/pom.xml index 167367d11..032b32afe 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.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE diff --git a/tests/xml/form/pom.xml b/tests/xml/form/pom.xml index ce9acb9cc..d4d71b427 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.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE diff --git a/tests/xml/jdbc/pom.xml b/tests/xml/jdbc/pom.xml index aa2808eb2..0b26fa136 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.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE diff --git a/tests/xml/jwt/pom.xml b/tests/xml/jwt/pom.xml index abe7d86c2..760e0c0a2 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.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE diff --git a/tests/xml/mappings/pom.xml b/tests/xml/mappings/pom.xml index 84c202fc6..17055406c 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.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE diff --git a/tests/xml/pom.xml b/tests/xml/pom.xml index 92810aa1b..21275e7da 100644 --- a/tests/xml/pom.xml +++ b/tests/xml/pom.xml @@ -4,7 +4,7 @@ org.demo spring-oauth2-tests-xml-parent - 2.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE pom @@ -33,7 +33,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE jackson-mapper-asl diff --git a/tests/xml/vanilla/pom.xml b/tests/xml/vanilla/pom.xml index 2a3b35e42..dfd8dde0e 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.3.5.BUILD-SNAPSHOT + 2.3.5.RELEASE From 05cfb0e079e171076fde8a87dc5b736faad455fb Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Tue, 19 Feb 2019 16:03:11 -0500 Subject: [PATCH 672/831] Next development version --- pom.xml | 2 +- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- tests/annotation/approval/pom.xml | 2 +- tests/annotation/client/pom.xml | 2 +- tests/annotation/common/pom.xml | 2 +- tests/annotation/custom-authentication/pom.xml | 2 +- tests/annotation/custom-grant/pom.xml | 2 +- tests/annotation/form/pom.xml | 2 +- tests/annotation/jaxb/pom.xml | 2 +- tests/annotation/jdbc/pom.xml | 2 +- tests/annotation/jpa/pom.xml | 2 +- tests/annotation/jwt/pom.xml | 2 +- tests/annotation/mappings/pom.xml | 2 +- tests/annotation/multi/pom.xml | 2 +- tests/annotation/pom.xml | 4 ++-- tests/annotation/resource/pom.xml | 2 +- tests/annotation/ssl/pom.xml | 2 +- tests/annotation/vanilla/pom.xml | 2 +- tests/pom.xml | 2 +- tests/xml/approval/pom.xml | 2 +- tests/xml/client/pom.xml | 2 +- tests/xml/common/pom.xml | 2 +- tests/xml/form/pom.xml | 2 +- tests/xml/jdbc/pom.xml | 2 +- tests/xml/jwt/pom.xml | 2 +- tests/xml/mappings/pom.xml | 2 +- tests/xml/pom.xml | 4 ++-- tests/xml/vanilla/pom.xml | 2 +- 34 files changed, 36 insertions(+), 36 deletions(-) diff --git a/pom.xml b/pom.xml index 0bf41e81f..32474a878 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.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT http://static.springframework.org/spring-security/oauth diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index 81e507b5b..bd44cf661 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.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index c530378d9..be01d9e76 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.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 021b4cebe..70a1d868b 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.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT ../../.. diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 48d83fc77..af8c148b2 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.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT ../../.. diff --git a/samples/pom.xml b/samples/pom.xml index 34aa5f2b6..6be997346 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT spring-security-oauth-samples diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index 859688f76..e7d99a71b 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.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT spring-security-oauth diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index e421c9b0b..a0af01cf6 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.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT spring-security-oauth2 diff --git a/tests/annotation/approval/pom.xml b/tests/annotation/approval/pom.xml index b6580f3dd..d3859e818 100644 --- a/tests/annotation/approval/pom.xml +++ b/tests/annotation/approval/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT diff --git a/tests/annotation/client/pom.xml b/tests/annotation/client/pom.xml index 2a02b5e1d..de7f6f4e5 100644 --- a/tests/annotation/client/pom.xml +++ b/tests/annotation/client/pom.xml @@ -11,7 +11,7 @@ org.demo spring-oauth2-tests-parent - 2.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT diff --git a/tests/annotation/common/pom.xml b/tests/annotation/common/pom.xml index 4e5120ac1..069432372 100644 --- a/tests/annotation/common/pom.xml +++ b/tests/annotation/common/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT diff --git a/tests/annotation/custom-authentication/pom.xml b/tests/annotation/custom-authentication/pom.xml index 7c8795c43..d7b764413 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.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT diff --git a/tests/annotation/custom-grant/pom.xml b/tests/annotation/custom-grant/pom.xml index fa788f66e..14ba8b794 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.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT diff --git a/tests/annotation/form/pom.xml b/tests/annotation/form/pom.xml index 2f75e7fcc..974761a37 100644 --- a/tests/annotation/form/pom.xml +++ b/tests/annotation/form/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT diff --git a/tests/annotation/jaxb/pom.xml b/tests/annotation/jaxb/pom.xml index ab4d5b89b..02077e121 100644 --- a/tests/annotation/jaxb/pom.xml +++ b/tests/annotation/jaxb/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT diff --git a/tests/annotation/jdbc/pom.xml b/tests/annotation/jdbc/pom.xml index 14f0ad9ec..fc2510e72 100644 --- a/tests/annotation/jdbc/pom.xml +++ b/tests/annotation/jdbc/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT diff --git a/tests/annotation/jpa/pom.xml b/tests/annotation/jpa/pom.xml index 298044e61..5ed4c2b2e 100644 --- a/tests/annotation/jpa/pom.xml +++ b/tests/annotation/jpa/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT diff --git a/tests/annotation/jwt/pom.xml b/tests/annotation/jwt/pom.xml index b58ccc76f..50248ff34 100644 --- a/tests/annotation/jwt/pom.xml +++ b/tests/annotation/jwt/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT diff --git a/tests/annotation/mappings/pom.xml b/tests/annotation/mappings/pom.xml index 1dc2e7831..db71b5234 100644 --- a/tests/annotation/mappings/pom.xml +++ b/tests/annotation/mappings/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT diff --git a/tests/annotation/multi/pom.xml b/tests/annotation/multi/pom.xml index e77f1a114..7a2035b3a 100644 --- a/tests/annotation/multi/pom.xml +++ b/tests/annotation/multi/pom.xml @@ -9,7 +9,7 @@ org.demo spring-oauth2-tests-parent - 2.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT diff --git a/tests/annotation/pom.xml b/tests/annotation/pom.xml index 634d56f3b..db787f9e2 100644 --- a/tests/annotation/pom.xml +++ b/tests/annotation/pom.xml @@ -4,7 +4,7 @@ org.demo spring-oauth2-tests-parent - 2.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT pom @@ -39,7 +39,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT jackson-mapper-asl diff --git a/tests/annotation/resource/pom.xml b/tests/annotation/resource/pom.xml index 1fcc8a346..c14109ae9 100644 --- a/tests/annotation/resource/pom.xml +++ b/tests/annotation/resource/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT diff --git a/tests/annotation/ssl/pom.xml b/tests/annotation/ssl/pom.xml index b87dee1ed..490f72a27 100644 --- a/tests/annotation/ssl/pom.xml +++ b/tests/annotation/ssl/pom.xml @@ -11,7 +11,7 @@ org.demo spring-oauth2-tests-parent - 2.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT diff --git a/tests/annotation/vanilla/pom.xml b/tests/annotation/vanilla/pom.xml index 71d180769..14b32c5e5 100644 --- a/tests/annotation/vanilla/pom.xml +++ b/tests/annotation/vanilla/pom.xml @@ -10,7 +10,7 @@ org.demo spring-oauth2-tests-parent - 2.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT diff --git a/tests/pom.xml b/tests/pom.xml index 90eba8b08..4e9e1eb5f 100644 --- a/tests/pom.xml +++ b/tests/pom.xml @@ -4,7 +4,7 @@ org.springframework.security.oauth spring-security-oauth-parent - 2.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT spring-security-oauth-tests diff --git a/tests/xml/approval/pom.xml b/tests/xml/approval/pom.xml index 8cb4a6412..d075f7721 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.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT diff --git a/tests/xml/client/pom.xml b/tests/xml/client/pom.xml index 70324030a..57b33458f 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.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT diff --git a/tests/xml/common/pom.xml b/tests/xml/common/pom.xml index 032b32afe..167261833 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.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT diff --git a/tests/xml/form/pom.xml b/tests/xml/form/pom.xml index d4d71b427..7ffa953e9 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.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT diff --git a/tests/xml/jdbc/pom.xml b/tests/xml/jdbc/pom.xml index 0b26fa136..0a1d67871 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.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT diff --git a/tests/xml/jwt/pom.xml b/tests/xml/jwt/pom.xml index 760e0c0a2..5eaaa6a40 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.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT diff --git a/tests/xml/mappings/pom.xml b/tests/xml/mappings/pom.xml index 17055406c..486a44c8b 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.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT diff --git a/tests/xml/pom.xml b/tests/xml/pom.xml index 21275e7da..cc6330292 100644 --- a/tests/xml/pom.xml +++ b/tests/xml/pom.xml @@ -4,7 +4,7 @@ org.demo spring-oauth2-tests-xml-parent - 2.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT pom @@ -33,7 +33,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT jackson-mapper-asl diff --git a/tests/xml/vanilla/pom.xml b/tests/xml/vanilla/pom.xml index dfd8dde0e..1edef3c55 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.3.5.RELEASE + 2.3.6.BUILD-SNAPSHOT From 9946272766c42d3e54c40099d37b7ebf5e25bb44 Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Fri, 22 Feb 2019 15:31:17 -0500 Subject: [PATCH 673/831] AuthenticationEntryPoint set on BasicAuthenticationFilter Fixes gh-501 --- ...AuthorizationServerSecurityConfigurer.java | 4 +- .../Gh501EnableAuthorizationServerTests.java | 148 ++++++++++++++++++ .../jaxb/src/main/java/demo/Application.java | 10 +- 3 files changed, 154 insertions(+), 8 deletions(-) create mode 100644 spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/Gh501EnableAuthorizationServerTests.java diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java index 3e37e2b4c..7c34c2e3d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2019 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 @@ -141,7 +141,7 @@ public void init(HttpSecurity http) throws Exception { http.userDetailsService(new ClientDetailsUserDetailsService(clientDetailsService())); } http.securityContext().securityContextRepository(new NullSecurityContextRepository()).and().csrf().disable() - .httpBasic().realmName(realm); + .httpBasic().authenticationEntryPoint(this.authenticationEntryPoint).realmName(realm); if (sslOnly) { http.requiresChannel().anyRequest().requiresSecure(); } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/Gh501EnableAuthorizationServerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/Gh501EnableAuthorizationServerTests.java new file mode 100644 index 000000000..062dab6b3 --- /dev/null +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/Gh501EnableAuthorizationServerTests.java @@ -0,0 +1,148 @@ +/* + * Copyright 2012-2019 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 org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.crypto.codec.Base64; +import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; +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.configurers.AuthorizationServerSecurityConfigurer; +import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.ClientRegistrationException; +import org.springframework.security.oauth2.provider.client.BaseClientDetails; +import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.FilterChainProxy; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.UnsupportedEncodingException; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * gh-501 + * + * @author Joe Grandja + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration +@WebAppConfiguration +public class Gh501EnableAuthorizationServerTests { + private static final String CLIENT_ID = "client-1234"; + private static final String CLIENT_SECRET = "secret-1234"; + private static BaseClientDetails client; + + @Autowired + WebApplicationContext context; + + @Autowired + FilterChainProxy springSecurityFilterChain; + + MockMvc mockMvc; + + static { + client = new BaseClientDetails(CLIENT_ID, null, "read,write", "client_credentials", null); + client.setClientSecret(CLIENT_SECRET); + } + + @Before + public void setup() { + mockMvc = MockMvcBuilders.webAppContextSetup(context).addFilters(springSecurityFilterChain).build(); + } + + @Test + public void clientAuthenticationFailsThenCustomAuthenticationEntryPointCalled() throws Exception { + mockMvc.perform(post("/oauth/token") + .param("grant_type", "client_credentials") + .header("Authorization", httpBasicCredentials(CLIENT_ID, "invalid-secret"))) + .andExpect(status().isUnauthorized()); + + verify(AuthorizationServerConfig.authenticationEntryPoint).commence( + any(HttpServletRequest.class), any(HttpServletResponse.class), any(AuthenticationException.class)); + } + + private String httpBasicCredentials(String userName, String password) { + String headerValue = "Basic "; + byte[] toEncode = null; + try { + toEncode = (userName + ":" + password).getBytes("UTF-8"); + } catch (UnsupportedEncodingException e) { } + headerValue += new String(Base64.encode(toEncode)); + return headerValue; + } + + @Configuration + @EnableAuthorizationServer + @EnableWebMvc + static class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { + private static AuthenticationEntryPoint authenticationEntryPoint = spy(new OAuth2AuthenticationEntryPoint()); + + @Override + public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { + security.authenticationEntryPoint(authenticationEntryPoint); + } + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + clients.withClientDetails(clientDetailsService()); + } + + @Bean + public ClientDetailsService clientDetailsService() { + return new ClientDetailsService() { + @Override + public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException { + return client; + } + }; + } + } + + @Configuration + @EnableWebSecurity + static class WebSecurityConfig extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .authorizeRequests() + .anyRequest().authenticated(); + } + } +} diff --git a/tests/annotation/jaxb/src/main/java/demo/Application.java b/tests/annotation/jaxb/src/main/java/demo/Application.java index 56ed06c4a..3ff888b30 100644 --- a/tests/annotation/jaxb/src/main/java/demo/Application.java +++ b/tests/annotation/jaxb/src/main/java/demo/Application.java @@ -1,8 +1,5 @@ package demo; -import java.util.ArrayList; -import java.util.List; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -27,6 +24,8 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import java.util.List; + @SpringBootApplication @EnableResourceServer @RestController @@ -72,15 +71,14 @@ private AccessDeniedHandler accessDeniedHandler() { private AuthenticationEntryPoint authenticationEntryPoint() { OAuth2AuthenticationEntryPoint authenticationEntryPoint = new OAuth2AuthenticationEntryPoint(); + authenticationEntryPoint.setTypeName("Basic"); + authenticationEntryPoint.setRealmName("oauth2/client"); authenticationEntryPoint.setExceptionRenderer(exceptionRenderer()); return authenticationEntryPoint; } private OAuth2ExceptionRenderer exceptionRenderer() { DefaultOAuth2ExceptionRenderer exceptionRenderer = new DefaultOAuth2ExceptionRenderer(); - List> converters = new ArrayList<>(); - converters.add(new JaxbOAuth2ExceptionMessageConverter()); - exceptionRenderer.setMessageConverters(converters); return exceptionRenderer; } From d2f5401f5789c36e42a51995d61ca4daf74fa8c3 Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Mon, 25 Feb 2019 12:22:49 -0500 Subject: [PATCH 674/831] Fix test Issue gh-501 --- .../annotation/Gh501EnableAuthorizationServerTests.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/Gh501EnableAuthorizationServerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/Gh501EnableAuthorizationServerTests.java index 062dab6b3..a4da13677 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/Gh501EnableAuthorizationServerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/Gh501EnableAuthorizationServerTests.java @@ -26,6 +26,8 @@ import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.AuthenticationException; import org.springframework.security.crypto.codec.Base64; +import org.springframework.security.crypto.password.NoOpPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; @@ -144,5 +146,10 @@ protected void configure(HttpSecurity http) throws Exception { .authorizeRequests() .anyRequest().authenticated(); } + + @Bean + public PasswordEncoder passwordEncoder() { + return NoOpPasswordEncoder.getInstance(); + } } } From 31377e0c8aaafbe23a987477632546f29dd9e3bd Mon Sep 17 00:00:00 2001 From: Spring Operator Date: Tue, 5 Mar 2019 21:00:57 -0600 Subject: [PATCH 675/831] URL Cleanup This commit updates URLs to prefer the https protocol. Redirects are not followed to avoid accidentally expanding intentionally shortened URLs (i.e. if using a URL shortener). # HTTP URLs that Could Not Be Fixed These URLs were unable to be fixed. Please review them to see if they can be manually resolved. * http://junit.sourceforge.net/javadoc/ (200) migrated to: http://junit.sourceforge.net/javadoc/ ([https](https://junit.sourceforge.net/javadoc/) result AnnotatedConnectException). # Fixed URLs ## Fixed But Review Recommended These URLs were fixed, but the https status was not OK. However, the https status was the same as the http request or http redirected to an https URL, so they were migrated. Your review is recommended. * http://jakarta.apache.org/regexp/apidocs/ (404) migrated to: https://jakarta.apache.org/regexp/apidocs/ ([https](https://jakarta.apache.org/regexp/apidocs/) result 404). * http://logging.apache.org/log4j/docs/api/ (404) migrated to: https://logging.apache.org/log4j/docs/api/ ([https](https://logging.apache.org/log4j/docs/api/) result 404). * http://oauth.googlecode.com/svn/code/maven/ (404) migrated to: https://oauth.googlecode.com/svn/code/maven/ ([https](https://oauth.googlecode.com/svn/code/maven/) result 404). ## Fixed Success These URLs were fixed successfully. * http://github.com/spring-projects/spring-security-oauth migrated to: https://github.com/spring-projects/spring-security-oauth ([https](https://github.com/spring-projects/spring-security-oauth) result 200). * http://www.apache.org/licenses/LICENSE-2.0 migrated to: https://www.apache.org/licenses/LICENSE-2.0 ([https](https://www.apache.org/licenses/LICENSE-2.0) result 200). * http://www.apache.org/licenses/LICENSE-2.0.txt migrated to: https://www.apache.org/licenses/LICENSE-2.0.txt ([https](https://www.apache.org/licenses/LICENSE-2.0.txt) result 200). * http://static.springframework.org/spring-security/oauth (301) migrated to: https://docs.spring.io/spring-security/oauth ([https](https://static.springframework.org/spring-security/oauth) result 301). * http://static.springframework.org/spring-security/oauth/samples (301) migrated to: https://docs.spring.io/spring-security/oauth/samples ([https](https://static.springframework.org/spring-security/oauth/samples) result 301). * http://static.springframework.org/spring/docs/2.5.x/api/ (301) migrated to: https://docs.spring.io/spring/docs/2.5.x/api/ ([https](https://static.springframework.org/spring/docs/2.5.x/api/) result 301). * http://forum.springframework.org/forumdisplay.php?f=79 migrated to: https://forum.springframework.org/forumdisplay.php?f=79 ([https](https://forum.springframework.org/forumdisplay.php?f=79) result 301). * http://github.com/SpringSource/spring-security-oauth migrated to: https://github.com/SpringSource/spring-security-oauth ([https](https://github.com/SpringSource/spring-security-oauth) result 301). * http://jakarta.apache.org/commons/collections/apidocs-COLLECTIONS_3_0/ migrated to: https://jakarta.apache.org/commons/collections/apidocs-COLLECTIONS_3_0/ ([https](https://jakarta.apache.org/commons/collections/apidocs-COLLECTIONS_3_0/) result 301). * http://jakarta.apache.org/commons/dbcp/apidocs/ migrated to: https://jakarta.apache.org/commons/dbcp/apidocs/ ([https](https://jakarta.apache.org/commons/dbcp/apidocs/) result 301). * http://jakarta.apache.org/commons/fileupload/apidocs/ migrated to: https://jakarta.apache.org/commons/fileupload/apidocs/ ([https](https://jakarta.apache.org/commons/fileupload/apidocs/) result 301). * http://jakarta.apache.org/commons/httpclient/apidocs/ migrated to: https://jakarta.apache.org/commons/httpclient/apidocs/ ([https](https://jakarta.apache.org/commons/httpclient/apidocs/) result 301). * http://jakarta.apache.org/commons/logging/apidocs/ migrated to: https://jakarta.apache.org/commons/logging/apidocs/ ([https](https://jakarta.apache.org/commons/logging/apidocs/) result 301). * http://jakarta.apache.org/commons/pool/apidocs/ migrated to: https://jakarta.apache.org/commons/pool/apidocs/ ([https](https://jakarta.apache.org/commons/pool/apidocs/) result 301). * http://jakarta.apache.org/velocity/api/ migrated to: https://jakarta.apache.org/velocity/api/ ([https](https://jakarta.apache.org/velocity/api/) result 301). * http://opensource.atlassian.com/projects/spring/browse/SECOAUTH migrated to: https://opensource.atlassian.com/projects/spring/browse/SECOAUTH ([https](https://opensource.atlassian.com/projects/spring/browse/SECOAUTH) result 301). * http://www.springsource.com migrated to: https://www.springsource.com ([https](https://www.springsource.com) result 301). * http://repo.spring.io/libs-milestone-local migrated to: https://repo.spring.io/libs-milestone-local ([https](https://repo.spring.io/libs-milestone-local) result 302). * http://repo.spring.io/libs-release-local migrated to: https://repo.spring.io/libs-release-local ([https](https://repo.spring.io/libs-release-local) result 302). * http://repo.spring.io/libs-snapshot migrated to: https://repo.spring.io/libs-snapshot ([https](https://repo.spring.io/libs-snapshot) result 302). * http://repo.spring.io/libs-snapshot-local migrated to: https://repo.spring.io/libs-snapshot-local ([https](https://repo.spring.io/libs-snapshot-local) result 302). * http://repo.spring.io/milestone migrated to: https://repo.spring.io/milestone ([https](https://repo.spring.io/milestone) result 302). * http://repo.spring.io/release migrated to: https://repo.spring.io/release ([https](https://repo.spring.io/release) result 302). * http://repo.spring.io/snapshot migrated to: https://repo.spring.io/snapshot ([https](https://repo.spring.io/snapshot) result 302). # Ignored These URLs were intentionally ignored. * http://java.sun.com/j2ee/1.4/docs/api * http://java.sun.com/j2se/1.5.0/docs/api * http://maven.apache.org/POM/4.0.0 * http://maven.apache.org/maven-v4_0_0.xsd * http://maven.apache.org/xsd/maven-4.0.0.xsd * http://www.w3.org/2001/XMLSchema-instance --- mvnw | 2 +- mvnw.cmd | 2 +- pom.xml | 50 ++++++++++++++++----------------- samples/oauth/sparklr/pom.xml | 2 +- samples/oauth/tonr/pom.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-jwt/mvnw | 2 +- spring-security-jwt/mvnw.cmd | 2 +- spring-security-jwt/pom.xml | 8 +++--- tests/annotation/common/pom.xml | 6 ++-- tests/annotation/pom.xml | 10 +++---- tests/xml/common/pom.xml | 6 ++-- 14 files changed, 49 insertions(+), 49 deletions(-) diff --git a/mvnw b/mvnw index 53c0d7219..02f96acef 100755 --- a/mvnw +++ b/mvnw @@ -8,7 +8,7 @@ # "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 +# https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an diff --git a/mvnw.cmd b/mvnw.cmd index fc8302432..eb9a292a7 100644 --- a/mvnw.cmd +++ b/mvnw.cmd @@ -7,7 +7,7 @@ @REM "License"); you may not use this file except in compliance @REM with the License. You may obtain a copy of the License at @REM -@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM https://www.apache.org/licenses/LICENSE-2.0 @REM @REM Unless required by applicable law or agreed to in writing, @REM software distributed under the License is distributed on an diff --git a/pom.xml b/pom.xml index 32474a878..be056fde5 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ Parent Project for OAuth Support for Spring Security pom 2.3.6.BUILD-SNAPSHOT - http://static.springframework.org/spring-security/oauth + https://docs.spring.io/spring-security/oauth spring-security-oauth @@ -27,20 +27,20 @@ - http://github.com/SpringSource/spring-security-oauth + https://github.com/SpringSource/spring-security-oauth scm:git:git://github.com/SpringSource/spring-security-oauth.git scm:git:ssh://git@github.com/SpringSource/spring-security-oauth.git HEAD JIRA - http://opensource.atlassian.com/projects/spring/browse/SECOAUTH + https://opensource.atlassian.com/projects/spring/browse/SECOAUTH Spring Security OAuth Forum - http://forum.springframework.org/forumdisplay.php?f=79 - http://forum.springframework.org/forumdisplay.php?f=79 + https://forum.springframework.org/forumdisplay.php?f=79 + https://forum.springframework.org/forumdisplay.php?f=79 @@ -50,7 +50,7 @@ Apache 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt + https://www.apache.org/licenses/LICENSE-2.0.txt @@ -94,22 +94,22 @@ repo.spring.io-milestone Spring Framework Milestone Repository - http://repo.spring.io/libs-milestone-local + https://repo.spring.io/libs-milestone-local repo.spring.io-release Spring Framework Release Repository - http://repo.spring.io/libs-release-local + https://repo.spring.io/libs-release-local repo.spring.io-snapshot Spring Framework Maven Snapshot Repository - http://repo.spring.io/libs-snapshot-local + https://repo.spring.io/libs-snapshot-local true oauth.googlecode.net - http://oauth.googlecode.com/svn/code/maven/ + https://oauth.googlecode.com/svn/code/maven/ @@ -119,7 +119,7 @@ repo.spring.io Spring Milestone Repository - http://repo.spring.io/libs-milestone-local + https://repo.spring.io/libs-milestone-local @@ -176,12 +176,12 @@ repo.spring.io-milestone Spring Framework Milestone Repository - http://repo.spring.io/libs-milestone-local + https://repo.spring.io/libs-milestone-local repo.spring.io-snapshot Spring Framework Maven Snapshot Repository - http://repo.spring.io/libs-snapshot-local + https://repo.spring.io/libs-snapshot-local true @@ -472,17 +472,17 @@ http://java.sun.com/j2ee/1.4/docs/api http://java.sun.com/j2se/1.5.0/docs/api - http://jakarta.apache.org/commons/collections/apidocs-COLLECTIONS_3_0/ - http://jakarta.apache.org/commons/dbcp/apidocs/ - http://jakarta.apache.org/commons/fileupload/apidocs/ - http://jakarta.apache.org/commons/httpclient/apidocs/ - http://jakarta.apache.org/commons/pool/apidocs/ - http://jakarta.apache.org/commons/logging/apidocs/ + https://jakarta.apache.org/commons/collections/apidocs-COLLECTIONS_3_0/ + https://jakarta.apache.org/commons/dbcp/apidocs/ + https://jakarta.apache.org/commons/fileupload/apidocs/ + https://jakarta.apache.org/commons/httpclient/apidocs/ + https://jakarta.apache.org/commons/pool/apidocs/ + https://jakarta.apache.org/commons/logging/apidocs/ http://junit.sourceforge.net/javadoc/ - http://logging.apache.org/log4j/docs/api/ - http://jakarta.apache.org/regexp/apidocs/ - http://jakarta.apache.org/velocity/api/ - http://static.springframework.org/spring/docs/2.5.x/api/ + https://logging.apache.org/log4j/docs/api/ + https://jakarta.apache.org/regexp/apidocs/ + https://jakarta.apache.org/velocity/api/ + https://docs.spring.io/spring/docs/2.5.x/api/ example @@ -504,13 +504,13 @@ repo.spring.io Spring Release Repository - http://repo.spring.io/libs-release-local + https://repo.spring.io/libs-release-local repo.spring.io Spring Snapshot Repository - http://repo.spring.io/libs-snapshot-local + https://repo.spring.io/libs-snapshot-local diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index bd44cf661..ae43f43aa 100644 --- a/samples/oauth/sparklr/pom.xml +++ b/samples/oauth/sparklr/pom.xml @@ -47,7 +47,7 @@ spring Spring Framework Repository - http://repo.spring.io/libs-snapshot + https://repo.spring.io/libs-snapshot diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml index be01d9e76..88d9561ad 100644 --- a/samples/oauth/tonr/pom.xml +++ b/samples/oauth/tonr/pom.xml @@ -51,7 +51,7 @@ spring Spring Framework Repository - http://repo.spring.io/libs-snapshot + https://repo.spring.io/libs-snapshot diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 70a1d868b..eb49c2f47 100644 --- a/samples/oauth2/sparklr/pom.xml +++ b/samples/oauth2/sparklr/pom.xml @@ -110,7 +110,7 @@ spring Spring Framework Repository - http://repo.spring.io/libs-snapshot + https://repo.spring.io/libs-snapshot diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index af8c148b2..85e4f0967 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -121,7 +121,7 @@ spring Spring Framework Repository - http://repo.spring.io/libs-snapshot + https://repo.spring.io/libs-snapshot diff --git a/samples/pom.xml b/samples/pom.xml index 6be997346..31f7e8e11 100755 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -19,7 +19,7 @@ oauth2/tonr - http://static.springframework.org/spring-security/oauth/samples + https://docs.spring.io/spring-security/oauth/samples diff --git a/spring-security-jwt/mvnw b/spring-security-jwt/mvnw index 53c0d7219..02f96acef 100755 --- a/spring-security-jwt/mvnw +++ b/spring-security-jwt/mvnw @@ -8,7 +8,7 @@ # "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 +# https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an diff --git a/spring-security-jwt/mvnw.cmd b/spring-security-jwt/mvnw.cmd index fc8302432..eb9a292a7 100644 --- a/spring-security-jwt/mvnw.cmd +++ b/spring-security-jwt/mvnw.cmd @@ -7,7 +7,7 @@ @REM "License"); you may not use this file except in compliance @REM with the License. You may obtain a copy of the License at @REM -@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM https://www.apache.org/licenses/LICENSE-2.0 @REM @REM Unless required by applicable law or agreed to in writing, @REM software distributed under the License is distributed on an diff --git a/spring-security-jwt/pom.xml b/spring-security-jwt/pom.xml index c005d8de7..2c3f34321 100755 --- a/spring-security-jwt/pom.xml +++ b/spring-security-jwt/pom.xml @@ -13,15 +13,15 @@ It belongs to the family of Spring Security crypto libraries that handle encoding and decoding text as a general, useful thing to be able to do. - http://github.com/spring-projects/spring-security-oauth + https://github.com/spring-projects/spring-security-oauth SpringSource - http://www.springsource.com + https://www.springsource.com Apache 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt + https://www.apache.org/licenses/LICENSE-2.0.txt @@ -178,7 +178,7 @@ - http://github.com/spring-projects/spring-security-oauth + https://github.com/spring-projects/spring-security-oauth scm:git:git://github.com/spring-projects/spring-security-oauth.git scm:git:ssh://git@github.com/spring-projects/spring-security-oauth.git diff --git a/tests/annotation/common/pom.xml b/tests/annotation/common/pom.xml index 069432372..b8c1b2823 100644 --- a/tests/annotation/common/pom.xml +++ b/tests/annotation/common/pom.xml @@ -57,7 +57,7 @@ spring-snapshots Spring Snapshots - http://repo.spring.io/snapshot + https://repo.spring.io/snapshot true @@ -65,7 +65,7 @@ spring-milestones Spring Milestones - http://repo.spring.io/milestone + https://repo.spring.io/milestone false @@ -75,7 +75,7 @@ spring-snapshots Spring Snapshots - http://repo.spring.io/snapshot + https://repo.spring.io/snapshot true diff --git a/tests/annotation/pom.xml b/tests/annotation/pom.xml index db787f9e2..a7ce37c01 100644 --- a/tests/annotation/pom.xml +++ b/tests/annotation/pom.xml @@ -94,7 +94,7 @@ spring-snapshots Spring Snapshots - http://repo.spring.io/libs-snapshot-local + https://repo.spring.io/libs-snapshot-local true @@ -102,7 +102,7 @@ spring-milestones Spring Milestones - http://repo.spring.io/libs-milestone-local + https://repo.spring.io/libs-milestone-local false @@ -110,7 +110,7 @@ spring-releases Spring Releases - http://repo.spring.io/release + https://repo.spring.io/release false @@ -120,7 +120,7 @@ spring-snapshots Spring Snapshots - http://repo.spring.io/libs-snapshot-local + https://repo.spring.io/libs-snapshot-local true @@ -128,7 +128,7 @@ spring-milestones Spring Milestones - http://repo.spring.io/libs-milestone-local + https://repo.spring.io/libs-milestone-local false diff --git a/tests/xml/common/pom.xml b/tests/xml/common/pom.xml index 167261833..a45840913 100644 --- a/tests/xml/common/pom.xml +++ b/tests/xml/common/pom.xml @@ -66,7 +66,7 @@ spring-snapshots Spring Snapshots - http://repo.spring.io/snapshot + https://repo.spring.io/snapshot true @@ -74,7 +74,7 @@ spring-milestones Spring Milestones - http://repo.spring.io/milestone + https://repo.spring.io/milestone false @@ -84,7 +84,7 @@ spring-snapshots Spring Snapshots - http://repo.spring.io/snapshot + https://repo.spring.io/snapshot true From 7be5eba69eb0f4200807a8bb400e827b543825c5 Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Wed, 6 Mar 2019 13:09:22 -0500 Subject: [PATCH 676/831] Update to Spring 4.3.22.RELEASE Fixes gh-1603 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index be056fde5..179e4b8d7 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ UTF-8 1.9 - 4.0.9.RELEASE + 4.3.22.RELEASE 3.2.10.RELEASE 1.5.0.RELEASE 2.6.3 From 36dc5d0cb1c3af64d3673fe52d3a559cb7fe10a6 Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Wed, 6 Mar 2019 13:12:28 -0500 Subject: [PATCH 677/831] Update to Spring Security 4.2.11.RELEASE Fixes gh-1604 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 179e4b8d7..0994f95b7 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ UTF-8 1.9 4.3.22.RELEASE - 3.2.10.RELEASE + 4.2.11.RELEASE 1.5.0.RELEASE 2.6.3 1.6 From adc4c90d4599cbb986d833f8ba4414e842f09411 Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Wed, 6 Mar 2019 13:19:03 -0500 Subject: [PATCH 678/831] Update to JUnit 4.12 Fixes gh-1605 --- pom.xml | 1 + samples/oauth2/sparklr/pom.xml | 2 -- samples/oauth2/tonr/pom.xml | 2 -- spring-security-oauth/pom.xml | 2 -- spring-security-oauth2/pom.xml | 2 -- 5 files changed, 1 insertion(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index 0994f95b7..7e36626e2 100644 --- a/pom.xml +++ b/pom.xml @@ -23,6 +23,7 @@ 4.2.11.RELEASE 1.5.0.RELEASE 2.6.3 + 4.12 1.6 diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index eb49c2f47..2f846e0da 100644 --- a/samples/oauth2/sparklr/pom.xml +++ b/samples/oauth2/sparklr/pom.xml @@ -17,7 +17,6 @@ /sparklr2 2.3.1 3.0.1 - 4.11 @@ -26,7 +25,6 @@ 2.9.0.pr3 3.1.0 - 4.12 diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index 85e4f0967..e013b6b3c 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -18,7 +18,6 @@ /tonr2 2.3.2 3.0.1 - 4.11 @@ -27,7 +26,6 @@ 2.9.0.pr3 3.1.0 - 4.12 diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index e7d99a71b..16595dc37 100644 --- a/spring-security-oauth/pom.xml +++ b/spring-security-oauth/pom.xml @@ -13,7 +13,6 @@ 3.0.1 - 4.11 @@ -21,7 +20,6 @@ spring5 3.1.0 - 4.12 diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index a0af01cf6..75e637734 100644 --- a/spring-security-oauth2/pom.xml +++ b/spring-security-oauth2/pom.xml @@ -17,7 +17,6 @@ 2.3.2 3.0.1 1.0.9.RELEASE - 4.11 1.5.4 @@ -27,7 +26,6 @@ 2.9.0.pr3 3.1.0 - 4.12 1.6.1 From 29fcbe91f553f5f700d81ef1903be2b44bddcead Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Wed, 6 Mar 2019 13:23:29 -0500 Subject: [PATCH 679/831] Update to Mockito 1.10.19 Fixes gh-1606 --- pom.xml | 1 + spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 7e36626e2..55efc4792 100644 --- a/pom.xml +++ b/pom.xml @@ -24,6 +24,7 @@ 1.5.0.RELEASE 2.6.3 4.12 + 1.10.19 1.6 diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index 16595dc37..0f38f2eb7 100644 --- a/spring-security-oauth/pom.xml +++ b/spring-security-oauth/pom.xml @@ -141,7 +141,7 @@ org.mockito mockito-core - 1.9.5 + ${mockito.version} test diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 75e637734..a109481ca 100644 --- a/spring-security-oauth2/pom.xml +++ b/spring-security-oauth2/pom.xml @@ -223,7 +223,7 @@ org.mockito mockito-core - 1.9.5 + ${mockito.version} test From c2ce6c5c9eafd4c3266c68fbfa023ec0f91ed35c Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Wed, 6 Mar 2019 13:26:11 -0500 Subject: [PATCH 680/831] Update to Powermock 1.7.4 Fixes gh-1607 --- spring-security-oauth2/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index a109481ca..bc49f7ce3 100644 --- a/spring-security-oauth2/pom.xml +++ b/spring-security-oauth2/pom.xml @@ -17,7 +17,7 @@ 2.3.2 3.0.1 1.0.9.RELEASE - 1.5.4 + 1.7.4 From 366f9e0a4263bed0b63a8f82652d368305e870bd Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Wed, 6 Mar 2019 13:30:12 -0500 Subject: [PATCH 681/831] Update to Jackson2 2.9.8 Fixes gh-1608 --- samples/oauth2/sparklr/pom.xml | 4 ++-- samples/oauth2/tonr/pom.xml | 4 ++-- spring-security-oauth2/pom.xml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 2f846e0da..4703a2f45 100644 --- a/samples/oauth2/sparklr/pom.xml +++ b/samples/oauth2/sparklr/pom.xml @@ -15,7 +15,7 @@ /sparklr2 - 2.3.1 + 2.9.8 3.0.1 @@ -23,7 +23,7 @@ spring5 - 2.9.0.pr3 + 2.9.8 3.1.0 diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml index e013b6b3c..26aa7c8d0 100644 --- a/samples/oauth2/tonr/pom.xml +++ b/samples/oauth2/tonr/pom.xml @@ -16,7 +16,7 @@ /tonr2 - 2.3.2 + 2.9.8 3.0.1 @@ -24,7 +24,7 @@ spring5 - 2.9.0.pr3 + 2.9.8 3.1.0 diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index bc49f7ce3..3b5a9e664 100644 --- a/spring-security-oauth2/pom.xml +++ b/spring-security-oauth2/pom.xml @@ -14,7 +14,7 @@ 1.9.13 - 2.3.2 + 2.9.8 3.0.1 1.0.9.RELEASE 1.7.4 @@ -24,7 +24,7 @@ spring5 - 2.9.0.pr3 + 2.9.8 3.1.0 1.6.1 From 558a428d4637e0df2bab707b24e9e38620153220 Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Wed, 6 Mar 2019 13:34:15 -0500 Subject: [PATCH 682/831] Update to httpclient 4.5.6 Fixes gh-1609 --- samples/oauth2/sparklr/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- spring-security-oauth2/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml index 4703a2f45..f96614a73 100644 --- a/samples/oauth2/sparklr/pom.xml +++ b/samples/oauth2/sparklr/pom.xml @@ -186,7 +186,7 @@ org.apache.httpcomponents httpclient - 4.3.3 + 4.5.6 test diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml index 0f38f2eb7..791df94f7 100644 --- a/spring-security-oauth/pom.xml +++ b/spring-security-oauth/pom.xml @@ -169,7 +169,7 @@ org.apache.httpcomponents httpclient - 4.3.3 + 4.5.6 diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml index 3b5a9e664..ffb7ff646 100644 --- a/spring-security-oauth2/pom.xml +++ b/spring-security-oauth2/pom.xml @@ -187,7 +187,7 @@ org.apache.httpcomponents httpclient - 4.3.3 + 4.5.6 true From 7bfe08d8f95b2fec035de484068f7907851b27d0 Mon Sep 17 00:00:00 2001 From: Spring Operator Date: Thu, 14 Mar 2019 20:14:55 -0500 Subject: [PATCH 683/831] URL Cleanup This commit updates URLs to prefer the https protocol. Redirects are not followed to avoid accidentally expanding intentionally shortened URLs (i.e. if using a URL shortener). These URLs were switched to an https URL with a 2xx status. While the status was successful, your review is still recommended. * http://www.apache.org/licenses/ with 1 occurrences migrated to: https://www.apache.org/licenses/ ([https](https://www.apache.org/licenses/) result 200). * http://www.apache.org/licenses/LICENSE-2.0 with 450 occurrences migrated to: https://www.apache.org/licenses/LICENSE-2.0 ([https](https://www.apache.org/licenses/LICENSE-2.0) result 200). Fixes gh-1621 --- license.txt | 4 ++-- .../oauth/examples/sparklr/impl/PhotoServiceImpl.java | 2 +- .../oauth/examples/sparklr/config/MethodSecurityConfig.java | 2 +- .../oauth/examples/sparklr/config/OAuth2ServerConfig.java | 2 +- .../oauth/examples/sparklr/config/ServletInitializer.java | 2 +- .../examples/sparklr/oauth/SparklrUserApprovalHandler.java | 2 +- .../oauth2/provider/AuthorizationCodeProviderTests.java | 2 +- .../samples/config/ApplicationConfigurationTests.java | 2 +- .../security/oauth/examples/config/ServletInitializer.java | 2 +- .../examples/tonr/converter/AccessTokenRequestConverter.java | 2 +- .../springframework/security/samples/config/AdHocTests.java | 2 +- .../security/samples/config/SecurityConfigTests.java | 2 +- .../org/springframework/security/jwt/AlgorithmMetadata.java | 2 +- .../java/org/springframework/security/jwt/BinaryFormat.java | 2 +- .../src/main/java/org/springframework/security/jwt/Jwt.java | 2 +- .../java/org/springframework/security/jwt/JwtAlgorithms.java | 2 +- .../main/java/org/springframework/security/jwt/JwtHelper.java | 2 +- .../java/org/springframework/security/jwt/codec/Codecs.java | 2 +- .../security/jwt/crypto/cipher/CipherMetadata.java | 2 +- .../security/jwt/crypto/sign/EllipticCurveKeyHelper.java | 2 +- .../jwt/crypto/sign/EllipticCurveSignatureHelper.java | 2 +- .../security/jwt/crypto/sign/EllipticCurveVerifier.java | 2 +- .../security/jwt/crypto/sign/InvalidSignatureException.java | 2 +- .../springframework/security/jwt/crypto/sign/MacSigner.java | 2 +- .../security/jwt/crypto/sign/RsaKeyHelper.java | 2 +- .../springframework/security/jwt/crypto/sign/RsaSigner.java | 2 +- .../springframework/security/jwt/crypto/sign/RsaVerifier.java | 2 +- .../security/jwt/crypto/sign/SignatureVerifier.java | 2 +- .../org/springframework/security/jwt/crypto/sign/Signer.java | 2 +- .../security/jwt/crypto/sign/SignerVerifier.java | 2 +- .../java/org/springframework/security/jwt/JwtSpecData.java | 2 +- .../test/java/org/springframework/security/jwt/JwtTests.java | 2 +- .../springframework/security/jwt/RubyJwtIntegrationTests.java | 2 +- .../security/jwt/crypto/cipher/RsaTestKeyData.java | 2 +- .../security/jwt/crypto/sign/EllipticCurveVerifierTests.java | 2 +- .../security/jwt/crypto/sign/RsaSigningTests.java | 2 +- .../org/springframework/security/oauth/common/OAuthCodec.java | 2 +- .../security/oauth/common/OAuthConsumerParameter.java | 2 +- .../springframework/security/oauth/common/OAuthException.java | 2 +- .../security/oauth/common/OAuthProviderParameter.java | 2 +- .../common/signature/CoreOAuthSignatureMethodFactory.java | 2 +- .../oauth/common/signature/HMAC_SHA1SignatureMethod.java | 2 +- .../oauth/common/signature/InvalidSignatureException.java | 2 +- .../security/oauth/common/signature/OAuthSignatureMethod.java | 2 +- .../oauth/common/signature/OAuthSignatureMethodFactory.java | 2 +- .../oauth/common/signature/PlainTextSignatureMethod.java | 2 +- .../security/oauth/common/signature/RSAKeySecret.java | 2 +- .../oauth/common/signature/RSA_SHA1SignatureMethod.java | 2 +- .../security/oauth/common/signature/SharedConsumerSecret.java | 2 +- .../oauth/common/signature/SharedConsumerSecretImpl.java | 2 +- .../security/oauth/common/signature/SignatureSecret.java | 2 +- .../oauth/common/signature/SignatureSecretEditor.java | 2 +- .../common/signature/UnsupportedSignatureMethodException.java | 2 +- .../security/oauth/config/ConsumerDetailsFactoryBean.java | 2 +- .../oauth/config/ConsumerServiceBeanDefinitionParser.java | 2 +- .../oauth/config/ExpressionHandlerBeanDefinitionParser.java | 2 +- .../oauth/config/OAuthConsumerBeanDefinitionParser.java | 2 +- .../oauth/config/OAuthProviderBeanDefinitionParser.java | 2 +- .../security/oauth/config/OAuthSecurityNamespaceHandler.java | 2 +- .../config/ProtectedResourceDetailsBeanDefinitionParser.java | 2 +- .../oauth/config/TokenServiceBeanDefinitionParser.java | 2 +- .../oauth/config/VerifierServiceBeanDefinitionParser.java | 2 +- .../security/oauth/consumer/BaseProtectedResourceDetails.java | 2 +- .../consumer/InMemoryProtectedResourceDetailsService.java | 2 +- .../security/oauth/consumer/InvalidOAuthRealmException.java | 2 +- .../security/oauth/consumer/OAuthConsumerSupport.java | 2 +- .../security/oauth/consumer/OAuthConsumerToken.java | 2 +- .../security/oauth/consumer/OAuthRequestFailedException.java | 2 +- .../security/oauth/consumer/ProtectedResourceDetails.java | 2 +- .../oauth/consumer/ProtectedResourceDetailsService.java | 2 +- .../oauth/consumer/UnverifiedRequestTokenException.java | 2 +- .../oauth/consumer/client/CoreOAuthConsumerSupport.java | 2 +- .../oauth/consumer/filter/OAuthConsumerContextFilter.java | 2 +- .../oauth/consumer/filter/OAuthConsumerProcessingFilter.java | 2 +- .../consumer/net/DefaultOAuthURLStreamHandlerFactory.java | 2 +- .../oauth/consumer/net/OAuthOverHttpURLStreamHandler.java | 2 +- .../oauth/consumer/net/OAuthOverHttpsURLStreamHandler.java | 2 +- .../oauth/consumer/net/OAuthURLStreamHandlerFactory.java | 2 +- .../security/oauth/consumer/nonce/NonceFactory.java | 2 +- .../security/oauth/consumer/nonce/UUIDNonceFactory.java | 2 +- .../oauth/consumer/token/HttpSessionBasedTokenServices.java | 2 +- .../oauth/consumer/token/OAuthConsumerTokenServices.java | 2 +- .../security/oauth/provider/BaseConsumerDetails.java | 2 +- .../security/oauth/provider/ConsumerAuthentication.java | 2 +- .../security/oauth/provider/ConsumerCredentials.java | 2 +- .../security/oauth/provider/ConsumerDetails.java | 2 +- .../security/oauth/provider/ConsumerDetailsService.java | 2 +- .../security/oauth/provider/ExtraTrustConsumerDetails.java | 2 +- .../oauth/provider/InMemoryConsumerDetailsService.java | 2 +- .../oauth/provider/InvalidOAuthParametersException.java | 2 +- .../security/oauth/provider/OAuthAuthenticationDetails.java | 2 +- .../oauth/provider/OAuthProcessingFilterEntryPoint.java | 2 +- .../security/oauth/provider/OAuthProviderSupport.java | 2 +- .../oauth/provider/OAuthVersionUnsupportedException.java | 2 +- .../oauth/provider/ResourceSpecificConsumerDetails.java | 2 +- .../oauth/provider/attributes/ConsumerKeysAllowed.java | 2 +- .../oauth/provider/attributes/ConsumerRolesAllowed.java | 2 +- .../oauth/provider/attributes/ConsumerSecurityConfig.java | 2 +- .../provider/attributes/ConsumerSecurityMetadataSource.java | 2 +- .../oauth/provider/attributes/ConsumerSecurityVoter.java | 2 +- .../security/oauth/provider/attributes/DenyAllConsumers.java | 2 +- .../oauth/provider/attributes/PermitAllConsumers.java | 2 +- .../oauth/provider/filter/AccessTokenProcessingFilter.java | 2 +- .../oauth/provider/filter/CoreOAuthProviderSupport.java | 2 +- .../oauth/provider/filter/OAuthProviderProcessingFilter.java | 2 +- .../provider/filter/ProtectedResourceProcessingFilter.java | 2 +- .../filter/UnauthenticatedRequestTokenProcessingFilter.java | 2 +- .../provider/filter/UserAuthorizationProcessingFilter.java | 2 +- .../UserAuthorizationSuccessfulAuthenticationHandler.java | 2 +- .../oauth/provider/nonce/ExpiringTimestampNonceServices.java | 2 +- .../security/oauth/provider/nonce/InMemoryNonceServices.java | 2 +- .../oauth/provider/nonce/NonceAlreadyUsedException.java | 2 +- .../security/oauth/provider/nonce/NullNonceServices.java | 2 +- .../security/oauth/provider/nonce/OAuthNonceServices.java | 2 +- .../oauth/provider/token/ExpiredOAuthTokenException.java | 2 +- .../oauth/provider/token/InMemoryProviderTokenServices.java | 2 +- .../token/InMemorySelfCleaningProviderTokenServices.java | 2 +- .../oauth/provider/token/InvalidOAuthTokenException.java | 2 +- .../oauth/provider/token/OAuthAccessProviderToken.java | 2 +- .../security/oauth/provider/token/OAuthProviderToken.java | 2 +- .../security/oauth/provider/token/OAuthProviderTokenImpl.java | 2 +- .../oauth/provider/token/OAuthProviderTokenServices.java | 2 +- .../provider/token/RandomValueProviderTokenServices.java | 2 +- .../oauth/provider/verifier/VerificationFailedException.java | 2 +- .../net/oauth/signature/GoogleCodeCompatibilityTests.java | 2 +- .../security/oauth/common/OAuthCodecTests.java | 2 +- .../signature/CoreOAuthSignatureMethodFactoryTests.java | 2 +- .../oauth/common/signature/HMAC_SHA1SignatureMethodTests.java | 2 +- .../oauth/common/signature/PlainTextSignatureMethodTests.java | 2 +- .../oauth/common/signature/RSA_SHA1SignatureMethodTests.java | 2 +- .../config/AuthorizationServerBeanDefinitionParserTests.java | 2 +- .../oauth/consumer/client/CoreOAuthConsumerSupportTests.java | 2 +- .../rememberme/HttpSessionOAuthRememberMeServicesTests.java | 2 +- .../oauth/provider/CoreOAuthProviderSupportTests.java | 2 +- .../provider/filter/AccessTokenProcessingFilterTests.java | 2 +- .../oauth/provider/filter/OAuthProcessingFilterTests.java | 2 +- .../filter/OAuthUserAuthorizationProcessingFilterTests.java | 2 +- .../filter/ProtectedResourceProcessingFilterTests.java | 2 +- .../UnauthenticatedRequestTokenProcessingFilterTests.java | 2 +- ...UserAuthorizationSuccessfulAuthenticationHandlerTests.java | 2 +- .../oauth2/client/DefaultOAuth2RequestAuthenticator.java | 2 +- .../security/oauth2/client/OAuth2ClientContext.java | 2 +- .../security/oauth2/client/OAuth2RequestAuthenticator.java | 2 +- .../security/oauth2/client/OAuth2RestOperations.java | 2 +- .../oauth2/client/discovery/ProviderConfiguration.java | 2 +- .../oauth2/client/discovery/ProviderDiscoveryClient.java | 2 +- .../filter/OAuth2ClientAuthenticationProcessingFilter.java | 2 +- .../oauth2/client/filter/state/DefaultStateKeyGenerator.java | 2 +- .../oauth2/client/filter/state/StateKeyGenerator.java | 2 +- .../security/oauth2/client/http/OAuth2ErrorHandler.java | 2 +- .../oauth2/client/resource/UserApprovalRequiredException.java | 2 +- .../security/oauth2/client/test/BeforeOAuth2Context.java | 2 +- .../oauth2/client/test/OAuth2ContextConfiguration.java | 2 +- .../security/oauth2/client/test/OAuth2ContextSetup.java | 2 +- .../security/oauth2/client/test/RestTemplateHolder.java | 2 +- .../security/oauth2/client/test/TestAccounts.java | 2 +- .../security/oauth2/client/token/AccessTokenProvider.java | 2 +- .../oauth2/client/token/AccessTokenProviderChain.java | 2 +- .../security/oauth2/client/token/AccessTokenRequest.java | 2 +- .../security/oauth2/client/token/ClientKeyGenerator.java | 2 +- .../security/oauth2/client/token/ClientTokenServices.java | 2 +- .../oauth2/client/token/DefaultAccessTokenRequest.java | 2 +- .../oauth2/client/token/DefaultClientKeyGenerator.java | 2 +- .../security/oauth2/client/token/DefaultRequestEnhancer.java | 2 +- .../security/oauth2/client/token/RequestEnhancer.java | 2 +- .../oauth2/client/token/auth/ClientAuthenticationHandler.java | 2 +- .../grant/code/AuthorizationCodeAccessTokenProvider.java | 4 ++-- .../grant/password/ResourceOwnerPasswordResourceDetails.java | 2 +- .../security/oauth2/common/AuthenticationScheme.java | 2 +- .../security/oauth2/common/ExpiringOAuth2RefreshToken.java | 2 +- .../security/oauth2/common/OAuth2AccessToken.java | 2 +- .../oauth2/common/OAuth2AccessTokenJackson1Deserializer.java | 2 +- .../oauth2/common/OAuth2AccessTokenJackson1Serializer.java | 2 +- .../oauth2/common/OAuth2AccessTokenJackson2Deserializer.java | 2 +- .../oauth2/common/OAuth2AccessTokenJackson2Serializer.java | 2 +- .../security/oauth2/common/OAuth2RefreshToken.java | 2 +- .../oauth2/common/exceptions/InvalidTokenException.java | 2 +- .../exceptions/OAuth2ExceptionJackson1Deserializer.java | 2 +- .../common/exceptions/OAuth2ExceptionJackson1Serializer.java | 2 +- .../exceptions/OAuth2ExceptionJackson2Deserializer.java | 2 +- .../common/exceptions/OAuth2ExceptionJackson2Serializer.java | 2 +- .../security/oauth2/common/util/DefaultJdbcListFactory.java | 2 +- .../security/oauth2/common/util/Jackson2JsonParser.java | 2 +- .../security/oauth2/common/util/JacksonJsonParser.java | 2 +- .../security/oauth2/common/util/JdbcListFactory.java | 2 +- .../security/oauth2/common/util/JsonParser.java | 2 +- .../security/oauth2/common/util/JsonParserFactory.java | 2 +- .../security/oauth2/common/util/OAuth2Utils.java | 2 +- .../security/oauth2/common/util/ProxyCreator.java | 2 +- .../annotation/builders/ClientDetailsServiceBuilder.java | 2 +- .../builders/InMemoryClientDetailsServiceBuilder.java | 2 +- .../annotation/builders/JdbcClientDetailsServiceBuilder.java | 2 +- .../configuration/ClientDetailsServiceConfiguration.java | 2 +- .../configurers/ClientDetailsServiceConfigurer.java | 2 +- .../web/configuration/AuthorizationServerConfigurer.java | 2 +- .../configuration/AuthorizationServerConfigurerAdapter.java | 2 +- .../AuthorizationServerEndpointsConfiguration.java | 2 +- .../AuthorizationServerSecurityConfiguration.java | 2 +- .../web/configuration/EnableAuthorizationServer.java | 2 +- .../annotation/web/configuration/EnableOAuth2Client.java | 2 +- .../annotation/web/configuration/EnableResourceServer.java | 2 +- .../web/configuration/OAuth2ClientConfiguration.java | 2 +- .../web/configuration/ResourceServerConfiguration.java | 2 +- .../web/configuration/ResourceServerConfigurer.java | 2 +- .../web/configuration/ResourceServerConfigurerAdapter.java | 2 +- .../configurers/AuthorizationServerEndpointsConfigurer.java | 2 +- .../configurers/AuthorizationServerSecurityConfigurer.java | 2 +- .../web/configurers/ResourceServerSecurityConfigurer.java | 2 +- .../config/xml/AuthorizationServerBeanDefinitionParser.java | 2 +- .../oauth2/config/xml/ClientBeanDefinitionParser.java | 2 +- .../config/xml/ClientDetailsServiceBeanDefinitionParser.java | 2 +- .../config/xml/ExpressionHandlerBeanDefinitionParser.java | 2 +- .../oauth2/config/xml/OAuth2ClientContextFactoryBean.java | 2 +- .../oauth2/config/xml/OAuth2SecurityNamespaceHandler.java | 2 +- .../oauth2/config/xml/ProviderBeanDefinitionParser.java | 2 +- .../oauth2/config/xml/ResourceBeanDefinitionParser.java | 2 +- .../oauth2/config/xml/ResourceServerBeanDefinitionParser.java | 2 +- .../oauth2/config/xml/RestTemplateBeanDefinitionParser.java | 2 +- .../config/xml/WebExpressionHandlerBeanDefinitionParser.java | 2 +- .../http/converter/FormOAuth2AccessTokenMessageConverter.java | 2 +- .../converter/FormOAuth2ExceptionHttpMessageConverter.java | 2 +- .../http/converter/jaxb/AbstractJaxbMessageConverter.java | 2 +- .../oauth2/http/converter/jaxb/JaxbOAuth2AccessToken.java | 2 +- .../converter/jaxb/JaxbOAuth2AccessTokenMessageConverter.java | 2 +- .../oauth2/http/converter/jaxb/JaxbOAuth2Exception.java | 2 +- .../converter/jaxb/JaxbOAuth2ExceptionMessageConverter.java | 2 +- .../springframework/security/oauth2/provider/BaseRequest.java | 2 +- .../oauth2/provider/ClientAlreadyExistsException.java | 2 +- .../security/oauth2/provider/ClientDetailsService.java | 2 +- .../security/oauth2/provider/ClientRegistrationException.java | 2 +- .../security/oauth2/provider/ClientRegistrationService.java | 2 +- .../security/oauth2/provider/CompositeTokenGranter.java | 2 +- .../oauth2/provider/DefaultSecurityContextAccessor.java | 2 +- .../security/oauth2/provider/NoSuchClientException.java | 2 +- .../security/oauth2/provider/OAuth2RequestFactory.java | 2 +- .../security/oauth2/provider/SecurityContextAccessor.java | 2 +- .../security/oauth2/provider/TokenGranter.java | 2 +- .../security/oauth2/provider/approval/Approval.java | 2 +- .../security/oauth2/provider/approval/ApprovalStore.java | 2 +- .../provider/approval/ApprovalStoreUserApprovalHandler.java | 2 +- .../oauth2/provider/approval/DefaultUserApprovalHandler.java | 2 +- .../oauth2/provider/approval/InMemoryApprovalStore.java | 2 +- .../security/oauth2/provider/approval/JdbcApprovalStore.java | 2 +- .../security/oauth2/provider/approval/TokenApprovalStore.java | 2 +- .../provider/approval/TokenStoreUserApprovalHandler.java | 2 +- .../oauth2/provider/authentication/BearerTokenExtractor.java | 2 +- .../provider/authentication/OAuth2AuthenticationDetails.java | 2 +- .../authentication/OAuth2AuthenticationDetailsSource.java | 2 +- .../provider/authentication/OAuth2AuthenticationManager.java | 2 +- .../authentication/OAuth2AuthenticationProcessingFilter.java | 2 +- .../oauth2/provider/authentication/TokenExtractor.java | 2 +- .../provider/client/ClientCredentialsTokenEndpointFilter.java | 2 +- .../oauth2/provider/client/ClientCredentialsTokenGranter.java | 2 +- .../provider/client/ClientDetailsUserDetailsService.java | 2 +- .../oauth2/provider/client/InMemoryClientDetailsService.java | 2 +- .../oauth2/provider/client/JdbcClientDetailsService.java | 2 +- .../oauth2/provider/code/AuthorizationCodeTokenGranter.java | 2 +- .../security/oauth2/provider/endpoint/AbstractEndpoint.java | 2 +- .../oauth2/provider/endpoint/AuthorizationEndpoint.java | 2 +- .../security/oauth2/provider/endpoint/CheckTokenEndpoint.java | 2 +- .../oauth2/provider/endpoint/DefaultRedirectResolver.java | 2 +- .../security/oauth2/provider/endpoint/FrameworkEndpoint.java | 2 +- .../provider/endpoint/FrameworkEndpointHandlerMapping.java | 2 +- .../security/oauth2/provider/endpoint/TokenEndpoint.java | 2 +- .../provider/endpoint/TokenEndpointAuthenticationFilter.java | 2 +- .../error/AbstractOAuth2SecurityExceptionHandler.java | 2 +- .../oauth2/provider/error/DefaultOAuth2ExceptionRenderer.java | 2 +- .../provider/error/DefaultWebResponseExceptionTranslator.java | 2 +- .../oauth2/provider/error/OAuth2AccessDeniedHandler.java | 2 +- .../oauth2/provider/error/OAuth2AuthenticationEntryPoint.java | 2 +- .../oauth2/provider/error/OAuth2ExceptionRenderer.java | 2 +- .../oauth2/provider/error/WebResponseExceptionTranslator.java | 2 +- .../oauth2/provider/expression/OAuth2ExpressionParser.java | 2 +- .../oauth2/provider/expression/OAuth2ExpressionUtils.java | 2 +- .../provider/expression/OAuth2SecurityExpressionMethods.java | 2 +- .../expression/OAuth2WebSecurityExpressionHandler.java | 2 +- .../oauth2/provider/implicit/ImplicitTokenGranter.java | 2 +- .../oauth2/provider/implicit/ImplicitTokenRequest.java | 2 +- .../provider/password/ResourceOwnerPasswordTokenGranter.java | 2 +- .../security/oauth2/provider/refresh/RefreshTokenGranter.java | 2 +- .../oauth2/provider/request/DefaultOAuth2RequestFactory.java | 2 +- .../security/oauth2/provider/token/AbstractTokenGranter.java | 2 +- .../oauth2/provider/token/AuthenticationKeyGenerator.java | 2 +- .../provider/token/AuthorizationServerTokenServices.java | 2 +- .../security/oauth2/provider/token/ConsumerTokenServices.java | 2 +- .../provider/token/DefaultAuthenticationKeyGenerator.java | 2 +- .../security/oauth2/provider/token/DefaultTokenServices.java | 2 +- .../security/oauth2/provider/token/TokenEnhancer.java | 2 +- .../security/oauth2/provider/token/TokenEnhancerChain.java | 2 +- .../provider/token/store/DelegatingJwtClaimsSetVerifier.java | 2 +- .../oauth2/provider/token/store/IssuerClaimVerifier.java | 2 +- .../oauth2/provider/token/store/JwtClaimsSetVerifier.java | 2 +- .../security/oauth2/provider/token/store/JwtTokenStore.java | 2 +- .../oauth2/provider/token/store/KeyStoreKeyFactory.java | 2 +- .../provider/token/store/jwk/EllipticCurveJwkDefinition.java | 2 +- .../oauth2/provider/token/store/jwk/JwkAttributes.java | 2 +- .../oauth2/provider/token/store/jwk/JwkDefinition.java | 2 +- .../oauth2/provider/token/store/jwk/JwkDefinitionSource.java | 2 +- .../oauth2/provider/token/store/jwk/JwkException.java | 2 +- .../oauth2/provider/token/store/jwk/JwkSetConverter.java | 2 +- .../oauth2/provider/token/store/jwk/JwkTokenStore.java | 2 +- .../token/store/jwk/JwkVerifyingJwtAccessTokenConverter.java | 2 +- .../oauth2/provider/token/store/jwk/JwtHeaderConverter.java | 2 +- .../oauth2/provider/token/store/jwk/RsaJwkDefinition.java | 2 +- .../security/oauth2/provider/vote/ScopeVoter.java | 2 +- .../org/springframework/security/oauth2/AdhocTestSuite.java | 2 +- .../oauth2/client/DefaultOAuth2RequestAuthenticatorTests.java | 2 +- .../oauth2/client/discovery/ProviderDiscoveryClientTest.java | 2 +- .../OAuth2ClientAuthenticationProcessingFilterTests.java | 2 +- .../security/oauth2/client/http/OAuth2ErrorHandlerTests.java | 2 +- .../oauth2/client/token/AccessTokenProviderChainTests.java | 2 +- .../oauth2/client/token/OAuth2AccessTokenSupportTests.java | 2 +- .../grant/code/AuthorizationCodeAccessTokenProviderTests.java | 2 +- ...thorizationCodeAccessTokenProviderWithConversionTests.java | 2 +- .../grant/code/AuthorizationCodeResourceDetailsTests.java | 2 +- .../grant/implicit/ImplicitAccessTokenProviderTests.java | 2 +- .../ResourceOwnerPasswordAccessTokenProviderTests.java | 2 +- .../oauth2/common/BaseOAuth2AccessTokenJacksonTest.java | 2 +- .../oauth2/common/DefaultOAuth2SerializationServiceTests.java | 2 +- .../security/oauth2/common/JsonSerializationTests.java | 2 +- .../common/OAuth2AccessTokenJackson1DeserializerTests.java | 2 +- .../common/OAuth2AccessTokenJackson2DeserializerTests.java | 2 +- .../common/exception/OAuth2ExceptionDeserializerTests.java | 2 +- .../exception/OAuth2ExceptionJackson2DeserializerTests.java | 2 +- .../common/exception/OAuth2ExceptionSerializerTests.java | 2 +- .../annotation/AuthorizationServerConfigurationTests.java | 2 +- .../oauth2/config/annotation/ClientConfigurationTests.java | 2 +- .../annotation/Gh501EnableAuthorizationServerTests.java | 2 +- .../annotation/Gh808EnableAuthorizationServerTests.java | 2 +- .../config/annotation/ResourceServerConfigurationTests.java | 2 +- .../config/annotation/TokenServicesMultipleBeansTests.java | 2 +- .../xml/AuthorizationServerBeanDefinitionParserTests.java | 2 +- ...izationServerClientCredentialsPasswordInvalidXmlTests.java | 2 +- ...orizationServerClientCredentialsPasswordValidXmlTests.java | 2 +- .../config/xml/InvalidResourceBeanDefinitionParserTests.java | 2 +- .../config/xml/ResourceServerBeanDefinitionParserTests.java | 2 +- .../http/converter/jaxb/BaseJaxbMessageConverterTest.java | 2 +- .../jaxb/JaxbOAuth2AccessTokenMessageConverterTests.java | 2 +- .../jaxb/JaxbOAuth2ExceptionMessageConverterTests.java | 2 +- .../security/oauth2/provider/AuthorizationRequestTests.java | 2 +- .../security/oauth2/provider/OAuth2RequestTests.java | 2 +- .../oauth2/provider/approval/AbstractTestApprovalStore.java | 2 +- .../provider/approval/DefaultUserApprovalHandlerTests.java | 2 +- .../oauth2/provider/approval/InMemoryApprovalStoreTests.java | 2 +- .../oauth2/provider/approval/JdbcApprovalStoreTests.java | 2 +- .../oauth2/provider/approval/TokenApprovalStoreTests.java | 2 +- .../provider/approval/TokenStoreUserApprovalHandlerTests.java | 2 +- .../authentication/OAuth2AuthenticationDetailsTests.java | 2 +- .../authentication/OAuth2AuthenticationManagerTests.java | 2 +- .../OAuth2AuthenticationProcessingFilterTests.java | 2 +- .../oauth2/provider/client/BaseClientDetailsTests.java | 2 +- .../client/ClientCredentialsTokenEndpointFilterTests.java | 2 +- .../provider/client/ClientDetailsUserDetailsServiceTests.java | 2 +- .../provider/code/AuthorizationCodeTokenGranterTests.java | 2 +- .../oauth2/provider/endpoint/AuthorizationEndpointTests.java | 2 +- .../oauth2/provider/endpoint/CheckTokenEndpointTest.java | 2 +- .../provider/endpoint/DefaultRedirectResolverTests.java | 2 +- .../provider/endpoint/ExactMatchRedirectResolverTests.java | 2 +- .../endpoint/FrameworkEndpointHandlerMappingTests.java | 2 +- .../endpoint/TokenEndpointAuthenticationFilterTests.java | 2 +- .../security/oauth2/provider/endpoint/TokenEndpointTests.java | 2 +- .../provider/endpoint/WhitelabelApprovalEndpointTests.java | 2 +- .../provider/endpoint/WhitelabelErrorEndpointTests.java | 2 +- .../error/DefaultWebResponseExceptionTranslatorTests.java | 2 +- .../oauth2/provider/error/OAuth2AccessDeniedHandlerTests.java | 2 +- .../provider/error/OAuth2AuthenticationEntryPointTests.java | 2 +- .../OAuth2MethodSecurityExpressionHandlerTests.java | 2 +- .../expression/OAuth2SecurityExpressionMethodsTests.java | 2 +- .../expression/OAuth2WebSecurityExpressionHandlerTests.java | 2 +- .../provider/implicit/InMemoryImplicitGrantServiceTests.java | 2 +- .../password/ResourceOwnerPasswordTokenGranterTests.java | 2 +- .../request/DefaultAuthorizationRequestFactoryTests.java | 2 +- .../provider/request/DefaultOAuth2RequestValidatorTests.java | 2 +- .../security/oauth2/provider/test/OAuth2RequestTests.java | 2 +- .../provider/token/AbstractDefaultTokenServicesTests.java | 2 +- .../provider/token/DefaultAccessTokenConverterTests.java | 2 +- .../provider/token/DefaultAuthenticationKeyGeneratorTest.java | 2 +- .../token/DefaultTokenServicesAuthoritiesChangeTests.java | 2 +- .../oauth2/provider/token/RemoteTokenServicesTest.java | 2 +- .../provider/token/TokenServicesWithTokenEnhancerTests.java | 2 +- .../oauth2/provider/token/store/IssuerClaimVerifierTest.java | 2 +- .../oauth2/provider/token/store/TokenStoreBaseTests.java | 2 +- .../provider/token/store/jwk/JwkDefinitionSourceITest.java | 2 +- .../provider/token/store/jwk/JwkDefinitionSourceTest.java | 2 +- .../oauth2/provider/token/store/jwk/JwkDefinitionTest.java | 2 +- .../oauth2/provider/token/store/jwk/JwkSetConverterTest.java | 2 +- .../oauth2/provider/token/store/jwk/JwkTokenStoreITest.java | 2 +- .../oauth2/provider/token/store/jwk/JwkTokenStoreTest.java | 2 +- .../store/jwk/JwkVerifyingJwtAccessTokenConverterTest.java | 2 +- .../provider/token/store/jwk/JwtHeaderConverterTest.java | 2 +- .../security/oauth2/provider/token/store/jwk/JwtTestUtil.java | 2 +- .../oauth2/provider/token/store/jwk/RsaJwkDefinitionTest.java | 2 +- .../provider/token/store/redis/RedisTokenStoreMockTests.java | 2 +- .../security/oauth2/provider/vote/ScopeVoterTests.java | 2 +- .../src/test/java/demo/AuthorizationCodeProviderTests.java | 2 +- .../approval/src/test/java/demo/ProtectedResourceTests.java | 2 +- .../client/src/test/java/client/CombinedApplication.java | 2 +- .../common/AbstractAuthorizationCodeProviderTests.java | 2 +- .../common/AbstractEmptyAuthorizationCodeProviderTests.java | 2 +- .../main/java/sparklr/common/AbstractIntegrationTests.java | 2 +- .../java/sparklr/common/AbstractProtectedResourceTests.java | 2 +- .../custom-grant/src/main/java/demo/CustomTokenGranter.java | 2 +- .../custom-grant/src/test/java/demo/AdHocTests.java | 2 +- .../src/test/java/demo/AuthorizationCodeProviderTests.java | 2 +- .../src/test/java/demo/ProtectedResourceTests.java | 2 +- tests/annotation/form/src/test/java/demo/AdHocTests.java | 2 +- .../src/test/java/demo/AuthorizationCodeProviderTests.java | 2 +- .../form/src/test/java/demo/ProtectedResourceTests.java | 2 +- .../src/test/java/demo/AuthorizationCodeProviderTests.java | 2 +- tests/annotation/jaxb/src/test/java/demo/Converters.java | 2 +- .../jaxb/src/test/java/demo/ProtectedResourceTests.java | 2 +- tests/annotation/jdbc/src/test/java/demo/AdHocTests.java | 2 +- .../src/test/java/demo/AuthorizationCodeProviderTests.java | 2 +- .../jdbc/src/test/java/demo/ProtectedResourceTests.java | 2 +- tests/annotation/jpa/src/test/java/demo/AdHocTests.java | 2 +- .../test/java/demo/AuthorizationCodeProviderCookieTests.java | 2 +- .../src/test/java/demo/AuthorizationCodeProviderTests.java | 2 +- .../jpa/src/test/java/demo/ProtectedResourceTests.java | 2 +- .../src/test/java/demo/AuthorizationCodeProviderTests.java | 2 +- .../jwt/src/test/java/demo/ProtectedResourceTests.java | 2 +- .../src/test/java/demo/AuthorizationCodeProviderTests.java | 2 +- .../mappings/src/test/java/demo/ProtectedResourceTests.java | 2 +- .../src/test/java/demo/AuthorizationCodeProviderTests.java | 2 +- .../multi/src/test/java/demo/ProtectedResourceTests.java | 2 +- .../resource/src/test/java/demo/ProtectedResourceTests.java | 2 +- .../test/java/demo/AuthorizationCodeProviderCookieTests.java | 2 +- .../src/test/java/demo/AuthorizationCodeProviderTests.java | 2 +- .../ssl/src/test/java/demo/ProtectedResourceTests.java | 2 +- tests/annotation/vanilla/src/test/java/demo/AdHocTests.java | 2 +- .../test/java/demo/AuthorizationCodeProviderCookieTests.java | 2 +- .../src/test/java/demo/AuthorizationCodeProviderTests.java | 2 +- .../vanilla/src/test/java/demo/ProtectedResourceTests.java | 2 +- .../src/test/java/demo/AuthorizationCodeProviderTests.java | 2 +- .../approval/src/test/java/demo/ProtectedResourceTests.java | 2 +- .../xml/client/src/test/java/client/CombinedApplication.java | 2 +- .../common/AbstractAuthorizationCodeProviderTests.java | 2 +- .../main/java/sparklr/common/AbstractIntegrationTests.java | 2 +- .../java/sparklr/common/AbstractProtectedResourceTests.java | 2 +- .../src/test/java/demo/AuthorizationCodeProviderTests.java | 2 +- tests/xml/form/src/test/java/demo/ProtectedResourceTests.java | 2 +- tests/xml/jdbc/src/test/java/demo/AdHocTests.java | 2 +- .../src/test/java/demo/AuthorizationCodeProviderTests.java | 2 +- tests/xml/jdbc/src/test/java/demo/ProtectedResourceTests.java | 2 +- .../src/test/java/demo/AuthorizationCodeProviderTests.java | 2 +- tests/xml/jwt/src/test/java/demo/ProtectedResourceTests.java | 2 +- .../src/test/java/demo/AuthorizationCodeProviderTests.java | 2 +- .../mappings/src/test/java/demo/ProtectedResourceTests.java | 2 +- .../src/test/java/demo/AuthorizationCodeProviderTests.java | 2 +- .../vanilla/src/test/java/demo/ProtectedResourceTests.java | 2 +- 449 files changed, 451 insertions(+), 451 deletions(-) diff --git a/license.txt b/license.txt index 261eeb9e9..20e4bd856 100755 --- a/license.txt +++ b/license.txt @@ -1,6 +1,6 @@ Apache License Version 2.0, January 2004 - http://www.apache.org/licenses/ + https://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION @@ -192,7 +192,7 @@ 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 + https://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, diff --git a/samples/oauth/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/impl/PhotoServiceImpl.java b/samples/oauth/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/impl/PhotoServiceImpl.java index f803497ed..6b96f61e3 100644 --- a/samples/oauth/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/impl/PhotoServiceImpl.java +++ b/samples/oauth/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/impl/PhotoServiceImpl.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/MethodSecurityConfig.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/MethodSecurityConfig.java index bb396e9cc..fe085e267 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/MethodSecurityConfig.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/MethodSecurityConfig.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java index 15744c4ef..42e638ade 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/ServletInitializer.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/ServletInitializer.java index ca0a61a91..1712f799c 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/ServletInitializer.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/ServletInitializer.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrUserApprovalHandler.java b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrUserApprovalHandler.java index 6ce4802b6..f9a79e655 100644 --- a/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrUserApprovalHandler.java +++ b/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/oauth/SparklrUserApprovalHandler.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/AuthorizationCodeProviderTests.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/AuthorizationCodeProviderTests.java index 12c54f673..2f986c809 100755 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/AuthorizationCodeProviderTests.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/oauth2/provider/AuthorizationCodeProviderTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/samples/oauth2/sparklr/src/test/java/org/springframework/security/samples/config/ApplicationConfigurationTests.java b/samples/oauth2/sparklr/src/test/java/org/springframework/security/samples/config/ApplicationConfigurationTests.java index c0ebc612e..fe6d2ee91 100644 --- a/samples/oauth2/sparklr/src/test/java/org/springframework/security/samples/config/ApplicationConfigurationTests.java +++ b/samples/oauth2/sparklr/src/test/java/org/springframework/security/samples/config/ApplicationConfigurationTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/ServletInitializer.java b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/ServletInitializer.java index 9dfd544eb..73b2be0ba 100644 --- a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/ServletInitializer.java +++ b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/ServletInitializer.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/converter/AccessTokenRequestConverter.java b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/converter/AccessTokenRequestConverter.java index 4dd475bde..56056fbb9 100644 --- a/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/converter/AccessTokenRequestConverter.java +++ b/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/tonr/converter/AccessTokenRequestConverter.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/samples/oauth2/tonr/src/test/java/org/springframework/security/samples/config/AdHocTests.java b/samples/oauth2/tonr/src/test/java/org/springframework/security/samples/config/AdHocTests.java index f9fd93b8b..8133a76db 100644 --- a/samples/oauth2/tonr/src/test/java/org/springframework/security/samples/config/AdHocTests.java +++ b/samples/oauth2/tonr/src/test/java/org/springframework/security/samples/config/AdHocTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/samples/oauth2/tonr/src/test/java/org/springframework/security/samples/config/SecurityConfigTests.java b/samples/oauth2/tonr/src/test/java/org/springframework/security/samples/config/SecurityConfigTests.java index 3b68447f1..b08ee85a3 100644 --- a/samples/oauth2/tonr/src/test/java/org/springframework/security/samples/config/SecurityConfigTests.java +++ b/samples/oauth2/tonr/src/test/java/org/springframework/security/samples/config/SecurityConfigTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-jwt/src/main/java/org/springframework/security/jwt/AlgorithmMetadata.java b/spring-security-jwt/src/main/java/org/springframework/security/jwt/AlgorithmMetadata.java index d4d72867d..029e563f3 100644 --- a/spring-security-jwt/src/main/java/org/springframework/security/jwt/AlgorithmMetadata.java +++ b/spring-security-jwt/src/main/java/org/springframework/security/jwt/AlgorithmMetadata.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-jwt/src/main/java/org/springframework/security/jwt/BinaryFormat.java b/spring-security-jwt/src/main/java/org/springframework/security/jwt/BinaryFormat.java index aaded18a0..1ca933a7f 100644 --- a/spring-security-jwt/src/main/java/org/springframework/security/jwt/BinaryFormat.java +++ b/spring-security-jwt/src/main/java/org/springframework/security/jwt/BinaryFormat.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-jwt/src/main/java/org/springframework/security/jwt/Jwt.java b/spring-security-jwt/src/main/java/org/springframework/security/jwt/Jwt.java index be3b253ef..97b67af47 100644 --- a/spring-security-jwt/src/main/java/org/springframework/security/jwt/Jwt.java +++ b/spring-security-jwt/src/main/java/org/springframework/security/jwt/Jwt.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-jwt/src/main/java/org/springframework/security/jwt/JwtAlgorithms.java b/spring-security-jwt/src/main/java/org/springframework/security/jwt/JwtAlgorithms.java index 6d837c6e7..cba16c5d0 100644 --- a/spring-security-jwt/src/main/java/org/springframework/security/jwt/JwtAlgorithms.java +++ b/spring-security-jwt/src/main/java/org/springframework/security/jwt/JwtAlgorithms.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-jwt/src/main/java/org/springframework/security/jwt/JwtHelper.java b/spring-security-jwt/src/main/java/org/springframework/security/jwt/JwtHelper.java index b239a68e8..b2d192155 100644 --- a/spring-security-jwt/src/main/java/org/springframework/security/jwt/JwtHelper.java +++ b/spring-security-jwt/src/main/java/org/springframework/security/jwt/JwtHelper.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-jwt/src/main/java/org/springframework/security/jwt/codec/Codecs.java b/spring-security-jwt/src/main/java/org/springframework/security/jwt/codec/Codecs.java index a654e52a5..d2f63894e 100644 --- a/spring-security-jwt/src/main/java/org/springframework/security/jwt/codec/Codecs.java +++ b/spring-security-jwt/src/main/java/org/springframework/security/jwt/codec/Codecs.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/cipher/CipherMetadata.java b/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/cipher/CipherMetadata.java index c8edfce77..5e9d107f7 100644 --- a/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/cipher/CipherMetadata.java +++ b/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/cipher/CipherMetadata.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/EllipticCurveKeyHelper.java b/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/EllipticCurveKeyHelper.java index f9b88f411..485d06a95 100644 --- a/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/EllipticCurveKeyHelper.java +++ b/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/EllipticCurveKeyHelper.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/EllipticCurveSignatureHelper.java b/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/EllipticCurveSignatureHelper.java index d1ee99dde..8d6b911ed 100644 --- a/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/EllipticCurveSignatureHelper.java +++ b/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/EllipticCurveSignatureHelper.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/EllipticCurveVerifier.java b/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/EllipticCurveVerifier.java index 00e525829..38c7bffb9 100644 --- a/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/EllipticCurveVerifier.java +++ b/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/EllipticCurveVerifier.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/InvalidSignatureException.java b/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/InvalidSignatureException.java index 15095325c..be63ca705 100644 --- a/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/InvalidSignatureException.java +++ b/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/InvalidSignatureException.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/MacSigner.java b/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/MacSigner.java index 71f75bbef..2f6c0add2 100644 --- a/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/MacSigner.java +++ b/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/MacSigner.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/RsaKeyHelper.java b/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/RsaKeyHelper.java index 41f36e47e..f15862a5e 100644 --- a/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/RsaKeyHelper.java +++ b/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/RsaKeyHelper.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/RsaSigner.java b/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/RsaSigner.java index bbd6b240a..04ed3cff5 100644 --- a/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/RsaSigner.java +++ b/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/RsaSigner.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/RsaVerifier.java b/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/RsaVerifier.java index faa562e1c..dc3944d21 100644 --- a/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/RsaVerifier.java +++ b/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/RsaVerifier.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/SignatureVerifier.java b/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/SignatureVerifier.java index 4a3371676..a74fc6c88 100644 --- a/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/SignatureVerifier.java +++ b/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/SignatureVerifier.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/Signer.java b/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/Signer.java index 2c5d98bda..5067e8b6f 100644 --- a/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/Signer.java +++ b/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/Signer.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/SignerVerifier.java b/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/SignerVerifier.java index 00c52b713..3e5307438 100644 --- a/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/SignerVerifier.java +++ b/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/SignerVerifier.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-jwt/src/test/java/org/springframework/security/jwt/JwtSpecData.java b/spring-security-jwt/src/test/java/org/springframework/security/jwt/JwtSpecData.java index a5fc71707..99139ee12 100644 --- a/spring-security-jwt/src/test/java/org/springframework/security/jwt/JwtSpecData.java +++ b/spring-security-jwt/src/test/java/org/springframework/security/jwt/JwtSpecData.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-jwt/src/test/java/org/springframework/security/jwt/JwtTests.java b/spring-security-jwt/src/test/java/org/springframework/security/jwt/JwtTests.java index 1cdc5793e..1a5eb20cc 100644 --- a/spring-security-jwt/src/test/java/org/springframework/security/jwt/JwtTests.java +++ b/spring-security-jwt/src/test/java/org/springframework/security/jwt/JwtTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-jwt/src/test/java/org/springframework/security/jwt/RubyJwtIntegrationTests.java b/spring-security-jwt/src/test/java/org/springframework/security/jwt/RubyJwtIntegrationTests.java index dd2f3bd74..6aa3b406a 100644 --- a/spring-security-jwt/src/test/java/org/springframework/security/jwt/RubyJwtIntegrationTests.java +++ b/spring-security-jwt/src/test/java/org/springframework/security/jwt/RubyJwtIntegrationTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-jwt/src/test/java/org/springframework/security/jwt/crypto/cipher/RsaTestKeyData.java b/spring-security-jwt/src/test/java/org/springframework/security/jwt/crypto/cipher/RsaTestKeyData.java index b37d29504..b0901127d 100644 --- a/spring-security-jwt/src/test/java/org/springframework/security/jwt/crypto/cipher/RsaTestKeyData.java +++ b/spring-security-jwt/src/test/java/org/springframework/security/jwt/crypto/cipher/RsaTestKeyData.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-jwt/src/test/java/org/springframework/security/jwt/crypto/sign/EllipticCurveVerifierTests.java b/spring-security-jwt/src/test/java/org/springframework/security/jwt/crypto/sign/EllipticCurveVerifierTests.java index f4e581757..718c9016d 100644 --- a/spring-security-jwt/src/test/java/org/springframework/security/jwt/crypto/sign/EllipticCurveVerifierTests.java +++ b/spring-security-jwt/src/test/java/org/springframework/security/jwt/crypto/sign/EllipticCurveVerifierTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-jwt/src/test/java/org/springframework/security/jwt/crypto/sign/RsaSigningTests.java b/spring-security-jwt/src/test/java/org/springframework/security/jwt/crypto/sign/RsaSigningTests.java index 363dee8ef..27e8dbb46 100644 --- a/spring-security-jwt/src/test/java/org/springframework/security/jwt/crypto/sign/RsaSigningTests.java +++ b/spring-security-jwt/src/test/java/org/springframework/security/jwt/crypto/sign/RsaSigningTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/OAuthCodec.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/OAuthCodec.java index 44ee7fc3b..0e917b772 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/OAuthCodec.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/OAuthCodec.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/OAuthConsumerParameter.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/OAuthConsumerParameter.java index c485601d5..91127a909 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/OAuthConsumerParameter.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/OAuthConsumerParameter.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/OAuthException.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/OAuthException.java index 7fc06de64..fc6e727a5 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/OAuthException.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/OAuthException.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/OAuthProviderParameter.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/OAuthProviderParameter.java index 30ce020ab..fdcd0ceae 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/OAuthProviderParameter.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/OAuthProviderParameter.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/CoreOAuthSignatureMethodFactory.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/CoreOAuthSignatureMethodFactory.java index 07f4e0758..0e736d7b1 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/CoreOAuthSignatureMethodFactory.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/CoreOAuthSignatureMethodFactory.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/HMAC_SHA1SignatureMethod.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/HMAC_SHA1SignatureMethod.java index 88e78edab..6fb680f6b 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/HMAC_SHA1SignatureMethod.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/HMAC_SHA1SignatureMethod.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/InvalidSignatureException.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/InvalidSignatureException.java index de5196961..260bee365 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/InvalidSignatureException.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/InvalidSignatureException.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/OAuthSignatureMethod.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/OAuthSignatureMethod.java index 01c85c3e2..348684003 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/OAuthSignatureMethod.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/OAuthSignatureMethod.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/OAuthSignatureMethodFactory.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/OAuthSignatureMethodFactory.java index a26a88a80..00f015391 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/OAuthSignatureMethodFactory.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/OAuthSignatureMethodFactory.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/PlainTextSignatureMethod.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/PlainTextSignatureMethod.java index 4b9be8946..31e6eae7d 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/PlainTextSignatureMethod.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/PlainTextSignatureMethod.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/RSAKeySecret.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/RSAKeySecret.java index 0f0da404f..21b49bcd1 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/RSAKeySecret.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/RSAKeySecret.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/RSA_SHA1SignatureMethod.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/RSA_SHA1SignatureMethod.java index 27a63419f..0c6a6cec9 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/RSA_SHA1SignatureMethod.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/RSA_SHA1SignatureMethod.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/SharedConsumerSecret.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/SharedConsumerSecret.java index 62423232e..9d0c07229 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/SharedConsumerSecret.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/SharedConsumerSecret.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/SharedConsumerSecretImpl.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/SharedConsumerSecretImpl.java index dbde015ee..dff207c00 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/SharedConsumerSecretImpl.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/SharedConsumerSecretImpl.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/SignatureSecret.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/SignatureSecret.java index b695d5e9c..8110de2a9 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/SignatureSecret.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/SignatureSecret.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/SignatureSecretEditor.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/SignatureSecretEditor.java index 64695177b..7702c508d 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/SignatureSecretEditor.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/SignatureSecretEditor.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/UnsupportedSignatureMethodException.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/UnsupportedSignatureMethodException.java index 422955590..88f1a4782 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/UnsupportedSignatureMethodException.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/common/signature/UnsupportedSignatureMethodException.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/ConsumerDetailsFactoryBean.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/ConsumerDetailsFactoryBean.java index 433904ccc..b3220e3e7 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/ConsumerDetailsFactoryBean.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/ConsumerDetailsFactoryBean.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/ConsumerServiceBeanDefinitionParser.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/ConsumerServiceBeanDefinitionParser.java index de91a6097..d8cfba0d1 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/ConsumerServiceBeanDefinitionParser.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/ConsumerServiceBeanDefinitionParser.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/ExpressionHandlerBeanDefinitionParser.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/ExpressionHandlerBeanDefinitionParser.java index 333fa1607..30e4118ac 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/ExpressionHandlerBeanDefinitionParser.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/ExpressionHandlerBeanDefinitionParser.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/OAuthConsumerBeanDefinitionParser.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/OAuthConsumerBeanDefinitionParser.java index 025c3eeb0..004fc87d5 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/OAuthConsumerBeanDefinitionParser.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/OAuthConsumerBeanDefinitionParser.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/OAuthProviderBeanDefinitionParser.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/OAuthProviderBeanDefinitionParser.java index dcb201c3e..5a1873e8c 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/OAuthProviderBeanDefinitionParser.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/OAuthProviderBeanDefinitionParser.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/OAuthSecurityNamespaceHandler.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/OAuthSecurityNamespaceHandler.java index e92a268ea..91cdaba92 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/OAuthSecurityNamespaceHandler.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/OAuthSecurityNamespaceHandler.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/ProtectedResourceDetailsBeanDefinitionParser.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/ProtectedResourceDetailsBeanDefinitionParser.java index c12d19820..ac4cdb905 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/ProtectedResourceDetailsBeanDefinitionParser.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/ProtectedResourceDetailsBeanDefinitionParser.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/TokenServiceBeanDefinitionParser.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/TokenServiceBeanDefinitionParser.java index 84c9095f9..784a69790 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/TokenServiceBeanDefinitionParser.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/TokenServiceBeanDefinitionParser.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/VerifierServiceBeanDefinitionParser.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/VerifierServiceBeanDefinitionParser.java index b22bec73d..8f85b150a 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/VerifierServiceBeanDefinitionParser.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/config/VerifierServiceBeanDefinitionParser.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/BaseProtectedResourceDetails.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/BaseProtectedResourceDetails.java index 8687c8de3..7a35df339 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/BaseProtectedResourceDetails.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/BaseProtectedResourceDetails.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/InMemoryProtectedResourceDetailsService.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/InMemoryProtectedResourceDetailsService.java index 7b0ca51fe..3d50987c2 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/InMemoryProtectedResourceDetailsService.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/InMemoryProtectedResourceDetailsService.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/InvalidOAuthRealmException.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/InvalidOAuthRealmException.java index ffc5536c7..4dfd1c010 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/InvalidOAuthRealmException.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/InvalidOAuthRealmException.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/OAuthConsumerSupport.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/OAuthConsumerSupport.java index 38c3dd851..fda9d13b5 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/OAuthConsumerSupport.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/OAuthConsumerSupport.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/OAuthConsumerToken.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/OAuthConsumerToken.java index 4ab2ecaaf..6472e24f5 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/OAuthConsumerToken.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/OAuthConsumerToken.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/OAuthRequestFailedException.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/OAuthRequestFailedException.java index ed92ba098..1e914cb36 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/OAuthRequestFailedException.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/OAuthRequestFailedException.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/ProtectedResourceDetails.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/ProtectedResourceDetails.java index f52181a6a..9e8ac672d 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/ProtectedResourceDetails.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/ProtectedResourceDetails.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/ProtectedResourceDetailsService.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/ProtectedResourceDetailsService.java index edd28ae21..f690fc042 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/ProtectedResourceDetailsService.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/ProtectedResourceDetailsService.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/UnverifiedRequestTokenException.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/UnverifiedRequestTokenException.java index cf0a54262..876f8c674 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/UnverifiedRequestTokenException.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/UnverifiedRequestTokenException.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/client/CoreOAuthConsumerSupport.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/client/CoreOAuthConsumerSupport.java index 36ab3b822..ddb718629 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/client/CoreOAuthConsumerSupport.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/client/CoreOAuthConsumerSupport.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/filter/OAuthConsumerContextFilter.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/filter/OAuthConsumerContextFilter.java index 8fb413a1a..776750baa 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/filter/OAuthConsumerContextFilter.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/filter/OAuthConsumerContextFilter.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/filter/OAuthConsumerProcessingFilter.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/filter/OAuthConsumerProcessingFilter.java index d8aa8d900..4a38aeecb 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/filter/OAuthConsumerProcessingFilter.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/filter/OAuthConsumerProcessingFilter.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/net/DefaultOAuthURLStreamHandlerFactory.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/net/DefaultOAuthURLStreamHandlerFactory.java index eb415be7b..b7b242900 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/net/DefaultOAuthURLStreamHandlerFactory.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/net/DefaultOAuthURLStreamHandlerFactory.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/net/OAuthOverHttpURLStreamHandler.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/net/OAuthOverHttpURLStreamHandler.java index 5ce53d96b..321d27fea 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/net/OAuthOverHttpURLStreamHandler.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/net/OAuthOverHttpURLStreamHandler.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/net/OAuthOverHttpsURLStreamHandler.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/net/OAuthOverHttpsURLStreamHandler.java index de6bbbbd1..1f1dc3159 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/net/OAuthOverHttpsURLStreamHandler.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/net/OAuthOverHttpsURLStreamHandler.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/net/OAuthURLStreamHandlerFactory.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/net/OAuthURLStreamHandlerFactory.java index 507088b1a..022d4719b 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/net/OAuthURLStreamHandlerFactory.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/net/OAuthURLStreamHandlerFactory.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/nonce/NonceFactory.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/nonce/NonceFactory.java index 82ff87a52..fa8315175 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/nonce/NonceFactory.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/nonce/NonceFactory.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/nonce/UUIDNonceFactory.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/nonce/UUIDNonceFactory.java index 028a47319..ca22d5dca 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/nonce/UUIDNonceFactory.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/nonce/UUIDNonceFactory.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/token/HttpSessionBasedTokenServices.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/token/HttpSessionBasedTokenServices.java index abfa1ce74..5cd4d987d 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/token/HttpSessionBasedTokenServices.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/token/HttpSessionBasedTokenServices.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/token/OAuthConsumerTokenServices.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/token/OAuthConsumerTokenServices.java index 854c205e7..a97c11a8b 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/token/OAuthConsumerTokenServices.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/consumer/token/OAuthConsumerTokenServices.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/BaseConsumerDetails.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/BaseConsumerDetails.java index 250172ff9..2f4a402ef 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/BaseConsumerDetails.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/BaseConsumerDetails.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ConsumerAuthentication.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ConsumerAuthentication.java index 6d5e37fce..3246e7e63 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ConsumerAuthentication.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ConsumerAuthentication.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ConsumerCredentials.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ConsumerCredentials.java index 5afe5324d..48b983954 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ConsumerCredentials.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ConsumerCredentials.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ConsumerDetails.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ConsumerDetails.java index c90a1baf6..9756f19fa 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ConsumerDetails.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ConsumerDetails.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ConsumerDetailsService.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ConsumerDetailsService.java index a67415592..41c52a421 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ConsumerDetailsService.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ConsumerDetailsService.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ExtraTrustConsumerDetails.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ExtraTrustConsumerDetails.java index 8c82ae5d3..4e5cd0d4c 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ExtraTrustConsumerDetails.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ExtraTrustConsumerDetails.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/InMemoryConsumerDetailsService.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/InMemoryConsumerDetailsService.java index 4a153a0a9..f8dc7cbd0 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/InMemoryConsumerDetailsService.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/InMemoryConsumerDetailsService.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/InvalidOAuthParametersException.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/InvalidOAuthParametersException.java index 8c8a93f05..de4753471 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/InvalidOAuthParametersException.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/InvalidOAuthParametersException.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/OAuthAuthenticationDetails.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/OAuthAuthenticationDetails.java index 66843bcaa..58ee7ee59 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/OAuthAuthenticationDetails.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/OAuthAuthenticationDetails.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/OAuthProcessingFilterEntryPoint.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/OAuthProcessingFilterEntryPoint.java index 3de65b479..8125ad077 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/OAuthProcessingFilterEntryPoint.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/OAuthProcessingFilterEntryPoint.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/OAuthProviderSupport.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/OAuthProviderSupport.java index f5b2af59e..c44e0a177 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/OAuthProviderSupport.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/OAuthProviderSupport.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/OAuthVersionUnsupportedException.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/OAuthVersionUnsupportedException.java index d715ac562..ea6a20eca 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/OAuthVersionUnsupportedException.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/OAuthVersionUnsupportedException.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ResourceSpecificConsumerDetails.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ResourceSpecificConsumerDetails.java index 0cffc2c05..0622281dc 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ResourceSpecificConsumerDetails.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/ResourceSpecificConsumerDetails.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/attributes/ConsumerKeysAllowed.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/attributes/ConsumerKeysAllowed.java index 8a95c59f6..8d77626bf 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/attributes/ConsumerKeysAllowed.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/attributes/ConsumerKeysAllowed.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/attributes/ConsumerRolesAllowed.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/attributes/ConsumerRolesAllowed.java index 8ed5bb49e..31ffbb298 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/attributes/ConsumerRolesAllowed.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/attributes/ConsumerRolesAllowed.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/attributes/ConsumerSecurityConfig.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/attributes/ConsumerSecurityConfig.java index 0fcd5869a..e6ad3e9b1 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/attributes/ConsumerSecurityConfig.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/attributes/ConsumerSecurityConfig.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/attributes/ConsumerSecurityMetadataSource.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/attributes/ConsumerSecurityMetadataSource.java index 2744a95da..8fcd6fe40 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/attributes/ConsumerSecurityMetadataSource.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/attributes/ConsumerSecurityMetadataSource.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/attributes/ConsumerSecurityVoter.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/attributes/ConsumerSecurityVoter.java index ffc53105b..fc26ba7c1 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/attributes/ConsumerSecurityVoter.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/attributes/ConsumerSecurityVoter.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/attributes/DenyAllConsumers.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/attributes/DenyAllConsumers.java index 7b9709c82..667c097ab 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/attributes/DenyAllConsumers.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/attributes/DenyAllConsumers.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/attributes/PermitAllConsumers.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/attributes/PermitAllConsumers.java index 99f8acc4f..859c105ee 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/attributes/PermitAllConsumers.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/attributes/PermitAllConsumers.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/AccessTokenProcessingFilter.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/AccessTokenProcessingFilter.java index 0a9bf8c42..a35eddd76 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/AccessTokenProcessingFilter.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/AccessTokenProcessingFilter.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/CoreOAuthProviderSupport.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/CoreOAuthProviderSupport.java index b46b989aa..93cbb612b 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/CoreOAuthProviderSupport.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/CoreOAuthProviderSupport.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/OAuthProviderProcessingFilter.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/OAuthProviderProcessingFilter.java index 8b6055584..e317593c8 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/OAuthProviderProcessingFilter.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/OAuthProviderProcessingFilter.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/ProtectedResourceProcessingFilter.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/ProtectedResourceProcessingFilter.java index cf7e5b5e0..9c75e1aa6 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/ProtectedResourceProcessingFilter.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/ProtectedResourceProcessingFilter.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/UnauthenticatedRequestTokenProcessingFilter.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/UnauthenticatedRequestTokenProcessingFilter.java index 3ac546d0d..f8df77f16 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/UnauthenticatedRequestTokenProcessingFilter.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/UnauthenticatedRequestTokenProcessingFilter.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/UserAuthorizationProcessingFilter.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/UserAuthorizationProcessingFilter.java index 3e8b81e48..ecff6e192 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/UserAuthorizationProcessingFilter.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/UserAuthorizationProcessingFilter.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/UserAuthorizationSuccessfulAuthenticationHandler.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/UserAuthorizationSuccessfulAuthenticationHandler.java index 0135a396a..c5558783f 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/UserAuthorizationSuccessfulAuthenticationHandler.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/filter/UserAuthorizationSuccessfulAuthenticationHandler.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/nonce/ExpiringTimestampNonceServices.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/nonce/ExpiringTimestampNonceServices.java index bfaf53972..8e3cf38e1 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/nonce/ExpiringTimestampNonceServices.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/nonce/ExpiringTimestampNonceServices.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/nonce/InMemoryNonceServices.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/nonce/InMemoryNonceServices.java index dce75709e..a4e726949 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/nonce/InMemoryNonceServices.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/nonce/InMemoryNonceServices.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/nonce/NonceAlreadyUsedException.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/nonce/NonceAlreadyUsedException.java index a3d180bf3..0a8d7845c 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/nonce/NonceAlreadyUsedException.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/nonce/NonceAlreadyUsedException.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/nonce/NullNonceServices.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/nonce/NullNonceServices.java index 0b2719f07..084ad767c 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/nonce/NullNonceServices.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/nonce/NullNonceServices.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/nonce/OAuthNonceServices.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/nonce/OAuthNonceServices.java index 91611fc62..2c5710bf6 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/nonce/OAuthNonceServices.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/nonce/OAuthNonceServices.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/ExpiredOAuthTokenException.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/ExpiredOAuthTokenException.java index 37222ba5c..c29acbff0 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/ExpiredOAuthTokenException.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/ExpiredOAuthTokenException.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/InMemoryProviderTokenServices.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/InMemoryProviderTokenServices.java index f68b2e420..f35ced78c 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/InMemoryProviderTokenServices.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/InMemoryProviderTokenServices.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/InMemorySelfCleaningProviderTokenServices.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/InMemorySelfCleaningProviderTokenServices.java index 3142eaf9b..7a8ce4bf6 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/InMemorySelfCleaningProviderTokenServices.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/InMemorySelfCleaningProviderTokenServices.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/InvalidOAuthTokenException.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/InvalidOAuthTokenException.java index 113ea14f3..b9984615a 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/InvalidOAuthTokenException.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/InvalidOAuthTokenException.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/OAuthAccessProviderToken.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/OAuthAccessProviderToken.java index 858ae43e6..c37038a8d 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/OAuthAccessProviderToken.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/OAuthAccessProviderToken.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/OAuthProviderToken.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/OAuthProviderToken.java index 15b0f3922..71cf6596b 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/OAuthProviderToken.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/OAuthProviderToken.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/OAuthProviderTokenImpl.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/OAuthProviderTokenImpl.java index 8a5c24a86..b8244dc39 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/OAuthProviderTokenImpl.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/OAuthProviderTokenImpl.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/OAuthProviderTokenServices.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/OAuthProviderTokenServices.java index b345a9bbd..4dff7d643 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/OAuthProviderTokenServices.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/OAuthProviderTokenServices.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/RandomValueProviderTokenServices.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/RandomValueProviderTokenServices.java index 8ae12b88f..6d8e4df96 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/RandomValueProviderTokenServices.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/token/RandomValueProviderTokenServices.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/verifier/VerificationFailedException.java b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/verifier/VerificationFailedException.java index 90d78788e..2c8a04a88 100644 --- a/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/verifier/VerificationFailedException.java +++ b/spring-security-oauth/src/main/java/org/springframework/security/oauth/provider/verifier/VerificationFailedException.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/test/java/net/oauth/signature/GoogleCodeCompatibilityTests.java b/spring-security-oauth/src/test/java/net/oauth/signature/GoogleCodeCompatibilityTests.java index e8c8b3a3e..ffb90bc58 100644 --- a/spring-security-oauth/src/test/java/net/oauth/signature/GoogleCodeCompatibilityTests.java +++ b/spring-security-oauth/src/test/java/net/oauth/signature/GoogleCodeCompatibilityTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/OAuthCodecTests.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/OAuthCodecTests.java index 06c870332..cc55abddf 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/OAuthCodecTests.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/OAuthCodecTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/CoreOAuthSignatureMethodFactoryTests.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/CoreOAuthSignatureMethodFactoryTests.java index 90c0b9be0..107277d77 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/CoreOAuthSignatureMethodFactoryTests.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/CoreOAuthSignatureMethodFactoryTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/HMAC_SHA1SignatureMethodTests.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/HMAC_SHA1SignatureMethodTests.java index 293cad1d6..0ebf3994b 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/HMAC_SHA1SignatureMethodTests.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/HMAC_SHA1SignatureMethodTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/PlainTextSignatureMethodTests.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/PlainTextSignatureMethodTests.java index 08927a001..fdcc840f5 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/PlainTextSignatureMethodTests.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/PlainTextSignatureMethodTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/RSA_SHA1SignatureMethodTests.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/RSA_SHA1SignatureMethodTests.java index 8b8c77570..e68dd10ad 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/RSA_SHA1SignatureMethodTests.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/common/signature/RSA_SHA1SignatureMethodTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/config/AuthorizationServerBeanDefinitionParserTests.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/config/AuthorizationServerBeanDefinitionParserTests.java index d2000dd4d..322a0bad2 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/config/AuthorizationServerBeanDefinitionParserTests.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/config/AuthorizationServerBeanDefinitionParserTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/client/CoreOAuthConsumerSupportTests.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/client/CoreOAuthConsumerSupportTests.java index 08673d126..f4b391848 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/client/CoreOAuthConsumerSupportTests.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/client/CoreOAuthConsumerSupportTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/rememberme/HttpSessionOAuthRememberMeServicesTests.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/rememberme/HttpSessionOAuthRememberMeServicesTests.java index 9beba686b..b20fa8e57 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/rememberme/HttpSessionOAuthRememberMeServicesTests.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/consumer/rememberme/HttpSessionOAuthRememberMeServicesTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/CoreOAuthProviderSupportTests.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/CoreOAuthProviderSupportTests.java index 451e42aaf..919d59dd9 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/CoreOAuthProviderSupportTests.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/CoreOAuthProviderSupportTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/AccessTokenProcessingFilterTests.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/AccessTokenProcessingFilterTests.java index 0360eecfb..5199c30fe 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/AccessTokenProcessingFilterTests.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/AccessTokenProcessingFilterTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/OAuthProcessingFilterTests.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/OAuthProcessingFilterTests.java index ab0a9ac90..b164b14bb 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/OAuthProcessingFilterTests.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/OAuthProcessingFilterTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/OAuthUserAuthorizationProcessingFilterTests.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/OAuthUserAuthorizationProcessingFilterTests.java index 76d57d0e0..ff967daed 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/OAuthUserAuthorizationProcessingFilterTests.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/OAuthUserAuthorizationProcessingFilterTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/ProtectedResourceProcessingFilterTests.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/ProtectedResourceProcessingFilterTests.java index 4f8f4cc30..8fc88f830 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/ProtectedResourceProcessingFilterTests.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/ProtectedResourceProcessingFilterTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/UnauthenticatedRequestTokenProcessingFilterTests.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/UnauthenticatedRequestTokenProcessingFilterTests.java index c6d27c93d..fb3fc1ac3 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/UnauthenticatedRequestTokenProcessingFilterTests.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/UnauthenticatedRequestTokenProcessingFilterTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/UserAuthorizationSuccessfulAuthenticationHandlerTests.java b/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/UserAuthorizationSuccessfulAuthenticationHandlerTests.java index 6924e6b4d..16f8b2359 100644 --- a/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/UserAuthorizationSuccessfulAuthenticationHandlerTests.java +++ b/spring-security-oauth/src/test/java/org/springframework/security/oauth/provider/filter/UserAuthorizationSuccessfulAuthenticationHandlerTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/DefaultOAuth2RequestAuthenticator.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/DefaultOAuth2RequestAuthenticator.java index 92d5125f2..a6114b9fe 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/DefaultOAuth2RequestAuthenticator.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/DefaultOAuth2RequestAuthenticator.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/OAuth2ClientContext.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/OAuth2ClientContext.java index de2b27876..9af13b874 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/OAuth2ClientContext.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/OAuth2ClientContext.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/OAuth2RequestAuthenticator.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/OAuth2RequestAuthenticator.java index 222e85836..6b668bd6b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/OAuth2RequestAuthenticator.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/OAuth2RequestAuthenticator.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/OAuth2RestOperations.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/OAuth2RestOperations.java index 1abea6d81..8a3967f7e 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/OAuth2RestOperations.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/OAuth2RestOperations.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/discovery/ProviderConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/discovery/ProviderConfiguration.java index 7cde6f8c9..e95a7c793 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/discovery/ProviderConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/discovery/ProviderConfiguration.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/discovery/ProviderDiscoveryClient.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/discovery/ProviderDiscoveryClient.java index fc2ecbe22..10c8a9d4d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/discovery/ProviderDiscoveryClient.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/discovery/ProviderDiscoveryClient.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilter.java index b616712ce..aeb8f477e 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilter.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/state/DefaultStateKeyGenerator.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/state/DefaultStateKeyGenerator.java index 569007200..94af21a2c 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/state/DefaultStateKeyGenerator.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/state/DefaultStateKeyGenerator.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/state/StateKeyGenerator.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/state/StateKeyGenerator.java index 58fc0638c..81cbd9511 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/state/StateKeyGenerator.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/filter/state/StateKeyGenerator.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandler.java index af510e2ae..8b2b42038 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandler.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/resource/UserApprovalRequiredException.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/resource/UserApprovalRequiredException.java index 144f9f399..f885264d8 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/resource/UserApprovalRequiredException.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/resource/UserApprovalRequiredException.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/BeforeOAuth2Context.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/BeforeOAuth2Context.java index f190be6ea..1fa2fbdd3 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/BeforeOAuth2Context.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/BeforeOAuth2Context.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/OAuth2ContextConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/OAuth2ContextConfiguration.java index f09930fa3..e4bf56ed4 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/OAuth2ContextConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/OAuth2ContextConfiguration.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/OAuth2ContextSetup.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/OAuth2ContextSetup.java index 83529d7e6..f9c932ed8 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/OAuth2ContextSetup.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/OAuth2ContextSetup.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/RestTemplateHolder.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/RestTemplateHolder.java index aa5a863cd..c14aabf5f 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/RestTemplateHolder.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/RestTemplateHolder.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/TestAccounts.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/TestAccounts.java index e7ca361d0..782532ce7 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/TestAccounts.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/test/TestAccounts.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/AccessTokenProvider.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/AccessTokenProvider.java index 025e36f55..bd3e3a382 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/AccessTokenProvider.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/AccessTokenProvider.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/AccessTokenProviderChain.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/AccessTokenProviderChain.java index 5564db383..86e5abc0e 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/AccessTokenProviderChain.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/AccessTokenProviderChain.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/AccessTokenRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/AccessTokenRequest.java index cd7ead483..85d0c2a67 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/AccessTokenRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/AccessTokenRequest.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/ClientKeyGenerator.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/ClientKeyGenerator.java index 9d8eb0fd0..58f376277 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/ClientKeyGenerator.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/ClientKeyGenerator.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/ClientTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/ClientTokenServices.java index 95811454b..0aef5cc19 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/ClientTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/ClientTokenServices.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/DefaultAccessTokenRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/DefaultAccessTokenRequest.java index 90c445af1..72a8f21af 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/DefaultAccessTokenRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/DefaultAccessTokenRequest.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/DefaultClientKeyGenerator.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/DefaultClientKeyGenerator.java index 5d5264983..b473d77c2 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/DefaultClientKeyGenerator.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/DefaultClientKeyGenerator.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/DefaultRequestEnhancer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/DefaultRequestEnhancer.java index f2356ae01..09ca76bd7 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/DefaultRequestEnhancer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/DefaultRequestEnhancer.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/RequestEnhancer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/RequestEnhancer.java index bb1a153b8..b6442bb1b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/RequestEnhancer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/RequestEnhancer.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/auth/ClientAuthenticationHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/auth/ClientAuthenticationHandler.java index 800130dca..b62669fda 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/auth/ClientAuthenticationHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/auth/ClientAuthenticationHandler.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProvider.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProvider.java index 37743c624..8a6ea6390 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProvider.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProvider.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -20,7 +20,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/password/ResourceOwnerPasswordResourceDetails.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/password/ResourceOwnerPasswordResourceDetails.java index b20155e8b..54fde4247 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/password/ResourceOwnerPasswordResourceDetails.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/password/ResourceOwnerPasswordResourceDetails.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/AuthenticationScheme.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/AuthenticationScheme.java index f4d75d22b..86b6e30e6 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/AuthenticationScheme.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/AuthenticationScheme.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/ExpiringOAuth2RefreshToken.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/ExpiringOAuth2RefreshToken.java index abeb44b90..d69672935 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/ExpiringOAuth2RefreshToken.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/ExpiringOAuth2RefreshToken.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessToken.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessToken.java index 0d2ea97ca..44959a85d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessToken.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessToken.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson1Deserializer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson1Deserializer.java index 68bbf55e9..66037bbc9 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson1Deserializer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson1Deserializer.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson1Serializer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson1Serializer.java index 2f2768a32..1fd3fe777 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson1Serializer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson1Serializer.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2Deserializer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2Deserializer.java index 608422d1f..9254d851f 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2Deserializer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2Deserializer.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2Serializer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2Serializer.java index f006e3998..60632949b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2Serializer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2Serializer.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2RefreshToken.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2RefreshToken.java index 9283b5e9a..2caf151e7 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2RefreshToken.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2RefreshToken.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/InvalidTokenException.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/InvalidTokenException.java index 527fdced8..555cc4a7c 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/InvalidTokenException.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/InvalidTokenException.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson1Deserializer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson1Deserializer.java index c9f4b68ab..a32e4e521 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson1Deserializer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson1Deserializer.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson1Serializer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson1Serializer.java index 091068177..c97d16ec2 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson1Serializer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson1Serializer.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson2Deserializer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson2Deserializer.java index 92a32aba6..516f39f41 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson2Deserializer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson2Deserializer.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson2Serializer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson2Serializer.java index cacc95408..e8a7a5ad2 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson2Serializer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/exceptions/OAuth2ExceptionJackson2Serializer.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/DefaultJdbcListFactory.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/DefaultJdbcListFactory.java index e05362f77..37347befe 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/DefaultJdbcListFactory.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/DefaultJdbcListFactory.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/Jackson2JsonParser.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/Jackson2JsonParser.java index e755a9bdf..e8ca0adfb 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/Jackson2JsonParser.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/Jackson2JsonParser.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JacksonJsonParser.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JacksonJsonParser.java index de8605c17..a79502e52 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JacksonJsonParser.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JacksonJsonParser.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JdbcListFactory.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JdbcListFactory.java index 1a58e4ef9..fb7492b60 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JdbcListFactory.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JdbcListFactory.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JsonParser.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JsonParser.java index 386cefd72..c2905ca5c 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JsonParser.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JsonParser.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JsonParserFactory.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JsonParserFactory.java index 775a84379..2ec9aa2da 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JsonParserFactory.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/JsonParserFactory.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/OAuth2Utils.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/OAuth2Utils.java index 181333022..4c22f34b3 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/OAuth2Utils.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/OAuth2Utils.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/ProxyCreator.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/ProxyCreator.java index d99622c15..b842648c7 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/ProxyCreator.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/ProxyCreator.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java index 6e5d72985..a47b3608c 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/InMemoryClientDetailsServiceBuilder.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/InMemoryClientDetailsServiceBuilder.java index da19dde33..8c6f37c3a 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/InMemoryClientDetailsServiceBuilder.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/InMemoryClientDetailsServiceBuilder.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/JdbcClientDetailsServiceBuilder.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/JdbcClientDetailsServiceBuilder.java index a0e90f0fd..4a9d26a87 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/JdbcClientDetailsServiceBuilder.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/builders/JdbcClientDetailsServiceBuilder.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/configuration/ClientDetailsServiceConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/configuration/ClientDetailsServiceConfiguration.java index a7319d4d6..d7ad2e699 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/configuration/ClientDetailsServiceConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/configuration/ClientDetailsServiceConfiguration.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/configurers/ClientDetailsServiceConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/configurers/ClientDetailsServiceConfigurer.java index 398666a4d..e1ec33053 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/configurers/ClientDetailsServiceConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/configurers/ClientDetailsServiceConfigurer.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurer.java index 56d9d2876..f81dfc06c 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurer.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurerAdapter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurerAdapter.java index 147573b3e..4e8342ac1 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurerAdapter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerConfigurerAdapter.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 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 b2bc71674..aa32758a5 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 @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java index 231e1ec8b..cc7601d03 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableAuthorizationServer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableAuthorizationServer.java index bed46e8a3..1b4415269 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableAuthorizationServer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableAuthorizationServer.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableOAuth2Client.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableOAuth2Client.java index b19b31858..3bac72c3c 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableOAuth2Client.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableOAuth2Client.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableResourceServer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableResourceServer.java index efaa1ce48..52c532833 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableResourceServer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/EnableResourceServer.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/OAuth2ClientConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/OAuth2ClientConfiguration.java index a5815fd19..b79985202 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/OAuth2ClientConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/OAuth2ClientConfiguration.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java index da4779d1f..1833fab9f 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfiguration.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurer.java index b8f8d4d8f..d2a60f747 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurer.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurerAdapter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurerAdapter.java index 1ab229281..2cf23e139 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurerAdapter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurerAdapter.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 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 64ee6d76e..9bb56fa2a 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 @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java index 7c34c2e3d..80b5d9cd3 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java index 4f26247b6..7251e85da 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/ResourceServerSecurityConfigurer.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 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..61047191d 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 @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ClientBeanDefinitionParser.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ClientBeanDefinitionParser.java index 347fe7099..d8034750c 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ClientBeanDefinitionParser.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ClientBeanDefinitionParser.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ClientDetailsServiceBeanDefinitionParser.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ClientDetailsServiceBeanDefinitionParser.java index 5d9ec4af8..21fe53fe6 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ClientDetailsServiceBeanDefinitionParser.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ClientDetailsServiceBeanDefinitionParser.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ExpressionHandlerBeanDefinitionParser.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ExpressionHandlerBeanDefinitionParser.java index 6edfbedda..9b8f9e7f7 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ExpressionHandlerBeanDefinitionParser.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ExpressionHandlerBeanDefinitionParser.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/OAuth2ClientContextFactoryBean.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/OAuth2ClientContextFactoryBean.java index 3663b8c05..8b8d702c9 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/OAuth2ClientContextFactoryBean.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/OAuth2ClientContextFactoryBean.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/OAuth2SecurityNamespaceHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/OAuth2SecurityNamespaceHandler.java index f7632dcdb..01210ba8b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/OAuth2SecurityNamespaceHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/OAuth2SecurityNamespaceHandler.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ProviderBeanDefinitionParser.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ProviderBeanDefinitionParser.java index 1550d3845..364c16013 100755 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ProviderBeanDefinitionParser.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ProviderBeanDefinitionParser.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ResourceBeanDefinitionParser.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ResourceBeanDefinitionParser.java index d992c8aac..23c9fc62b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ResourceBeanDefinitionParser.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ResourceBeanDefinitionParser.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ResourceServerBeanDefinitionParser.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ResourceServerBeanDefinitionParser.java index 8301b596a..d7d261e1e 100755 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ResourceServerBeanDefinitionParser.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/ResourceServerBeanDefinitionParser.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/RestTemplateBeanDefinitionParser.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/RestTemplateBeanDefinitionParser.java index 41bb2a291..c4aeca280 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/RestTemplateBeanDefinitionParser.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/RestTemplateBeanDefinitionParser.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/WebExpressionHandlerBeanDefinitionParser.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/WebExpressionHandlerBeanDefinitionParser.java index 17b364f56..dff530bb3 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/WebExpressionHandlerBeanDefinitionParser.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/WebExpressionHandlerBeanDefinitionParser.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/FormOAuth2AccessTokenMessageConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/FormOAuth2AccessTokenMessageConverter.java index 6d27ee68c..f64ea48b0 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/FormOAuth2AccessTokenMessageConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/FormOAuth2AccessTokenMessageConverter.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/FormOAuth2ExceptionHttpMessageConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/FormOAuth2ExceptionHttpMessageConverter.java index d66a13880..d81a0ecf7 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/FormOAuth2ExceptionHttpMessageConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/FormOAuth2ExceptionHttpMessageConverter.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/jaxb/AbstractJaxbMessageConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/jaxb/AbstractJaxbMessageConverter.java index fb2666dac..5bc7c0191 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/jaxb/AbstractJaxbMessageConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/jaxb/AbstractJaxbMessageConverter.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2AccessToken.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2AccessToken.java index 1cbabd251..1df8ab8a0 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2AccessToken.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2AccessToken.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2AccessTokenMessageConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2AccessTokenMessageConverter.java index 07d898077..be71dafae 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2AccessTokenMessageConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2AccessTokenMessageConverter.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2Exception.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2Exception.java index ca4f3fdd2..75dfa02bf 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2Exception.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2Exception.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2ExceptionMessageConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2ExceptionMessageConverter.java index f78313852..72ae1cd6f 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2ExceptionMessageConverter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2ExceptionMessageConverter.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java index 7fd7f28d5..47e869cca 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/BaseRequest.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientAlreadyExistsException.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientAlreadyExistsException.java index eae256046..b7875f603 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientAlreadyExistsException.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientAlreadyExistsException.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientDetailsService.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientDetailsService.java index e08aa3540..f9e4166b9 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientDetailsService.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientDetailsService.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientRegistrationException.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientRegistrationException.java index aa32bf437..731577ee5 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientRegistrationException.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientRegistrationException.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientRegistrationService.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientRegistrationService.java index 4515539cf..a388c1b5b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientRegistrationService.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/ClientRegistrationService.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/CompositeTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/CompositeTokenGranter.java index 0148e580c..fab6fbf89 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/CompositeTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/CompositeTokenGranter.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultSecurityContextAccessor.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultSecurityContextAccessor.java index 0bab78276..46915dc66 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultSecurityContextAccessor.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/DefaultSecurityContextAccessor.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/NoSuchClientException.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/NoSuchClientException.java index ba68dee61..0083d4d51 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/NoSuchClientException.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/NoSuchClientException.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestFactory.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestFactory.java index d98418ab2..278b25b0c 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestFactory.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/OAuth2RequestFactory.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/SecurityContextAccessor.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/SecurityContextAccessor.java index 26862cc64..cd6522724 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/SecurityContextAccessor.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/SecurityContextAccessor.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenGranter.java index 51b34f3f4..fcd9ef1f8 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/TokenGranter.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/Approval.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/Approval.java index ffb7bd13a..27bbf8262 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/Approval.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/Approval.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStore.java index 2f6063310..88209e612 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStore.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java index a250c3283..33804a776 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/ApprovalStoreUserApprovalHandler.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/DefaultUserApprovalHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/DefaultUserApprovalHandler.java index 4233b6796..2344627f5 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/DefaultUserApprovalHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/DefaultUserApprovalHandler.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/InMemoryApprovalStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/InMemoryApprovalStore.java index ef7e69009..b70818196 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/InMemoryApprovalStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/InMemoryApprovalStore.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/JdbcApprovalStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/JdbcApprovalStore.java index bc3325afe..d200e22ee 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/JdbcApprovalStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/JdbcApprovalStore.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenApprovalStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenApprovalStore.java index cf1cc2e5f..e9f0ebb30 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenApprovalStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenApprovalStore.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandler.java index 4f995a4d1..ad69f0d10 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandler.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/BearerTokenExtractor.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/BearerTokenExtractor.java index bc2b76c29..4d224556d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/BearerTokenExtractor.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/BearerTokenExtractor.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationDetails.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationDetails.java index e2adb379b..d7a14ce8e 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationDetails.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationDetails.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationDetailsSource.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationDetailsSource.java index 4dad52034..880c374e0 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationDetailsSource.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationDetailsSource.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java index b02b6375b..f81470cda 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManager.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilter.java index 65278c005..cc27d8d26 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilter.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/TokenExtractor.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/TokenExtractor.java index 8d8506a67..d0864e6c4 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/TokenExtractor.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/TokenExtractor.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenEndpointFilter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenEndpointFilter.java index f032642eb..22d3d57b9 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenEndpointFilter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenEndpointFilter.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenGranter.java index 6583e255d..2ddfff51d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenGranter.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientDetailsUserDetailsService.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientDetailsUserDetailsService.java index d088c4f64..ed49f6845 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientDetailsUserDetailsService.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/ClientDetailsUserDetailsService.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/InMemoryClientDetailsService.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/InMemoryClientDetailsService.java index 763d9a0bb..bc519b5bb 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/InMemoryClientDetailsService.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/InMemoryClientDetailsService.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/JdbcClientDetailsService.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/JdbcClientDetailsService.java index f503b9d2d..d4a4ef465 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/JdbcClientDetailsService.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/client/JdbcClientDetailsService.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranter.java index c76ed6d5d..c7be47b54 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranter.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AbstractEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AbstractEndpoint.java index 3d7587f68..d50da6219 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AbstractEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AbstractEndpoint.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java index 43b5fc9ca..62966e7ac 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/CheckTokenEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/CheckTokenEndpoint.java index 75c978731..3e33b9da5 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/CheckTokenEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/CheckTokenEndpoint.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolver.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolver.java index 9f12b27f1..714bc191c 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolver.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolver.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpoint.java index ea5759aa1..17e953f2b 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpoint.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java index ed12a5b78..a3cebb978 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMapping.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java index 2fb806176..8472f7420 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpoint.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java index f01295986..1b7723d59 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/AbstractOAuth2SecurityExceptionHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/AbstractOAuth2SecurityExceptionHandler.java index 8d1c71b14..748a0af8a 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/AbstractOAuth2SecurityExceptionHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/AbstractOAuth2SecurityExceptionHandler.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/DefaultOAuth2ExceptionRenderer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/DefaultOAuth2ExceptionRenderer.java index 917ea5675..9fca8a568 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/DefaultOAuth2ExceptionRenderer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/DefaultOAuth2ExceptionRenderer.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/DefaultWebResponseExceptionTranslator.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/DefaultWebResponseExceptionTranslator.java index ee866ccae..a9327fb0f 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/DefaultWebResponseExceptionTranslator.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/DefaultWebResponseExceptionTranslator.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/OAuth2AccessDeniedHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/OAuth2AccessDeniedHandler.java index 404c0b957..f6867f2e0 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/OAuth2AccessDeniedHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/OAuth2AccessDeniedHandler.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/OAuth2AuthenticationEntryPoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/OAuth2AuthenticationEntryPoint.java index 02f1071be..ce3570d2f 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/OAuth2AuthenticationEntryPoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/OAuth2AuthenticationEntryPoint.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/OAuth2ExceptionRenderer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/OAuth2ExceptionRenderer.java index db17479a4..72b5bcd95 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/OAuth2ExceptionRenderer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/OAuth2ExceptionRenderer.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/WebResponseExceptionTranslator.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/WebResponseExceptionTranslator.java index 1a52e89b3..7b7bc664d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/WebResponseExceptionTranslator.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/error/WebResponseExceptionTranslator.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionParser.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionParser.java index 861411969..a1f897fce 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionParser.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionParser.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionUtils.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionUtils.java index 600847150..b516a9b27 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionUtils.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2ExpressionUtils.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethods.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethods.java index 3a56698cd..0c88491be 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethods.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethods.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2WebSecurityExpressionHandler.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2WebSecurityExpressionHandler.java index f4e458373..cea72d5a3 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2WebSecurityExpressionHandler.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/expression/OAuth2WebSecurityExpressionHandler.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java index 209bfc2a6..04ab21883 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenRequest.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenRequest.java index b7e967f74..66094ee27 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenRequest.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenRequest.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java index c996f1d30..34a502ed7 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranter.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/refresh/RefreshTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/refresh/RefreshTokenGranter.java index 55327ed86..c5081ade7 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/refresh/RefreshTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/refresh/RefreshTokenGranter.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/request/DefaultOAuth2RequestFactory.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/request/DefaultOAuth2RequestFactory.java index 17e9afcd3..8f81294ff 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/request/DefaultOAuth2RequestFactory.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/request/DefaultOAuth2RequestFactory.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AbstractTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AbstractTokenGranter.java index 5c13db131..bbe5b8a30 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AbstractTokenGranter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AbstractTokenGranter.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AuthenticationKeyGenerator.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AuthenticationKeyGenerator.java index 8e90b4c51..dcb80754e 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AuthenticationKeyGenerator.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AuthenticationKeyGenerator.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AuthorizationServerTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AuthorizationServerTokenServices.java index 13549ea70..26e3013d6 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AuthorizationServerTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/AuthorizationServerTokenServices.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/ConsumerTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/ConsumerTokenServices.java index 68dbb019a..1e3de255d 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/ConsumerTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/ConsumerTokenServices.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAuthenticationKeyGenerator.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAuthenticationKeyGenerator.java index ebc766846..3b98fd347 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAuthenticationKeyGenerator.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAuthenticationKeyGenerator.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java index fe3cb09a2..16f7a4914 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/TokenEnhancer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/TokenEnhancer.java index 6da146dfa..fd248d3ca 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/TokenEnhancer.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/TokenEnhancer.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/TokenEnhancerChain.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/TokenEnhancerChain.java index d5dc50c4f..f34cb76d5 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/TokenEnhancerChain.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/TokenEnhancerChain.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/DelegatingJwtClaimsSetVerifier.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/DelegatingJwtClaimsSetVerifier.java index 7182fc70f..3a8fab70c 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/DelegatingJwtClaimsSetVerifier.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/DelegatingJwtClaimsSetVerifier.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/IssuerClaimVerifier.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/IssuerClaimVerifier.java index 6f5936c8d..7203283d1 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/IssuerClaimVerifier.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/IssuerClaimVerifier.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtClaimsSetVerifier.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtClaimsSetVerifier.java index 20fe97d42..e686220cd 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtClaimsSetVerifier.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtClaimsSetVerifier.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStore.java index 489df3f24..4f8ddd9c9 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStore.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/JwtTokenStore.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/KeyStoreKeyFactory.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/KeyStoreKeyFactory.java index 8eda6ef2a..2f43064b6 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/KeyStoreKeyFactory.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/KeyStoreKeyFactory.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/EllipticCurveJwkDefinition.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/EllipticCurveJwkDefinition.java index 241d0526f..5b259ee79 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/EllipticCurveJwkDefinition.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/EllipticCurveJwkDefinition.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, 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 index b5a2b3338..931397668 100644 --- 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 @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, 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 index 95e37a217..eb19ba2e3 100644 --- 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 @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, 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 index c60d29866..94879e7a5 100644 --- 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 @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, 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 index 1d3211dfb..1e15ae2c8 100644 --- 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 @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, 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 index 2962e977a..d23683cf6 100644 --- 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 @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, 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 index 05c2285e9..92a8e0f9c 100644 --- 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 @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, 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 index 717876de9..3f2a6ebc3 100644 --- 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 @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, 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 index 3083c3b92..cc435012d 100644 --- 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 @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, 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 index 41655c7af..141cadb97 100644 --- 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 @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/vote/ScopeVoter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/vote/ScopeVoter.java index 6198ecce3..7328c5f67 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/vote/ScopeVoter.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/vote/ScopeVoter.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/AdhocTestSuite.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/AdhocTestSuite.java index 4838bace2..91b80aa64 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/AdhocTestSuite.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/AdhocTestSuite.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/DefaultOAuth2RequestAuthenticatorTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/DefaultOAuth2RequestAuthenticatorTests.java index eb0311ec1..6ca39d0ec 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/DefaultOAuth2RequestAuthenticatorTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/DefaultOAuth2RequestAuthenticatorTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/discovery/ProviderDiscoveryClientTest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/discovery/ProviderDiscoveryClientTest.java index c3c8603ab..4a8b89e54 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/discovery/ProviderDiscoveryClientTest.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/discovery/ProviderDiscoveryClientTest.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilterTests.java index 1b84f709d..b37e46f43 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/filter/OAuth2ClientAuthenticationProcessingFilterTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandlerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandlerTests.java index 4cd63d393..4f42c5dbf 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandlerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/http/OAuth2ErrorHandlerTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/AccessTokenProviderChainTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/AccessTokenProviderChainTests.java index 9c5847b96..5b9e08035 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/AccessTokenProviderChainTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/AccessTokenProviderChainTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/OAuth2AccessTokenSupportTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/OAuth2AccessTokenSupportTests.java index 783df39e0..93e63e43f 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/OAuth2AccessTokenSupportTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/OAuth2AccessTokenSupportTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProviderTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProviderTests.java index deeacc458..988cfe939 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProviderTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProviderTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProviderWithConversionTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProviderWithConversionTests.java index bf09ee61e..2c21fb3dc 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProviderWithConversionTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProviderWithConversionTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeResourceDetailsTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeResourceDetailsTests.java index 6bde16be9..2bec0d021 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeResourceDetailsTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeResourceDetailsTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/implicit/ImplicitAccessTokenProviderTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/implicit/ImplicitAccessTokenProviderTests.java index a23b32aae..207172a06 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/implicit/ImplicitAccessTokenProviderTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/implicit/ImplicitAccessTokenProviderTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/password/ResourceOwnerPasswordAccessTokenProviderTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/password/ResourceOwnerPasswordAccessTokenProviderTests.java index e6499ef6e..72df46099 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/password/ResourceOwnerPasswordAccessTokenProviderTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/client/token/grant/password/ResourceOwnerPasswordAccessTokenProviderTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/BaseOAuth2AccessTokenJacksonTest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/BaseOAuth2AccessTokenJacksonTest.java index 752a250fb..93a277c4f 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/BaseOAuth2AccessTokenJacksonTest.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/BaseOAuth2AccessTokenJacksonTest.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/DefaultOAuth2SerializationServiceTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/DefaultOAuth2SerializationServiceTests.java index da50f0930..9ab676c68 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/DefaultOAuth2SerializationServiceTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/DefaultOAuth2SerializationServiceTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/JsonSerializationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/JsonSerializationTests.java index 9c50fc5ce..15168df0b 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/JsonSerializationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/JsonSerializationTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson1DeserializerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson1DeserializerTests.java index 7d5ca3fc4..ff855f5d3 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson1DeserializerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson1DeserializerTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2DeserializerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2DeserializerTests.java index 937d895b3..fbd43158a 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2DeserializerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/OAuth2AccessTokenJackson2DeserializerTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/OAuth2ExceptionDeserializerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/OAuth2ExceptionDeserializerTests.java index 9e4f4c242..573e38fc7 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/OAuth2ExceptionDeserializerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/OAuth2ExceptionDeserializerTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/OAuth2ExceptionJackson2DeserializerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/OAuth2ExceptionJackson2DeserializerTests.java index bb872494e..3e14b01fa 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/OAuth2ExceptionJackson2DeserializerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/OAuth2ExceptionJackson2DeserializerTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/OAuth2ExceptionSerializerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/OAuth2ExceptionSerializerTests.java index bae47cba3..0e88364ea 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/OAuth2ExceptionSerializerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/common/exception/OAuth2ExceptionSerializerTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java index 75bc1a0d3..1e63ddd3c 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/AuthorizationServerConfigurationTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ClientConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ClientConfigurationTests.java index 3419b272e..a976c77ff 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ClientConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ClientConfigurationTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/Gh501EnableAuthorizationServerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/Gh501EnableAuthorizationServerTests.java index a4da13677..e3aa6a4ed 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/Gh501EnableAuthorizationServerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/Gh501EnableAuthorizationServerTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/Gh808EnableAuthorizationServerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/Gh808EnableAuthorizationServerTests.java index 7f0f6e239..c6383f903 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/Gh808EnableAuthorizationServerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/Gh808EnableAuthorizationServerTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java index fb826eec1..013252f2e 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/ResourceServerConfigurationTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 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 index d38593d54..83b798f89 100644 --- 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 @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/AuthorizationServerBeanDefinitionParserTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/AuthorizationServerBeanDefinitionParserTests.java index 25431ad8d..452458cec 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/AuthorizationServerBeanDefinitionParserTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/AuthorizationServerBeanDefinitionParserTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/AuthorizationServerClientCredentialsPasswordInvalidXmlTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/AuthorizationServerClientCredentialsPasswordInvalidXmlTests.java index 2dd1a329e..cd9fc3b44 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/AuthorizationServerClientCredentialsPasswordInvalidXmlTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/AuthorizationServerClientCredentialsPasswordInvalidXmlTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/AuthorizationServerClientCredentialsPasswordValidXmlTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/AuthorizationServerClientCredentialsPasswordValidXmlTests.java index fba5fa40c..6008f8d83 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/AuthorizationServerClientCredentialsPasswordValidXmlTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/AuthorizationServerClientCredentialsPasswordValidXmlTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/InvalidResourceBeanDefinitionParserTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/InvalidResourceBeanDefinitionParserTests.java index 460925c8f..323fc83da 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/InvalidResourceBeanDefinitionParserTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/InvalidResourceBeanDefinitionParserTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/ResourceServerBeanDefinitionParserTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/ResourceServerBeanDefinitionParserTests.java index e70a1030a..cfae87560 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/ResourceServerBeanDefinitionParserTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/xml/ResourceServerBeanDefinitionParserTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/BaseJaxbMessageConverterTest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/BaseJaxbMessageConverterTest.java index cf52a5bae..9342b5564 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/BaseJaxbMessageConverterTest.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/BaseJaxbMessageConverterTest.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2AccessTokenMessageConverterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2AccessTokenMessageConverterTests.java index 9e7b71e21..f2a8e17e2 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2AccessTokenMessageConverterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2AccessTokenMessageConverterTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2ExceptionMessageConverterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2ExceptionMessageConverterTests.java index 243cd92d9..bc146c02a 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2ExceptionMessageConverterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/http/converter/jaxb/JaxbOAuth2ExceptionMessageConverterTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/AuthorizationRequestTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/AuthorizationRequestTests.java index dd1363216..0f1ae75e3 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/AuthorizationRequestTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/AuthorizationRequestTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/OAuth2RequestTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/OAuth2RequestTests.java index 63b09d34e..1462e82af 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/OAuth2RequestTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/OAuth2RequestTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/AbstractTestApprovalStore.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/AbstractTestApprovalStore.java index 68124cb0f..034b25563 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/AbstractTestApprovalStore.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/AbstractTestApprovalStore.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/DefaultUserApprovalHandlerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/DefaultUserApprovalHandlerTests.java index 90bfbdf14..f1cb3c2bd 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/DefaultUserApprovalHandlerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/DefaultUserApprovalHandlerTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/InMemoryApprovalStoreTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/InMemoryApprovalStoreTests.java index af74be060..730dc47fd 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/InMemoryApprovalStoreTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/InMemoryApprovalStoreTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/JdbcApprovalStoreTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/JdbcApprovalStoreTests.java index a0b6eabeb..f202d9be1 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/JdbcApprovalStoreTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/JdbcApprovalStoreTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TokenApprovalStoreTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TokenApprovalStoreTests.java index d136b380d..81dce821a 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TokenApprovalStoreTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TokenApprovalStoreTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandlerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandlerTests.java index 70552058c..c52b0d9f6 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandlerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/approval/TokenStoreUserApprovalHandlerTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationDetailsTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationDetailsTests.java index 658c958ee..3674c6e45 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationDetailsTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationDetailsTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManagerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManagerTests.java index 4dc6bcdfc..9ba7107cc 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManagerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationManagerTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilterTests.java index d3b34b51f..e77bceea7 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilterTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/BaseClientDetailsTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/BaseClientDetailsTests.java index d80e9b773..6e215a8cf 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/BaseClientDetailsTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/BaseClientDetailsTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenEndpointFilterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenEndpointFilterTests.java index 36fe64ed8..cc3054244 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenEndpointFilterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/ClientCredentialsTokenEndpointFilterTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/ClientDetailsUserDetailsServiceTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/ClientDetailsUserDetailsServiceTests.java index ede103a46..aa4878bce 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/ClientDetailsUserDetailsServiceTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/client/ClientDetailsUserDetailsServiceTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranterTests.java index 429cefa0a..4d9a0eece 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/code/AuthorizationCodeTokenGranterTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java index e42a8c838..78b091b61 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/CheckTokenEndpointTest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/CheckTokenEndpointTest.java index 5c7dfd093..34618717d 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/CheckTokenEndpointTest.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/CheckTokenEndpointTest.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolverTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolverTests.java index b65967280..105f9fd5c 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolverTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/DefaultRedirectResolverTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/ExactMatchRedirectResolverTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/ExactMatchRedirectResolverTests.java index 1e387efa3..a7238112b 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/ExactMatchRedirectResolverTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/ExactMatchRedirectResolverTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMappingTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMappingTests.java index e3b89090c..8f83ebc19 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMappingTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/FrameworkEndpointHandlerMappingTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilterTests.java index 954b1b5d9..154dbb5b8 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointAuthenticationFilterTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointTests.java index ed98ad138..27f4c9dc7 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/TokenEndpointTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelApprovalEndpointTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelApprovalEndpointTests.java index b37b75306..f4c408dc7 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelApprovalEndpointTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelApprovalEndpointTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelErrorEndpointTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelErrorEndpointTests.java index 722ec5e0c..f97741a20 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelErrorEndpointTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelErrorEndpointTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/DefaultWebResponseExceptionTranslatorTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/DefaultWebResponseExceptionTranslatorTests.java index a761308fc..89ed1bc08 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/DefaultWebResponseExceptionTranslatorTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/DefaultWebResponseExceptionTranslatorTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/OAuth2AccessDeniedHandlerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/OAuth2AccessDeniedHandlerTests.java index b03239049..021e534b8 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/OAuth2AccessDeniedHandlerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/OAuth2AccessDeniedHandlerTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/OAuth2AuthenticationEntryPointTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/OAuth2AuthenticationEntryPointTests.java index cba776763..71d708188 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/OAuth2AuthenticationEntryPointTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/error/OAuth2AuthenticationEntryPointTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2MethodSecurityExpressionHandlerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2MethodSecurityExpressionHandlerTests.java index a5f6eddc2..5caf36640 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2MethodSecurityExpressionHandlerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2MethodSecurityExpressionHandlerTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethodsTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethodsTests.java index 87e400d6f..3a34da46b 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethodsTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2SecurityExpressionMethodsTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2WebSecurityExpressionHandlerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2WebSecurityExpressionHandlerTests.java index d866755e3..55acf56e7 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2WebSecurityExpressionHandlerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/expression/OAuth2WebSecurityExpressionHandlerTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/implicit/InMemoryImplicitGrantServiceTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/implicit/InMemoryImplicitGrantServiceTests.java index 15852a7aa..74490bcc8 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/implicit/InMemoryImplicitGrantServiceTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/implicit/InMemoryImplicitGrantServiceTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranterTests.java index 160669744..0e7cfcdee 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/password/ResourceOwnerPasswordTokenGranterTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/request/DefaultAuthorizationRequestFactoryTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/request/DefaultAuthorizationRequestFactoryTests.java index 61daf0520..1909b8b53 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/request/DefaultAuthorizationRequestFactoryTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/request/DefaultAuthorizationRequestFactoryTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/request/DefaultOAuth2RequestValidatorTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/request/DefaultOAuth2RequestValidatorTests.java index f485055d4..482009c07 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/request/DefaultOAuth2RequestValidatorTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/request/DefaultOAuth2RequestValidatorTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/test/OAuth2RequestTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/test/OAuth2RequestTests.java index 886efe82d..edfcd2bd9 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/test/OAuth2RequestTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/test/OAuth2RequestTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractDefaultTokenServicesTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractDefaultTokenServicesTests.java index f5c071437..61b356122 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractDefaultTokenServicesTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/AbstractDefaultTokenServicesTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverterTests.java index 75758d1c9..059a28e66 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverterTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultAuthenticationKeyGeneratorTest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultAuthenticationKeyGeneratorTest.java index 09ffcfbbc..d66cd1b59 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultAuthenticationKeyGeneratorTest.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultAuthenticationKeyGeneratorTest.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesAuthoritiesChangeTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesAuthoritiesChangeTests.java index 48edeb1c2..e650c5210 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesAuthoritiesChangeTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/DefaultTokenServicesAuthoritiesChangeTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/RemoteTokenServicesTest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/RemoteTokenServicesTest.java index 5d156fbeb..0a88a279e 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/RemoteTokenServicesTest.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/RemoteTokenServicesTest.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenServicesWithTokenEnhancerTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenServicesWithTokenEnhancerTests.java index 680653077..999bd3dea 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenServicesWithTokenEnhancerTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/TokenServicesWithTokenEnhancerTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/IssuerClaimVerifierTest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/IssuerClaimVerifierTest.java index 7e340be62..aef5706b8 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/IssuerClaimVerifierTest.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/IssuerClaimVerifierTest.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/TokenStoreBaseTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/TokenStoreBaseTests.java index 4872da3e7..15a21e0d0 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/TokenStoreBaseTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/TokenStoreBaseTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkDefinitionSourceITest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkDefinitionSourceITest.java index fa4daca28..e08ace32b 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkDefinitionSourceITest.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkDefinitionSourceITest.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, 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 index ae3f2d36c..e0556619c 100644 --- 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 @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, 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 index a6ad3d2b2..66660b65f 100644 --- 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 @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, 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 index df1620318..6591efa25 100644 --- 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 @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkTokenStoreITest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkTokenStoreITest.java index 082edecaf..370fb7a28 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkTokenStoreITest.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkTokenStoreITest.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, 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 index e1b2cdbf8..1817582fd 100644 --- 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 @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, 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 index 8cf44e8e4..c67c54c3e 100644 --- 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 @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, 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 index 890729a87..f15422876 100644 --- 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 @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, 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 index 5aab5d5e9..4b8b97c30 100644 --- 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 @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, 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 index 72ca34d3c..96712e452 100644 --- 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 @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/redis/RedisTokenStoreMockTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/redis/RedisTokenStoreMockTests.java index 149643aa0..738f0f1c2 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/redis/RedisTokenStoreMockTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/redis/RedisTokenStoreMockTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/ScopeVoterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/ScopeVoterTests.java index e54397109..a1b522122 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/ScopeVoterTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/vote/ScopeVoterTests.java @@ -5,7 +5,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/tests/annotation/approval/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/approval/src/test/java/demo/AuthorizationCodeProviderTests.java index 2f3ddf7e7..2ecdcf333 100755 --- a/tests/annotation/approval/src/test/java/demo/AuthorizationCodeProviderTests.java +++ b/tests/annotation/approval/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/approval/src/test/java/demo/ProtectedResourceTests.java b/tests/annotation/approval/src/test/java/demo/ProtectedResourceTests.java index 302b30f96..be5dc3b8b 100644 --- a/tests/annotation/approval/src/test/java/demo/ProtectedResourceTests.java +++ b/tests/annotation/approval/src/test/java/demo/ProtectedResourceTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/client/src/test/java/client/CombinedApplication.java b/tests/annotation/client/src/test/java/client/CombinedApplication.java index 107fd1a5b..1a6887f42 100644 --- a/tests/annotation/client/src/test/java/client/CombinedApplication.java +++ b/tests/annotation/client/src/test/java/client/CombinedApplication.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java b/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java index 8420fc311..5343e0805 100755 --- a/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/common/src/main/java/sparklr/common/AbstractEmptyAuthorizationCodeProviderTests.java b/tests/annotation/common/src/main/java/sparklr/common/AbstractEmptyAuthorizationCodeProviderTests.java index 1459a9817..bd8a04a59 100644 --- a/tests/annotation/common/src/main/java/sparklr/common/AbstractEmptyAuthorizationCodeProviderTests.java +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractEmptyAuthorizationCodeProviderTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 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 023566427..c5129b5c4 100644 --- a/tests/annotation/common/src/main/java/sparklr/common/AbstractIntegrationTests.java +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractIntegrationTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/common/src/main/java/sparklr/common/AbstractProtectedResourceTests.java b/tests/annotation/common/src/main/java/sparklr/common/AbstractProtectedResourceTests.java index 7e37f24d9..dd29cc9e1 100644 --- a/tests/annotation/common/src/main/java/sparklr/common/AbstractProtectedResourceTests.java +++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractProtectedResourceTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/custom-grant/src/main/java/demo/CustomTokenGranter.java b/tests/annotation/custom-grant/src/main/java/demo/CustomTokenGranter.java index cab7c0417..c61aa898c 100644 --- a/tests/annotation/custom-grant/src/main/java/demo/CustomTokenGranter.java +++ b/tests/annotation/custom-grant/src/main/java/demo/CustomTokenGranter.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/custom-grant/src/test/java/demo/AdHocTests.java b/tests/annotation/custom-grant/src/test/java/demo/AdHocTests.java index ee518795d..b82adb62d 100644 --- a/tests/annotation/custom-grant/src/test/java/demo/AdHocTests.java +++ b/tests/annotation/custom-grant/src/test/java/demo/AdHocTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 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 34cdef81b..f56a2522a 100755 --- a/tests/annotation/custom-grant/src/test/java/demo/AuthorizationCodeProviderTests.java +++ b/tests/annotation/custom-grant/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 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 302b30f96..be5dc3b8b 100644 --- a/tests/annotation/custom-grant/src/test/java/demo/ProtectedResourceTests.java +++ b/tests/annotation/custom-grant/src/test/java/demo/ProtectedResourceTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/form/src/test/java/demo/AdHocTests.java b/tests/annotation/form/src/test/java/demo/AdHocTests.java index e5bfeca13..fa3a8f21c 100644 --- a/tests/annotation/form/src/test/java/demo/AdHocTests.java +++ b/tests/annotation/form/src/test/java/demo/AdHocTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/form/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/form/src/test/java/demo/AuthorizationCodeProviderTests.java index 2ef50fde6..529bacd06 100755 --- a/tests/annotation/form/src/test/java/demo/AuthorizationCodeProviderTests.java +++ b/tests/annotation/form/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/form/src/test/java/demo/ProtectedResourceTests.java b/tests/annotation/form/src/test/java/demo/ProtectedResourceTests.java index 302b30f96..be5dc3b8b 100644 --- a/tests/annotation/form/src/test/java/demo/ProtectedResourceTests.java +++ b/tests/annotation/form/src/test/java/demo/ProtectedResourceTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/jaxb/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/jaxb/src/test/java/demo/AuthorizationCodeProviderTests.java index 0333fa789..083436112 100755 --- a/tests/annotation/jaxb/src/test/java/demo/AuthorizationCodeProviderTests.java +++ b/tests/annotation/jaxb/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/jaxb/src/test/java/demo/Converters.java b/tests/annotation/jaxb/src/test/java/demo/Converters.java index e3d61a8f2..2b7542431 100644 --- a/tests/annotation/jaxb/src/test/java/demo/Converters.java +++ b/tests/annotation/jaxb/src/test/java/demo/Converters.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/jaxb/src/test/java/demo/ProtectedResourceTests.java b/tests/annotation/jaxb/src/test/java/demo/ProtectedResourceTests.java index 0a539c5f4..e23874743 100644 --- a/tests/annotation/jaxb/src/test/java/demo/ProtectedResourceTests.java +++ b/tests/annotation/jaxb/src/test/java/demo/ProtectedResourceTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/jdbc/src/test/java/demo/AdHocTests.java b/tests/annotation/jdbc/src/test/java/demo/AdHocTests.java index a7d0087ca..7e52aa7b5 100644 --- a/tests/annotation/jdbc/src/test/java/demo/AdHocTests.java +++ b/tests/annotation/jdbc/src/test/java/demo/AdHocTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/jdbc/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/jdbc/src/test/java/demo/AuthorizationCodeProviderTests.java index 27a0a1c4e..19d4492b7 100755 --- a/tests/annotation/jdbc/src/test/java/demo/AuthorizationCodeProviderTests.java +++ b/tests/annotation/jdbc/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/jdbc/src/test/java/demo/ProtectedResourceTests.java b/tests/annotation/jdbc/src/test/java/demo/ProtectedResourceTests.java index 0e2acc8d9..2eb25a2cf 100644 --- a/tests/annotation/jdbc/src/test/java/demo/ProtectedResourceTests.java +++ b/tests/annotation/jdbc/src/test/java/demo/ProtectedResourceTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/jpa/src/test/java/demo/AdHocTests.java b/tests/annotation/jpa/src/test/java/demo/AdHocTests.java index f3f947369..7ba4feea0 100644 --- a/tests/annotation/jpa/src/test/java/demo/AdHocTests.java +++ b/tests/annotation/jpa/src/test/java/demo/AdHocTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/jpa/src/test/java/demo/AuthorizationCodeProviderCookieTests.java b/tests/annotation/jpa/src/test/java/demo/AuthorizationCodeProviderCookieTests.java index 26d88d46a..b7394bfc2 100644 --- a/tests/annotation/jpa/src/test/java/demo/AuthorizationCodeProviderCookieTests.java +++ b/tests/annotation/jpa/src/test/java/demo/AuthorizationCodeProviderCookieTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/jpa/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/jpa/src/test/java/demo/AuthorizationCodeProviderTests.java index 34cdef81b..f56a2522a 100755 --- a/tests/annotation/jpa/src/test/java/demo/AuthorizationCodeProviderTests.java +++ b/tests/annotation/jpa/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/jpa/src/test/java/demo/ProtectedResourceTests.java b/tests/annotation/jpa/src/test/java/demo/ProtectedResourceTests.java index 302b30f96..be5dc3b8b 100644 --- a/tests/annotation/jpa/src/test/java/demo/ProtectedResourceTests.java +++ b/tests/annotation/jpa/src/test/java/demo/ProtectedResourceTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/jwt/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/jwt/src/test/java/demo/AuthorizationCodeProviderTests.java index 2ef50fde6..529bacd06 100755 --- a/tests/annotation/jwt/src/test/java/demo/AuthorizationCodeProviderTests.java +++ b/tests/annotation/jwt/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/jwt/src/test/java/demo/ProtectedResourceTests.java b/tests/annotation/jwt/src/test/java/demo/ProtectedResourceTests.java index 302b30f96..be5dc3b8b 100644 --- a/tests/annotation/jwt/src/test/java/demo/ProtectedResourceTests.java +++ b/tests/annotation/jwt/src/test/java/demo/ProtectedResourceTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/mappings/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/mappings/src/test/java/demo/AuthorizationCodeProviderTests.java index 5fba9cfe0..2fc343dc5 100755 --- a/tests/annotation/mappings/src/test/java/demo/AuthorizationCodeProviderTests.java +++ b/tests/annotation/mappings/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/mappings/src/test/java/demo/ProtectedResourceTests.java b/tests/annotation/mappings/src/test/java/demo/ProtectedResourceTests.java index 4f5e357cc..f7ef5432c 100644 --- a/tests/annotation/mappings/src/test/java/demo/ProtectedResourceTests.java +++ b/tests/annotation/mappings/src/test/java/demo/ProtectedResourceTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/multi/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/multi/src/test/java/demo/AuthorizationCodeProviderTests.java index 2ef50fde6..529bacd06 100755 --- a/tests/annotation/multi/src/test/java/demo/AuthorizationCodeProviderTests.java +++ b/tests/annotation/multi/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/multi/src/test/java/demo/ProtectedResourceTests.java b/tests/annotation/multi/src/test/java/demo/ProtectedResourceTests.java index bf1dfd35f..89190be29 100644 --- a/tests/annotation/multi/src/test/java/demo/ProtectedResourceTests.java +++ b/tests/annotation/multi/src/test/java/demo/ProtectedResourceTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/resource/src/test/java/demo/ProtectedResourceTests.java b/tests/annotation/resource/src/test/java/demo/ProtectedResourceTests.java index 302b30f96..be5dc3b8b 100644 --- a/tests/annotation/resource/src/test/java/demo/ProtectedResourceTests.java +++ b/tests/annotation/resource/src/test/java/demo/ProtectedResourceTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/ssl/src/test/java/demo/AuthorizationCodeProviderCookieTests.java b/tests/annotation/ssl/src/test/java/demo/AuthorizationCodeProviderCookieTests.java index 7b614e004..c3cc8b30a 100644 --- a/tests/annotation/ssl/src/test/java/demo/AuthorizationCodeProviderCookieTests.java +++ b/tests/annotation/ssl/src/test/java/demo/AuthorizationCodeProviderCookieTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/ssl/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/ssl/src/test/java/demo/AuthorizationCodeProviderTests.java index 49a38d4ab..2a14e7d5e 100755 --- a/tests/annotation/ssl/src/test/java/demo/AuthorizationCodeProviderTests.java +++ b/tests/annotation/ssl/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/ssl/src/test/java/demo/ProtectedResourceTests.java b/tests/annotation/ssl/src/test/java/demo/ProtectedResourceTests.java index c752cbe12..e43d004e3 100644 --- a/tests/annotation/ssl/src/test/java/demo/ProtectedResourceTests.java +++ b/tests/annotation/ssl/src/test/java/demo/ProtectedResourceTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/vanilla/src/test/java/demo/AdHocTests.java b/tests/annotation/vanilla/src/test/java/demo/AdHocTests.java index f3f947369..7ba4feea0 100644 --- a/tests/annotation/vanilla/src/test/java/demo/AdHocTests.java +++ b/tests/annotation/vanilla/src/test/java/demo/AdHocTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderCookieTests.java b/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderCookieTests.java index 26d88d46a..b7394bfc2 100644 --- a/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderCookieTests.java +++ b/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderCookieTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java index 34cdef81b..f56a2522a 100755 --- a/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java +++ b/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/annotation/vanilla/src/test/java/demo/ProtectedResourceTests.java b/tests/annotation/vanilla/src/test/java/demo/ProtectedResourceTests.java index 302b30f96..be5dc3b8b 100644 --- a/tests/annotation/vanilla/src/test/java/demo/ProtectedResourceTests.java +++ b/tests/annotation/vanilla/src/test/java/demo/ProtectedResourceTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/xml/approval/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/xml/approval/src/test/java/demo/AuthorizationCodeProviderTests.java index f336430f4..97f5ae1f5 100755 --- a/tests/xml/approval/src/test/java/demo/AuthorizationCodeProviderTests.java +++ b/tests/xml/approval/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/xml/approval/src/test/java/demo/ProtectedResourceTests.java b/tests/xml/approval/src/test/java/demo/ProtectedResourceTests.java index c752cbe12..e43d004e3 100644 --- a/tests/xml/approval/src/test/java/demo/ProtectedResourceTests.java +++ b/tests/xml/approval/src/test/java/demo/ProtectedResourceTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/xml/client/src/test/java/client/CombinedApplication.java b/tests/xml/client/src/test/java/client/CombinedApplication.java index 9c612f760..294565e1f 100644 --- a/tests/xml/client/src/test/java/client/CombinedApplication.java +++ b/tests/xml/client/src/test/java/client/CombinedApplication.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/xml/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java b/tests/xml/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java index 548978c72..8769d6ee2 100755 --- a/tests/xml/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java +++ b/tests/xml/common/src/main/java/sparklr/common/AbstractAuthorizationCodeProviderTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/xml/common/src/main/java/sparklr/common/AbstractIntegrationTests.java b/tests/xml/common/src/main/java/sparklr/common/AbstractIntegrationTests.java index ac2f12db7..b44539912 100644 --- a/tests/xml/common/src/main/java/sparklr/common/AbstractIntegrationTests.java +++ b/tests/xml/common/src/main/java/sparklr/common/AbstractIntegrationTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/xml/common/src/main/java/sparklr/common/AbstractProtectedResourceTests.java b/tests/xml/common/src/main/java/sparklr/common/AbstractProtectedResourceTests.java index e267f4430..2e49192df 100644 --- a/tests/xml/common/src/main/java/sparklr/common/AbstractProtectedResourceTests.java +++ b/tests/xml/common/src/main/java/sparklr/common/AbstractProtectedResourceTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/xml/form/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/xml/form/src/test/java/demo/AuthorizationCodeProviderTests.java index 632098bf1..8ae483f92 100755 --- a/tests/xml/form/src/test/java/demo/AuthorizationCodeProviderTests.java +++ b/tests/xml/form/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/xml/form/src/test/java/demo/ProtectedResourceTests.java b/tests/xml/form/src/test/java/demo/ProtectedResourceTests.java index c752cbe12..e43d004e3 100644 --- a/tests/xml/form/src/test/java/demo/ProtectedResourceTests.java +++ b/tests/xml/form/src/test/java/demo/ProtectedResourceTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/xml/jdbc/src/test/java/demo/AdHocTests.java b/tests/xml/jdbc/src/test/java/demo/AdHocTests.java index a7d0087ca..7e52aa7b5 100644 --- a/tests/xml/jdbc/src/test/java/demo/AdHocTests.java +++ b/tests/xml/jdbc/src/test/java/demo/AdHocTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/xml/jdbc/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/xml/jdbc/src/test/java/demo/AuthorizationCodeProviderTests.java index 32cb5606d..8f1993b56 100755 --- a/tests/xml/jdbc/src/test/java/demo/AuthorizationCodeProviderTests.java +++ b/tests/xml/jdbc/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/xml/jdbc/src/test/java/demo/ProtectedResourceTests.java b/tests/xml/jdbc/src/test/java/demo/ProtectedResourceTests.java index c752cbe12..e43d004e3 100644 --- a/tests/xml/jdbc/src/test/java/demo/ProtectedResourceTests.java +++ b/tests/xml/jdbc/src/test/java/demo/ProtectedResourceTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/xml/jwt/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/xml/jwt/src/test/java/demo/AuthorizationCodeProviderTests.java index 632098bf1..8ae483f92 100755 --- a/tests/xml/jwt/src/test/java/demo/AuthorizationCodeProviderTests.java +++ b/tests/xml/jwt/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/xml/jwt/src/test/java/demo/ProtectedResourceTests.java b/tests/xml/jwt/src/test/java/demo/ProtectedResourceTests.java index c752cbe12..e43d004e3 100644 --- a/tests/xml/jwt/src/test/java/demo/ProtectedResourceTests.java +++ b/tests/xml/jwt/src/test/java/demo/ProtectedResourceTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/xml/mappings/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/xml/mappings/src/test/java/demo/AuthorizationCodeProviderTests.java index 36e02d25f..34075877a 100755 --- a/tests/xml/mappings/src/test/java/demo/AuthorizationCodeProviderTests.java +++ b/tests/xml/mappings/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/xml/mappings/src/test/java/demo/ProtectedResourceTests.java b/tests/xml/mappings/src/test/java/demo/ProtectedResourceTests.java index 743d9158b..fad494589 100644 --- a/tests/xml/mappings/src/test/java/demo/ProtectedResourceTests.java +++ b/tests/xml/mappings/src/test/java/demo/ProtectedResourceTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/xml/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/xml/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java index 632098bf1..8ae483f92 100755 --- a/tests/xml/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java +++ b/tests/xml/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/tests/xml/vanilla/src/test/java/demo/ProtectedResourceTests.java b/tests/xml/vanilla/src/test/java/demo/ProtectedResourceTests.java index c752cbe12..e43d004e3 100644 --- a/tests/xml/vanilla/src/test/java/demo/ProtectedResourceTests.java +++ b/tests/xml/vanilla/src/test/java/demo/ProtectedResourceTests.java @@ -4,7 +4,7 @@ * 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 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the From 835919b2b89e5b62ac8f1b3b288be85c72947349 Mon Sep 17 00:00:00 2001 From: Spring Operator Date: Tue, 19 Mar 2019 22:50:21 -0500 Subject: [PATCH 684/831] URL Cleanup This commit updates URLs to prefer the https protocol. Redirects are not followed to avoid accidentally expanding intentionally shortened URLs (i.e. if using a URL shortener). These URLs were unable to be fixed. Please review them to see if they can be manually resolved. * http://junit.sourceforge.net/javadoc/ (200) with 1 occurrences could not be migrated: ([https](https://junit.sourceforge.net/javadoc/) result AnnotatedConnectException). * http://oauth.gmodules.com/gadgets/oauthcallback (200) with 1 occurrences could not be migrated: ([https](https://oauth.gmodules.com/gadgets/oauthcallback) result SSLHandshakeException). * http://somewhere.com (403) with 8 occurrences could not be migrated: ([https](https://somewhere.com) result ConnectTimeoutException). These URLs were fixed, but the https status was not OK. However, the https status was the same as the http request or http redirected to an https URL, so they were migrated. Your review is recommended. * http://picasaweb.google.com/stoicflame/HawaiiBeach (404) with 8 occurrences migrated to: /109190140453754943808/HawaiiBeach?gsessionid=SApB7ihRtbUnXPMYlCx4O2myoa0iD-E9 ([https](https://picasaweb.google.com/stoicflame/HawaiiBeach) result IllegalArgumentException). * http://picasaweb.google.com/stoicflame/TheHeatonHome?authkey=aEgk9ZZkNoY (404) with 2 occurrences migrated to: /109190140453754943808/TheHeatonHome?authkey=aEgk9ZZkNoY&gsessionid=1ct-z3jGjEC8oXohyjDG7FXpwPazlGXo ([https](https://picasaweb.google.com/stoicflame/TheHeatonHome?authkey=aEgk9ZZkNoY) result IllegalArgumentException). * http://picasaweb.google.com/stoicflame (404) with 2 occurrences migrated to: /109190140453754943808?gsessionid=clr7rfNSarvEV15l85q1khMqSj8oDwqx ([https](https://picasaweb.google.com/stoicflame) result IllegalArgumentException). * http://mycompany.com (302) with 1 occurrences migrated to: https://secure.mycompany.com ([https](https://mycompany.com) result ConnectTimeoutException). * http://tools.ietf.org/html/draft-ietf-oauth-v2 (301) with 1 occurrences migrated to: https://tools.ietf.org/html/draft-ietf-oauth-v2 ([https](https://tools.ietf.org/html/draft-ietf-oauth-v2) result ReadTimeoutException). * http://anywhere (UnknownHostException) with 5 occurrences migrated to: https://anywhere ([https](https://anywhere) result UnknownHostException). * http://anywhere?key=value (UnknownHostException) with 5 occurrences migrated to: https://anywhere?key=value ([https](https://anywhere?key=value) result UnknownHostException). * http://schemas.google.com/g/2005 (UnknownHostException) with 22 occurrences migrated to: https://schemas.google.com/g/2005 ([https](https://schemas.google.com/g/2005) result UnknownHostException). * http://schemas.google.com/photos/2007 (UnknownHostException) with 33 occurrences migrated to: https://schemas.google.com/photos/2007 ([https](https://schemas.google.com/photos/2007) result UnknownHostException). * http://schemas.google.com/photos/exif/2007 (UnknownHostException) with 1 occurrences migrated to: https://schemas.google.com/photos/exif/2007 ([https](https://schemas.google.com/photos/exif/2007) result UnknownHostException). * http://a9.com/-/spec/opensearchrss/1.0/ (301) with 1 occurrences migrated to: https://a9.com/-/spec/opensearchrss/1.0/ ([https](https://a9.com/-/spec/opensearchrss/1.0/) result 404). * http://code.google.com/apis/accounts/docs/OAuth_ref.html-- (404) with 1 occurrences migrated to: https://code.google.com/apis/accounts/docs/OAuth_ref.html-- ([https](https://code.google.com/apis/accounts/docs/OAuth_ref.html--) result 404). * http://gadget-doc-examples.googlecode.com/svn/trunk/images/new.gif (404) with 1 occurrences migrated to: https://gadget-doc-examples.googlecode.com/svn/trunk/images/new.gif ([https](https://gadget-doc-examples.googlecode.com/svn/trunk/images/new.gif) result 404). * http://gadget-doc-examples.googlecode.com/svn/trunk/opensocial-gadgets/popup.js (404) with 1 occurrences migrated to: https://gadget-doc-examples.googlecode.com/svn/trunk/opensocial-gadgets/popup.js ([https](https://gadget-doc-examples.googlecode.com/svn/trunk/opensocial-gadgets/popup.js) result 404). * http://picasaweb.google.com/lh/photo/1_pPyhAE3IXRe5cb4AagZQ (404) with 1 occurrences migrated to: https://picasaweb.google.com/lh/photo/1_pPyhAE3IXRe5cb4AagZQ ([https](https://picasaweb.google.com/lh/photo/1_pPyhAE3IXRe5cb4AagZQ) result 404). * http://picasaweb.google.com/lh/photo/EpbAByEAotaQekZSdVgZQg (404) with 1 occurrences migrated to: https://picasaweb.google.com/lh/photo/EpbAByEAotaQekZSdVgZQg ([https](https://picasaweb.google.com/lh/photo/EpbAByEAotaQekZSdVgZQg) result 404). * http://picasaweb.google.com/lh/photo/Ioko4Z0cbBD1Dh1B7YubrA (404) with 1 occurrences migrated to: https://picasaweb.google.com/lh/photo/Ioko4Z0cbBD1Dh1B7YubrA ([https](https://picasaweb.google.com/lh/photo/Ioko4Z0cbBD1Dh1B7YubrA) result 404). * http://picasaweb.google.com/lh/photo/U7NcEx5i97pGfjxIhqlYow (404) with 1 occurrences migrated to: https://picasaweb.google.com/lh/photo/U7NcEx5i97pGfjxIhqlYow ([https](https://picasaweb.google.com/lh/photo/U7NcEx5i97pGfjxIhqlYow) result 404). * http://picasaweb.google.com/lh/photo/XpvsZB33FPqLHa527Nc2hQ (404) with 1 occurrences migrated to: https://picasaweb.google.com/lh/photo/XpvsZB33FPqLHa527Nc2hQ ([https](https://picasaweb.google.com/lh/photo/XpvsZB33FPqLHa527Nc2hQ) result 404). * http://picasaweb.google.com/lh/photo/_rJ23c0-ev-GEsuqajvYWg (404) with 1 occurrences migrated to: https://picasaweb.google.com/lh/photo/_rJ23c0-ev-GEsuqajvYWg ([https](https://picasaweb.google.com/lh/photo/_rJ23c0-ev-GEsuqajvYWg) result 404). * http://picasaweb.google.com/lh/photo/b02iZRlngmObhiG-xVwmng (404) with 1 occurrences migrated to: https://picasaweb.google.com/lh/photo/b02iZRlngmObhiG-xVwmng ([https](https://picasaweb.google.com/lh/photo/b02iZRlngmObhiG-xVwmng) result 404). * http://picasaweb.google.com/lh/photo/cyqNMsCJd4KMl9d8thlF9A (404) with 1 occurrences migrated to: https://picasaweb.google.com/lh/photo/cyqNMsCJd4KMl9d8thlF9A ([https](https://picasaweb.google.com/lh/photo/cyqNMsCJd4KMl9d8thlF9A) result 404). * http://picasaweb.google.com/lh/photo/emw168uzsXbckWn6o1NOGw (404) with 1 occurrences migrated to: https://picasaweb.google.com/lh/photo/emw168uzsXbckWn6o1NOGw ([https](https://picasaweb.google.com/lh/photo/emw168uzsXbckWn6o1NOGw) result 404). * http://picasaweb.google.com/lh/photo/zU1hicDzC1JGgsnl6CMtQw (404) with 1 occurrences migrated to: https://picasaweb.google.com/lh/photo/zU1hicDzC1JGgsnl6CMtQw ([https](https://picasaweb.google.com/lh/photo/zU1hicDzC1JGgsnl6CMtQw) result 404). * http://picasaweb.google.com/lh/reportAbuse?uname=stoicflame&aid=5155181789245632497&iid=5155184692643524754 (404) with 1 occurrences migrated to: https://picasaweb.google.com/lh/reportAbuse?uname=stoicflame&aid=5155181789245632497&iid=5155184692643524754 ([https](https://picasaweb.google.com/lh/reportAbuse?uname=stoicflame&aid=5155181789245632497&iid=5155184692643524754) result 404). * http://picasaweb.google.com/lh/reportAbuse?uname=stoicflame&aid=5155181789245632497&iid=5155184993291235490 (404) with 1 occurrences migrated to: https://picasaweb.google.com/lh/reportAbuse?uname=stoicflame&aid=5155181789245632497&iid=5155184993291235490 ([https](https://picasaweb.google.com/lh/reportAbuse?uname=stoicflame&aid=5155181789245632497&iid=5155184993291235490) result 404). * http://picasaweb.google.com/lh/reportAbuse?uname=stoicflame&aid=5155181789245632497&iid=5155185272464109746 (404) with 1 occurrences migrated to: https://picasaweb.google.com/lh/reportAbuse?uname=stoicflame&aid=5155181789245632497&iid=5155185272464109746 ([https](https://picasaweb.google.com/lh/reportAbuse?uname=stoicflame&aid=5155181789245632497&iid=5155185272464109746) result 404). * http://picasaweb.google.com/lh/reportAbuse?uname=stoicflame&aid=5155181789245632497&iid=5155185633241362626 (404) with 1 occurrences migrated to: https://picasaweb.google.com/lh/reportAbuse?uname=stoicflame&aid=5155181789245632497&iid=5155185633241362626 ([https](https://picasaweb.google.com/lh/reportAbuse?uname=stoicflame&aid=5155181789245632497&iid=5155185633241362626) result 404). * http://picasaweb.google.com/lh/reportAbuse?uname=stoicflame&aid=5155181789245632497&iid=5155186024083386578 (404) with 1 occurrences migrated to: https://picasaweb.google.com/lh/reportAbuse?uname=stoicflame&aid=5155181789245632497&iid=5155186024083386578 ([https](https://picasaweb.google.com/lh/reportAbuse?uname=stoicflame&aid=5155181789245632497&iid=5155186024083386578) result 404). * http://picasaweb.google.com/lh/reportAbuse?uname=stoicflame&aid=5155181789245632497&iid=5155186290371358946 (404) with 1 occurrences migrated to: https://picasaweb.google.com/lh/reportAbuse?uname=stoicflame&aid=5155181789245632497&iid=5155186290371358946 ([https](https://picasaweb.google.com/lh/reportAbuse?uname=stoicflame&aid=5155181789245632497&iid=5155186290371358946) result 404). * http://picasaweb.google.com/lh/reportAbuse?uname=stoicflame&aid=5155181789245632497&iid=5155186560954298610 (404) with 1 occurrences migrated to: https://picasaweb.google.com/lh/reportAbuse?uname=stoicflame&aid=5155181789245632497&iid=5155186560954298610 ([https](https://picasaweb.google.com/lh/reportAbuse?uname=stoicflame&aid=5155181789245632497&iid=5155186560954298610) result 404). * http://picasaweb.google.com/lh/reportAbuse?uname=stoicflame&aid=5155181789245632497&iid=5155186870191943938 (404) with 1 occurrences migrated to: https://picasaweb.google.com/lh/reportAbuse?uname=stoicflame&aid=5155181789245632497&iid=5155186870191943938 ([https](https://picasaweb.google.com/lh/reportAbuse?uname=stoicflame&aid=5155181789245632497&iid=5155186870191943938) result 404). * http://picasaweb.google.com/lh/reportAbuse?uname=stoicflame&aid=5381874767712259297&iid=5398207118777306258 (404) with 1 occurrences migrated to: https://picasaweb.google.com/lh/reportAbuse?uname=stoicflame&aid=5381874767712259297&iid=5398207118777306258 ([https](https://picasaweb.google.com/lh/reportAbuse?uname=stoicflame&aid=5381874767712259297&iid=5398207118777306258) result 404). * http://picasaweb.google.com/lh/reportAbuse?uname=stoicflame&aid=5381874767712259297&iid=5416573875289209458 (404) with 1 occurrences migrated to: https://picasaweb.google.com/lh/reportAbuse?uname=stoicflame&aid=5381874767712259297&iid=5416573875289209458 ([https](https://picasaweb.google.com/lh/reportAbuse?uname=stoicflame&aid=5381874767712259297&iid=5416573875289209458) result 404). These URLs were switched to an https URL with a 2xx status. While the status was successful, your review is still recommended. * http://static.springframework.org/spring-security/site/ (301) with 1 occurrences migrated to: https://docs.spring.io/spring-security/site/ ([https](https://static.springframework.org/spring-security/site/) result 200). * http://maven.apache.org/xsd/maven-4.0.0.xsd with 25 occurrences migrated to: https://maven.apache.org/xsd/maven-4.0.0.xsd ([https](https://maven.apache.org/xsd/maven-4.0.0.xsd) result 200). * http://myhost.com with 1 occurrences migrated to: https://myhost.com ([https](https://myhost.com) result 200). * http://oauth.net/ with 1 occurrences migrated to: https://oauth.net/ ([https](https://oauth.net/) result 200). * http://www.springframework.org/schema/beans/spring-beans-3.0.xsd with 12 occurrences migrated to: https://www.springframework.org/schema/beans/spring-beans-3.0.xsd ([https](https://www.springframework.org/schema/beans/spring-beans-3.0.xsd) result 200). * http://www.springframework.org/schema/beans/spring-beans-3.1.xsd with 1 occurrences migrated to: https://www.springframework.org/schema/beans/spring-beans-3.1.xsd ([https](https://www.springframework.org/schema/beans/spring-beans-3.1.xsd) result 200). * http://www.springframework.org/schema/beans/spring-beans.xsd with 15 occurrences migrated to: https://www.springframework.org/schema/beans/spring-beans.xsd ([https](https://www.springframework.org/schema/beans/spring-beans.xsd) result 200). * http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd with 1 occurrences migrated to: https://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd ([https](https://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd) result 200). * http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd with 1 occurrences migrated to: https://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd ([https](https://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd) result 200). * http://www.springframework.org/schema/mvc/spring-mvc.xsd with 2 occurrences migrated to: https://www.springframework.org/schema/mvc/spring-mvc.xsd ([https](https://www.springframework.org/schema/mvc/spring-mvc.xsd) result 200). * http://www.springframework.org/schema/security/spring-security-oauth-1.0.xsd with 5 occurrences migrated to: https://www.springframework.org/schema/security/spring-security-oauth-1.0.xsd ([https](https://www.springframework.org/schema/security/spring-security-oauth-1.0.xsd) result 200). * http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd with 2 occurrences migrated to: https://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd ([https](https://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd) result 200). * http://www.springframework.org/schema/security/spring-security-oauth2.xsd with 19 occurrences migrated to: https://www.springframework.org/schema/security/spring-security-oauth2.xsd ([https](https://www.springframework.org/schema/security/spring-security-oauth2.xsd) result 200). * http://www.springframework.org/schema/security/spring-security.xsd with 9 occurrences migrated to: https://www.springframework.org/schema/security/spring-security.xsd ([https](https://www.springframework.org/schema/security/spring-security.xsd) result 200). * http://anywhere.com with 2 occurrences migrated to: https://anywhere.com ([https](https://anywhere.com) result 301). * http://maven.apache.org/maven-v4_0_0.xsd with 10 occurrences migrated to: https://maven.apache.org/maven-v4_0_0.xsd ([https](https://maven.apache.org/maven-v4_0_0.xsd) result 301). * http://springframework.org/ with 1 occurrences migrated to: https://springframework.org/ ([https](https://springframework.org/) result 301). * http://java.sun.com/dtd/web-app_2_3.dtd with 2 occurrences migrated to: https://java.sun.com/dtd/web-app_2_3.dtd ([https](https://java.sun.com/dtd/web-app_2_3.dtd) result 302). * http://java.sun.com/j2ee/1.4/docs/api with 1 occurrences migrated to: https://java.sun.com/j2ee/1.4/docs/api ([https](https://java.sun.com/j2ee/1.4/docs/api) result 302). * http://java.sun.com/j2se/1.5.0/docs/api with 1 occurrences migrated to: https://java.sun.com/j2se/1.5.0/docs/api ([https](https://java.sun.com/j2se/1.5.0/docs/api) result 302). * http://picasaweb.google.com/ with 1 occurrences migrated to: https://picasaweb.google.com/ ([https](https://picasaweb.google.com/) result 302). * http://picasaweb.google.com/s/c/bin/slideshow.swf?host=picasaweb.google.com&RGB=0x000000&feed=https%3A%2F%2Fpicasaweb.google.com%2Fdata%2Ffeed%2Fapi%2Fuser%2Fstoicflame%3Falt%3Drss with 1 occurrences migrated to: https://picasaweb.google.com/s/c/bin/slideshow.swf?host=picasaweb.google.com&RGB=0x000000&feed=https%3A%2F%2Fpicasaweb.google.com%2Fdata%2Ffeed%2Fapi%2Fuser%2Fstoicflame%3Falt%3Drss ([https](https://picasaweb.google.com/s/c/bin/slideshow.swf?host=picasaweb.google.com&RGB=0x000000&feed=https%3A%2F%2Fpicasaweb.google.com%2Fdata%2Ffeed%2Fapi%2Fuser%2Fstoicflame%3Falt%3Drss) result 302). * http://search.yahoo.com/mrss/ with 1 occurrences migrated to: https://search.yahoo.com/mrss/ ([https](https://search.yahoo.com/mrss/) result 302). These URLs were intentionally ignored. * http://appengine.google.com/ns/1.0 with 1 occurrences * http://localhost:8080/oauth/authorize with 1 occurrences * http://localhost:8080/oauth/token with 1 occurrences * http://localhost:8080/sparklr/oauth/access_token with 1 occurrences * http://localhost:8080/sparklr/oauth/confirm_access with 1 occurrences * http://localhost:8080/sparklr/oauth/request_token with 1 occurrences * http://maven.apache.org/POM/4.0.0 with 70 occurrences * http://www.springframework.org/schema/beans with 56 occurrences * http://www.springframework.org/schema/mvc with 8 occurrences * http://www.springframework.org/schema/security with 18 occurrences * http://www.springframework.org/schema/security/oauth with 10 occurrences * http://www.springframework.org/schema/security/oauth2 with 53 occurrences * http://www.w3.org/2001/XMLSchema-instance with 63 occurrences * http://www.w3.org/2005/Atom with 1 occurrences Fixes gh-1628 --- pom.xml | 6 +- samples/oauth/sparklr/pom.xml | 2 +- .../webapp/WEB-INF/applicationContext.xml | 6 +- .../main/webapp/WEB-INF/spring-servlet.xml | 4 +- .../sparklr/src/main/webapp/WEB-INF/web.xml | 2 +- .../src/main/webapp/sparklr_gadget.xml | 4 +- samples/oauth/tonr/pom.xml | 2 +- .../main/resources/example_picasa_feed.xml | 138 +++++++++--------- .../webapp/WEB-INF/applicationContext.xml | 8 +- .../main/webapp/WEB-INF/spring-servlet.xml | 4 +- .../tonr/src/main/webapp/WEB-INF/web.xml | 2 +- samples/oauth2/sparklr/pom.xml | 2 +- samples/oauth2/tonr/pom.xml | 2 +- samples/pom.xml | 2 +- spring-security-jwt/pom.xml | 2 +- spring-security-oauth/pom.xml | 2 +- ...erverBeanDefinitionParserTests-context.xml | 6 +- ...rviceBeanDefinitionParserTests-context.xml | 6 +- ...FilterChainInitializationTests-context.xml | 6 +- spring-security-oauth2/pom.xml | 2 +- ...rviceBeanDefinitionParserTests-context.xml | 6 +- ...ourceBeanDefinitionParserTests-context.xml | 10 +- ...ion-server-check-token-custom-endpoint.xml | 4 +- .../xml/authorization-server-check-token.xml | 4 +- ...er-client-credentials-password-invalid.xml | 8 +- ...rver-client-credentials-password-valid.xml | 8 +- .../xml/authorization-server-custom-grant.xml | 4 +- .../xml/authorization-server-disable.xml | 6 +- .../xml/authorization-server-extras.xml | 4 +- .../xml/authorization-server-invalid.xml | 4 +- .../config/xml/authorization-server-types.xml | 6 +- .../xml/authorization-server-vanilla.xml | 4 +- .../resource-server-authmanager-context.xml | 4 +- .../config/xml/resource-server-context.xml | 4 +- src/site/site.xml | 8 +- tests/annotation/approval/pom.xml | 2 +- tests/annotation/client/pom.xml | 2 +- tests/annotation/common/pom.xml | 2 +- .../annotation/custom-authentication/pom.xml | 2 +- tests/annotation/custom-grant/pom.xml | 2 +- tests/annotation/form/pom.xml | 2 +- tests/annotation/jaxb/pom.xml | 2 +- tests/annotation/jdbc/pom.xml | 2 +- tests/annotation/jpa/pom.xml | 2 +- tests/annotation/jwt/pom.xml | 2 +- tests/annotation/mappings/pom.xml | 2 +- tests/annotation/multi/pom.xml | 2 +- tests/annotation/pom.xml | 2 +- tests/annotation/resource/pom.xml | 2 +- tests/annotation/ssl/pom.xml | 2 +- tests/annotation/vanilla/pom.xml | 2 +- tests/pom.xml | 2 +- tests/xml/approval/pom.xml | 2 +- .../approval/src/main/resources/context.xml | 8 +- tests/xml/client/pom.xml | 2 +- .../xml/client/src/main/resources/context.xml | 4 +- tests/xml/common/pom.xml | 2 +- tests/xml/form/pom.xml | 2 +- tests/xml/form/src/main/resources/context.xml | 8 +- tests/xml/jdbc/pom.xml | 2 +- tests/xml/jdbc/src/main/resources/context.xml | 4 +- tests/xml/jwt/pom.xml | 2 +- tests/xml/jwt/src/main/resources/context.xml | 8 +- tests/xml/mappings/pom.xml | 2 +- .../mappings/src/main/resources/context.xml | 8 +- tests/xml/pom.xml | 2 +- tests/xml/vanilla/pom.xml | 2 +- .../vanilla/src/main/resources/context.xml | 8 +- 68 files changed, 196 insertions(+), 196 deletions(-) diff --git a/pom.xml b/pom.xml index 55efc4792..5caebe627 100644 --- a/pom.xml +++ b/pom.xml @@ -1,4 +1,4 @@ - + 4.0.0 org.springframework.security.oauth spring-security-oauth-parent @@ -472,8 +472,8 @@ true true - http://java.sun.com/j2ee/1.4/docs/api - http://java.sun.com/j2se/1.5.0/docs/api + https://java.sun.com/j2ee/1.4/docs/api + https://java.sun.com/j2se/1.5.0/docs/api https://jakarta.apache.org/commons/collections/apidocs-COLLECTIONS_3_0/ https://jakarta.apache.org/commons/dbcp/apidocs/ https://jakarta.apache.org/commons/fileupload/apidocs/ diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml index ae43f43aa..eb075133a 100644 --- a/samples/oauth/sparklr/pom.xml +++ b/samples/oauth/sparklr/pom.xml @@ -1,4 +1,4 @@ - + 4.0.0 diff --git a/samples/oauth/sparklr/src/main/webapp/WEB-INF/applicationContext.xml b/samples/oauth/sparklr/src/main/webapp/WEB-INF/applicationContext.xml index c23317603..f33670c75 100644 --- a/samples/oauth/sparklr/src/main/webapp/WEB-INF/applicationContext.xml +++ b/samples/oauth/sparklr/src/main/webapp/WEB-INF/applicationContext.xml @@ -4,9 +4,9 @@ xmlns:beans="http://www.springframework.org/schema/beans" xmlns:oauth="http://www.springframework.org/schema/security/oauth" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://www.springframework.org/schema/beans%20http://www.springframework.org/schema/beans/spring-beans.xsd-%20%20%20%20%20%20%20%20%20%20%20%20%20%20http://www.springframework.org/schema/security%20http://www.springframework.org/schema/security/spring-security.xsd-%20%20%20%20%20%20%20%20%20%20%20%20%20%20http://www.springframework.org/schema/security/oauth%20http://www.springframework.org/schema/security/spring-security-oauth-1.0.xsd"> + xsi:schemaLocation="http://www.springframework.org/schema/beans%20https://www.springframework.org/schema/beans/spring-beans.xsd+%20%20%20%20%20%20%20%20%20%20%20%20%20%20http://www.springframework.org/schema/security%20https://www.springframework.org/schema/security/spring-security.xsd+%20%20%20%20%20%20%20%20%20%20%20%20%20%20http://www.springframework.org/schema/security/oauth%20https://www.springframework.org/schema/security/spring-security-oauth-1.0.xsd"> diff --git a/samples/oauth/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml b/samples/oauth/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml index 65bcd5a97..b364e2142 100644 --- a/samples/oauth/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml +++ b/samples/oauth/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml @@ -2,8 +2,8 @@ + xsi:schemaLocation="http://www.springframework.org/schema/mvc%20https://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd+http://www.springframework.org/schema/beans%20https://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> diff --git a/samples/oauth/sparklr/src/main/webapp/WEB-INF/web.xml b/samples/oauth/sparklr/src/main/webapp/WEB-INF/web.xml index 8492917b3..31390bf58 100644 --- a/samples/oauth/sparklr/src/main/webapp/WEB-INF/web.xml +++ b/samples/oauth/sparklr/src/main/webapp/WEB-INF/web.xml @@ -2,7 +2,7 @@ + "https://java.sun.com/dtd/web-app_2_3.dtd"> diff --git a/samples/oauth/sparklr/src/main/webapp/sparklr_gadget.xml b/samples/oauth/sparklr/src/main/webapp/sparklr_gadget.xml index 3f914b85a..e05842d8b 100644 --- a/samples/oauth/sparklr/src/main/webapp/sparklr_gadget.xml +++ b/samples/oauth/sparklr/src/main/webapp/sparklr_gadget.xml @@ -15,7 +15,7 @@ - +