Author: sergeyb Date: Tue Jun 4 12:06:01 2013 New Revision: 1489396 URL: http://svn.apache.org/r1489396 Log: Merged revisions 1489394 via svnmerge from https://svn.apache.org/repos/asf/cxf/branches/2.7.x-fixes
................ r1489394 | sergeyb | 2013-06-04 13:01:55 +0100 (Tue, 04 Jun 2013) | 9 lines Merged revisions 1489392 via svnmerge from https://svn.apache.org/repos/asf/cxf/trunk ........ r1489392 | sergeyb | 2013-06-04 12:57:46 +0100 (Tue, 04 Jun 2013) | 1 line [CXF-5055] OOB Response support, Client scopes registration ........ ................ Added: cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OOBAuthorizationResponse.java - copied unchanged from r1489394, cxf/branches/2.7.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OOBAuthorizationResponse.java cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OAuthContextProvider.java - copied unchanged from r1489394, cxf/branches/2.7.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OAuthContextProvider.java cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OOBResponseDeliverer.java - copied unchanged from r1489394, cxf/branches/2.7.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OOBResponseDeliverer.java cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/MessageDigestGenerator.java - copied unchanged from r1489394, cxf/branches/2.7.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/MessageDigestGenerator.java cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtilsTest.java - copied unchanged from r1489394, cxf/branches/2.7.x-fixes/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtilsTest.java Removed: cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/MD5SequenceGenerator.java Modified: cxf/branches/2.6.x-fixes/ (props changed) cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/AbstractGrantHandler.java cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/refresh/RefreshTokenGrantHandler.java cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AccessTokenService.java cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AuthorizationCodeGrantService.java cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/ImplicitGrantService.java cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java Propchange: cxf/branches/2.6.x-fixes/ ------------------------------------------------------------------------------ Merged /cxf/branches/2.7.x-fixes:r1489394 Merged /cxf/trunk:r1489392 Propchange: cxf/branches/2.6.x-fixes/ ------------------------------------------------------------------------------ Binary property 'svnmerge-integrated' - no diff available. Modified: cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java?rev=1489396&r1=1489395&r2=1489396&view=diff ============================================================================== --- cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java (original) +++ cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java Tue Jun 4 12:06:01 2013 @@ -39,6 +39,8 @@ public class Client { private boolean isConfidential; private List<String> allowedGrantTypes = new LinkedList<String>(); + private List<String> registeredScopes = new LinkedList<String>(); + private List<Property> properties = new LinkedList<Property>(); private UserSubject subject; @@ -230,4 +232,25 @@ public class Client { public void setProperties(List<Property> properties) { this.properties = properties; } + + /** + * Get the list of registered scopes + * @return scopes + */ + public List<String> getRegisteredScopes() { + return registeredScopes; + } + + /** + * Set the list of registered scopes. + * Registering the scopes will allow the clients not to include the scopes + * and delegate to the runtime to enforce that the current request scopes are + * a subset of the pre-registered scopes. + * + * Client Registration service is expected to reject unknown scopes. + * @param registeredScopes the scopes + */ + public void setRegisteredScopes(List<String> registeredScopes) { + this.registeredScopes = registeredScopes; + } } Modified: cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/AbstractGrantHandler.java URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/AbstractGrantHandler.java?rev=1489396&r1=1489395&r2=1489396&view=diff ============================================================================== --- cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/AbstractGrantHandler.java (original) +++ cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/AbstractGrantHandler.java Tue Jun 4 12:06:01 2013 @@ -24,6 +24,7 @@ import java.util.List; import org.apache.cxf.rs.security.oauth2.common.AccessTokenRegistration; import org.apache.cxf.rs.security.oauth2.common.Client; +import org.apache.cxf.rs.security.oauth2.common.OAuthError; import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken; import org.apache.cxf.rs.security.oauth2.common.UserSubject; import org.apache.cxf.rs.security.oauth2.provider.AccessTokenGrantHandler; @@ -40,7 +41,8 @@ public abstract class AbstractGrantHandl private String supportedGrant; private OAuthDataProvider dataProvider; - private boolean isClientConfidential; + private boolean isClientConfidential; + private boolean partialMatchScopeValidation; protected AbstractGrantHandler(String grant, boolean isClientConfidential) { supportedGrant = grant; this.isClientConfidential = isClientConfidential; @@ -66,6 +68,10 @@ public abstract class AbstractGrantHandl protected ServerAccessToken doCreateAccessToken(Client client, UserSubject subject, List<String> requestedScope) { + if (!OAuthUtils.validateScopes(requestedScope, client.getRegisteredScopes(), + partialMatchScopeValidation)) { + throw new OAuthServiceException(new OAuthError(OAuthConstants.INVALID_SCOPE)); + } // Check if a pre-authorized token available ServerAccessToken token = dataProvider.getPreauthorizedToken( client, requestedScope, subject, supportedGrant); @@ -82,4 +88,8 @@ public abstract class AbstractGrantHandl return dataProvider.createAccessToken(reg); } + + public void setPartialMatchScopeValidation(boolean partialMatchScopeValidation) { + this.partialMatchScopeValidation = partialMatchScopeValidation; + } } Modified: cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/refresh/RefreshTokenGrantHandler.java URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/refresh/RefreshTokenGrantHandler.java?rev=1489396&r1=1489395&r2=1489396&view=diff ============================================================================== --- cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/refresh/RefreshTokenGrantHandler.java (original) +++ cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/refresh/RefreshTokenGrantHandler.java Tue Jun 4 12:06:01 2013 @@ -34,6 +34,7 @@ import org.apache.cxf.rs.security.oauth2 public class RefreshTokenGrantHandler implements AccessTokenGrantHandler { private OAuthDataProvider dataProvider; + private boolean partialMatchScopeValidation; public void setDataProvider(OAuthDataProvider dataProvider) { this.dataProvider = dataProvider; @@ -49,8 +50,14 @@ public class RefreshTokenGrantHandler im throw new OAuthServiceException(OAuthConstants.UNAUTHORIZED_CLIENT); } String refreshToken = params.getFirst(OAuthConstants.REFRESH_TOKEN); - List<String> requestedScopes = OAuthUtils.parseScope(params.getFirst(OAuthConstants.SCOPE)); + List<String> requestedScopes = OAuthUtils.getRequestedScopes(client, + params.getFirst(OAuthConstants.SCOPE), + partialMatchScopeValidation); return dataProvider.refreshAccessToken(client, refreshToken, requestedScopes); } + + public void setPartialMatchScopeValidation(boolean partialMatchScopeValidation) { + this.partialMatchScopeValidation = partialMatchScopeValidation; + } } Modified: cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AccessTokenService.java URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AccessTokenService.java?rev=1489396&r1=1489395&r2=1489396&view=diff ============================================================================== --- cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AccessTokenService.java (original) +++ cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AccessTokenService.java Tue Jun 4 12:06:01 2013 @@ -53,6 +53,7 @@ import org.apache.cxf.rs.security.oauth2 public class AccessTokenService extends AbstractOAuthService { private List<AccessTokenGrantHandler> grantHandlers = Collections.emptyList(); private boolean writeCustomErrors; + private boolean canSupportPublicClients; public void setWriteCustomErrors(boolean write) { writeCustomErrors = write; @@ -170,7 +171,15 @@ public class AccessTokenService extends // Get the Client and check the id and secret private Client getAndValidateClient(String clientId, String clientSecret) { Client client = getClient(clientId); - if (clientSecret == null || !client.getClientId().equals(clientId) + if (canSupportPublicClients + && !client.isConfidential() + && client.getClientSecret() == null + && client.getRedirectUris().isEmpty() + && clientSecret == null) { + return client; + } + if (clientSecret == null || client.getClientSecret() == null + || !client.getClientId().equals(clientId) || !client.getClientSecret().equals(clientSecret)) { throw new WebApplicationException(401); } @@ -210,4 +219,8 @@ public class AccessTokenService extends protected Response createErrorResponseFromBean(OAuthError errorBean) { return Response.status(400).entity(errorBean).build(); } + + public void setCanSupportPublicClients(boolean support) { + this.canSupportPublicClients = support; + } } Modified: cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AuthorizationCodeGrantService.java URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AuthorizationCodeGrantService.java?rev=1489396&r1=1489395&r2=1489396&view=diff ============================================================================== --- cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AuthorizationCodeGrantService.java (original) +++ cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AuthorizationCodeGrantService.java Tue Jun 4 12:06:01 2013 @@ -22,17 +22,20 @@ package org.apache.cxf.rs.security.oauth import java.util.List; import javax.ws.rs.Path; +import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriBuilder; import org.apache.cxf.rs.security.oauth2.common.Client; +import org.apache.cxf.rs.security.oauth2.common.OOBAuthorizationResponse; import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken; import org.apache.cxf.rs.security.oauth2.common.UserSubject; import org.apache.cxf.rs.security.oauth2.grants.code.AuthorizationCodeDataProvider; import org.apache.cxf.rs.security.oauth2.grants.code.AuthorizationCodeRegistration; import org.apache.cxf.rs.security.oauth2.grants.code.ServerAuthorizationCodeGrant; import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException; +import org.apache.cxf.rs.security.oauth2.provider.OOBResponseDeliverer; import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants; @@ -45,8 +48,11 @@ import org.apache.cxf.rs.security.oauth2 */ @Path("/authorize") public class AuthorizationCodeGrantService extends RedirectionBasedGrantService { + private boolean canSupportPublicClients; + private OOBResponseDeliverer oobDeliverer; + public AuthorizationCodeGrantService() { - super(OAuthConstants.CODE_RESPONSE_TYPE, OAuthConstants.AUTHORIZATION_CODE_GRANT, true); + super(OAuthConstants.CODE_RESPONSE_TYPE, OAuthConstants.AUTHORIZATION_CODE_GRANT); } protected Response createGrant(MultivaluedMap<String, String> params, @@ -73,18 +79,39 @@ public class AuthorizationCodeGrantServi return createErrorResponse(params, redirectUri, OAuthConstants.ACCESS_DENIED); } - // return the code by appending it as a query parameter to the redirect URI - UriBuilder ub = getRedirectUriBuilder(params.getFirst(OAuthConstants.STATE), redirectUri); - ub.queryParam(OAuthConstants.AUTHORIZATION_CODE_VALUE, grant.getCode()); - return Response.seeOther(ub.build()).build(); + if (!client.isConfidential()) { + OOBAuthorizationResponse oobResponse = new OOBAuthorizationResponse(); + oobResponse.setClientId(client.getClientId()); + oobResponse.setAuthorizationCode(grant.getCode()); + oobResponse.setUserId(userSubject.getLogin()); + oobResponse.setLifetime(grant.getLifetime()); + return deliverOOBResponse(oobResponse); + } else { + // return the code by appending it as a query parameter to the redirect URI + UriBuilder ub = getRedirectUriBuilder(params.getFirst(OAuthConstants.STATE), redirectUri); + ub.queryParam(OAuthConstants.AUTHORIZATION_CODE_VALUE, grant.getCode()); + return Response.seeOther(ub.build()).build(); + } + } + + protected Response deliverOOBResponse(OOBAuthorizationResponse response) { + if (oobDeliverer != null) { + return oobDeliverer.deliver(response); + } else { + return Response.ok(response).type(MediaType.TEXT_HTML).build(); + } } protected Response createErrorResponse(MultivaluedMap<String, String> params, String redirectUri, String error) { - UriBuilder ub = getRedirectUriBuilder(params.getFirst(OAuthConstants.STATE), redirectUri); - ub.queryParam(OAuthConstants.ERROR_KEY, error); - return Response.seeOther(ub.build()).build(); + if (redirectUri == null) { + return Response.status(401).entity(error).build(); + } else { + UriBuilder ub = getRedirectUriBuilder(params.getFirst(OAuthConstants.STATE), redirectUri); + ub.queryParam(OAuthConstants.ERROR_KEY, error); + return Response.seeOther(ub.build()).build(); + } } protected UriBuilder getRedirectUriBuilder(String state, String redirectUri) { @@ -94,6 +121,23 @@ public class AuthorizationCodeGrantServi } return ub; } + + @Override + protected boolean canSupportPublicClient(Client c) { + return canSupportPublicClients && !c.isConfidential() + && c.getClientSecret() == null && c.getRedirectUris().isEmpty(); + } + + @Override + protected boolean canRedirectUriBeEmpty(Client c) { + return canSupportPublicClient(c); + } + + public void setCanSupportPublicClients(boolean support) { + this.canSupportPublicClients = support; + } + + } Modified: cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/ImplicitGrantService.java URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/ImplicitGrantService.java?rev=1489396&r1=1489395&r2=1489396&view=diff ============================================================================== --- cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/ImplicitGrantService.java (original) +++ cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/ImplicitGrantService.java Tue Jun 4 12:06:01 2013 @@ -46,8 +46,11 @@ import org.apache.cxf.rs.security.oauth2 */ @Path("/authorize-implicit") public class ImplicitGrantService extends RedirectionBasedGrantService { + // For a client to validate that this client is a targeted recipient. + private boolean reportClientId; + public ImplicitGrantService() { - super(OAuthConstants.TOKEN_RESPONSE_TYPE, OAuthConstants.IMPLICIT_GRANT, false); + super(OAuthConstants.TOKEN_RESPONSE_TYPE, OAuthConstants.IMPLICIT_GRANT); } protected Response createGrant(MultivaluedMap<String, String> params, @@ -81,6 +84,10 @@ public class ImplicitGrantService extend sb.append(OAuthConstants.ACCESS_TOKEN).append("=").append(token.getTokenKey()); sb.append("&") .append(OAuthConstants.ACCESS_TOKEN_TYPE).append("=").append(token.getTokenType()); + if (reportClientId) { + sb.append("&") + .append(OAuthConstants.CLIENT_ID).append("=").append(client.getClientId()); + } if (isWriteOptionalParameters()) { sb.append("&").append(OAuthConstants.ACCESS_TOKEN_EXPIRES_IN) .append("=").append(token.getExpiresIn()); @@ -118,6 +125,20 @@ public class ImplicitGrantService extend } return sb; } + + public void setReportClientId(boolean reportClientId) { + this.reportClientId = reportClientId; + } + + @Override + protected boolean canSupportPublicClient(Client c) { + return true; + } + + @Override + protected boolean canRedirectUriBeEmpty(Client c) { + return false; + } } Modified: cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java?rev=1489396&r1=1489395&r2=1489396&view=diff ============================================================================== --- cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java (original) +++ cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java Tue Jun 4 12:06:01 2013 @@ -56,17 +56,15 @@ import org.apache.cxf.security.SecurityC public abstract class RedirectionBasedGrantService extends AbstractOAuthService { private String supportedResponseType; private String supportedGrantType; - private boolean isClientConfidential; + private boolean partialMatchScopeValidation; private SessionAuthenticityTokenProvider sessionAuthenticityTokenProvider; private SubjectCreator subjectCreator; private ResourceOwnerNameProvider resourceOwnerNameProvider; protected RedirectionBasedGrantService(String supportedResponseType, - String supportedGrantType, - boolean isConfidential) { + String supportedGrantType) { this.supportedResponseType = supportedResponseType; this.supportedGrantType = supportedGrantType; - this.isClientConfidential = isConfidential; } /** @@ -118,7 +116,7 @@ public abstract class RedirectionBasedGr String redirectUri = validateRedirectUri(client, params.getFirst(OAuthConstants.REDIRECT_URI)); // Enforce the client confidentiality requirements - if (!OAuthUtils.isGrantSupportedForClient(client, isClientConfidential, supportedGrantType)) { + if (!OAuthUtils.isGrantSupportedForClient(client, !canSupportPublicClient(client), supportedGrantType)) { return createErrorResponse(params, redirectUri, OAuthConstants.UNAUTHORIZED_CLIENT); } @@ -127,9 +125,17 @@ public abstract class RedirectionBasedGr if (responseType == null || !responseType.equals(supportedResponseType)) { return createErrorResponse(params, redirectUri, OAuthConstants.UNSUPPORTED_RESPONSE_TYPE); } - // Get the requested scopes - List<String> requestedScope = OAuthUtils.parseScope(params.getFirst(OAuthConstants.SCOPE)); + List<String> requestedScope = null; + + try { + requestedScope = OAuthUtils.getRequestedScopes(client, + params.getFirst(OAuthConstants.SCOPE), + partialMatchScopeValidation); + } catch (OAuthServiceException ex) { + return createErrorResponse(params, redirectUri, OAuthConstants.INVALID_SCOPE); + } + // Create a UserSubject representing the end user UserSubject userSubject = createUserSubject(sc); @@ -234,10 +240,11 @@ public abstract class RedirectionBasedGr approvedScope.add(rScope); } } - if (!requestedScope.containsAll(approvedScope)) { + if (!requestedScope.containsAll(approvedScope) + || !OAuthUtils.validateScopes(requestedScope, client.getRegisteredScopes(), + partialMatchScopeValidation)) { return createErrorResponse(params, redirectUri, OAuthConstants.INVALID_SCOPE); } - UserSubject userSubject = createUserSubject(securityContext); // Request a new grant @@ -308,8 +315,8 @@ public abstract class RedirectionBasedGr } else if (uris.size() == 1) { redirectUri = uris.get(0); } - if (redirectUri == null) { - reportInvalidRequestError("Client Redirect Uri is invalid"); + if (redirectUri == null && !canRedirectUriBeEmpty(client)) { + reportInvalidRequestError("Client Redirect Uri is invalid"); } return redirectUri; } @@ -348,4 +355,12 @@ public abstract class RedirectionBasedGr public void setResourceOwnerNameProvider(ResourceOwnerNameProvider resourceOwnerNameProvider) { this.resourceOwnerNameProvider = resourceOwnerNameProvider; } + + public void setPartialMatchScopeValidation(boolean partialMatchScopeValidation) { + this.partialMatchScopeValidation = partialMatchScopeValidation; + } + + protected abstract boolean canSupportPublicClient(Client c); + + protected abstract boolean canRedirectUriBeEmpty(Client c); } Modified: cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java?rev=1489396&r1=1489395&r2=1489396&view=diff ============================================================================== --- cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java (original) +++ cxf/branches/2.6.x-fixes/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java Tue Jun 4 12:06:01 2013 @@ -100,9 +100,17 @@ public final class OAuthUtils { } public static String generateRandomTokenKey() throws OAuthServiceException { + return generateRandomTokenKey(null); + } + + public static String generateRandomTokenKey(String digestAlgo) throws OAuthServiceException { try { byte[] bytes = UUID.randomUUID().toString().getBytes("UTF-8"); - return new MD5SequenceGenerator().generate(bytes); + MessageDigestGenerator gen = new MessageDigestGenerator(); + if (digestAlgo != null) { + gen.setAlgorithm(digestAlgo); + } + return gen.generate(bytes); } catch (Exception ex) { throw new OAuthServiceException(OAuthConstants.SERVER_ERROR, ex); } @@ -131,4 +139,42 @@ public final class OAuthUtils { return false; } + public static List<String> getRequestedScopes(Client client, String scopeParameter, + boolean partialMatchScopeValidation) { + List<String> requestScopes = parseScope(scopeParameter); + List<String> registeredScopes = client.getRegisteredScopes(); + if (requestScopes.isEmpty()) { + requestScopes.addAll(registeredScopes); + return requestScopes; + } + if (!validateScopes(requestScopes, registeredScopes, partialMatchScopeValidation)) { + throw new OAuthServiceException("Unexpected scope"); + } + return requestScopes; + } + + public static boolean validateScopes(List<String> requestScopes, List<String> registeredScopes, + boolean partialMatchScopeValidation) { + if (!registeredScopes.isEmpty()) { + // if it is a strict validation then pre-registered scopes have to contains all + // the current request scopes + if (!partialMatchScopeValidation) { + return registeredScopes.containsAll(requestScopes); + } else { + for (String requestScope : requestScopes) { + boolean match = false; + for (String registeredScope : registeredScopes) { + if (requestScope.startsWith(registeredScope)) { + match = true; + break; + } + } + if (!match) { + return false; + } + } + } + } + return true; + } }
