You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2013/06/04 14:06:02 UTC
svn commit: r1489396 - in /cxf/branches/2.6.x-fixes: ./
rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/
rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/
rt/rs/security...
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;
+ }
}