Author: sergeyb
Date: Tue Jun 4 11:57:46 2013
New Revision: 1489392
URL: http://svn.apache.org/r1489392
Log:
[CXF-5055] OOB Response support, Client scopes registration
Added:
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OOBAuthorizationResponse.java
(with props)
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OAuthContextProvider.java
(with props)
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OOBResponseDeliverer.java
(with props)
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/MessageDigestGenerator.java
(with props)
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtilsTest.java
(with props)
Removed:
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/MD5SequenceGenerator.java
Modified:
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/AbstractGrantHandler.java
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/refresh/RefreshTokenGrantHandler.java
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AccessTokenService.java
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AuthorizationCodeGrantService.java
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/ImplicitGrantService.java
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java
Modified:
cxf/trunk/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/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java?rev=1489392&r1=1489391&r2=1489392&view=diff
==============================================================================
---
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java
(original)
+++
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java
Tue Jun 4 11:57:46 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;
+ }
}
Added:
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OOBAuthorizationResponse.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OOBAuthorizationResponse.java?rev=1489392&view=auto
==============================================================================
---
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OOBAuthorizationResponse.java
(added)
+++
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OOBAuthorizationResponse.java
Tue Jun 4 11:57:46 2013
@@ -0,0 +1,60 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this 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.apache.cxf.rs.security.oauth2.common;
+
+
+public class OOBAuthorizationResponse {
+ private String authorizationCode;
+ private String clientId;
+ private String userId;
+ private long lifetime;
+
+ public String getAuthorizationCode() {
+ return authorizationCode;
+ }
+
+ public void setAuthorizationCode(String authorizationCode) {
+ this.authorizationCode = authorizationCode;
+ }
+
+ public String getClientId() {
+ return clientId;
+ }
+
+ public void setClientId(String clientId) {
+ this.clientId = clientId;
+ }
+
+ public String getUserId() {
+ return userId;
+ }
+
+ public void setUserId(String userId) {
+ this.userId = userId;
+ }
+
+ public long getLifetime() {
+ return lifetime;
+ }
+
+ public void setLifetime(long lifetime) {
+ this.lifetime = lifetime;
+ }
+
+}
Propchange:
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OOBAuthorizationResponse.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OOBAuthorizationResponse.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Modified:
cxf/trunk/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/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/AbstractGrantHandler.java?rev=1489392&r1=1489391&r2=1489392&view=diff
==============================================================================
---
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/AbstractGrantHandler.java
(original)
+++
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/AbstractGrantHandler.java
Tue Jun 4 11:57:46 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/trunk/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/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/refresh/RefreshTokenGrantHandler.java?rev=1489392&r1=1489391&r2=1489392&view=diff
==============================================================================
---
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/refresh/RefreshTokenGrantHandler.java
(original)
+++
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/refresh/RefreshTokenGrantHandler.java
Tue Jun 4 11:57:46 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;
+ }
}
Added:
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OAuthContextProvider.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OAuthContextProvider.java?rev=1489392&view=auto
==============================================================================
---
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OAuthContextProvider.java
(added)
+++
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OAuthContextProvider.java
Tue Jun 4 11:57:46 2013
@@ -0,0 +1,34 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this 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.apache.cxf.rs.security.oauth2.provider;
+
+import javax.ws.rs.ext.Provider;
+
+import org.apache.cxf.jaxrs.ext.ContextProvider;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.rs.security.oauth2.common.OAuthContext;
+
+@Provider
+public class OAuthContextProvider implements ContextProvider<OAuthContext> {
+
+ public OAuthContext createContext(Message message) {
+ return message.getContent(OAuthContext.class);
+ }
+
+}
Propchange:
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OAuthContextProvider.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OAuthContextProvider.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added:
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OOBResponseDeliverer.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OOBResponseDeliverer.java?rev=1489392&view=auto
==============================================================================
---
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OOBResponseDeliverer.java
(added)
+++
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OOBResponseDeliverer.java
Tue Jun 4 11:57:46 2013
@@ -0,0 +1,27 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this 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.apache.cxf.rs.security.oauth2.provider;
+
+import javax.ws.rs.core.Response;
+
+import org.apache.cxf.rs.security.oauth2.common.OOBAuthorizationResponse;
+
+public interface OOBResponseDeliverer {
+ Response deliver(OOBAuthorizationResponse response);
+}
Propchange:
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OOBResponseDeliverer.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OOBResponseDeliverer.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Modified:
cxf/trunk/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/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AccessTokenService.java?rev=1489392&r1=1489391&r2=1489392&view=diff
==============================================================================
---
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AccessTokenService.java
(original)
+++
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AccessTokenService.java
Tue Jun 4 11:57:46 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 NotAuthorizedException(Response.status(401).build());
}
@@ -230,4 +239,8 @@ public class AccessTokenService extends
return client;
}
+
+ public void setCanSupportPublicClients(boolean support) {
+ this.canSupportPublicClients = support;
+ }
}
Modified:
cxf/trunk/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/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AuthorizationCodeGrantService.java?rev=1489392&r1=1489391&r2=1489392&view=diff
==============================================================================
---
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AuthorizationCodeGrantService.java
(original)
+++
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AuthorizationCodeGrantService.java
Tue Jun 4 11:57:46 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/trunk/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/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/ImplicitGrantService.java?rev=1489392&r1=1489391&r2=1489392&view=diff
==============================================================================
---
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/ImplicitGrantService.java
(original)
+++
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/ImplicitGrantService.java
Tue Jun 4 11:57:46 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/trunk/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/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java?rev=1489392&r1=1489391&r2=1489392&view=diff
==============================================================================
---
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java
(original)
+++
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java
Tue Jun 4 11:57:46 2013
@@ -57,17 +57,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;
}
/**
@@ -119,7 +117,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);
}
@@ -128,9 +126,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);
@@ -235,10 +241,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
@@ -309,8 +316,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;
}
@@ -374,4 +381,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);
}
Added:
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/MessageDigestGenerator.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/MessageDigestGenerator.java?rev=1489392&view=auto
==============================================================================
---
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/MessageDigestGenerator.java
(added)
+++
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/MessageDigestGenerator.java
Tue Jun 4 11:57:46 2013
@@ -0,0 +1,57 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this 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.apache.cxf.rs.security.oauth2.utils;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException;
+
+/**
+ * The utility Message Digest generator which can be used for generating
+ * random values
+ */
+public class MessageDigestGenerator {
+ private String algorithm = "MD5";
+
+ public String generate(byte[] input) throws OAuthServiceException {
+ if (input == null) {
+ throw new OAuthServiceException("You have to pass input to Token
Generator");
+ }
+
+ try {
+ MessageDigest md = MessageDigest.getInstance(algorithm);
+ md.reset();
+ md.update(input);
+ byte[] messageDigest = md.digest();
+ StringBuffer hexString = new StringBuffer();
+ for (int i = 0; i < messageDigest.length; i++) {
+ hexString.append(Integer.toHexString(0xFF & messageDigest[i]));
+ }
+
+ return hexString.toString();
+ } catch (NoSuchAlgorithmException e) {
+ throw new OAuthServiceException("server_error", e);
+ }
+ }
+
+ public void setAlgorithm(String algo) {
+ this.algorithm = algo;
+ }
+}
Propchange:
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/MessageDigestGenerator.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/MessageDigestGenerator.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Modified:
cxf/trunk/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/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java?rev=1489392&r1=1489391&r2=1489392&view=diff
==============================================================================
---
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java
(original)
+++
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java
Tue Jun 4 11:57:46 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;
+ }
}
Added:
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtilsTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtilsTest.java?rev=1489392&view=auto
==============================================================================
---
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtilsTest.java
(added)
+++
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtilsTest.java
Tue Jun 4 11:57:46 2013
@@ -0,0 +1,54 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this 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.apache.cxf.rs.security.oauth2.utils;
+
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class OAuthUtilsTest extends Assert {
+
+ @Test
+ public void testValidateScopesStrict() {
+ List<String> requestScopes = OAuthUtils.parseScope("a c b");
+ List<String> registeredScopes = OAuthUtils.parseScope("a b c d");
+ assertTrue(OAuthUtils.validateScopes(requestScopes, registeredScopes,
false));
+ }
+ @Test
+ public void testValidateScopesStrictFail() {
+ List<String> requestScopes = OAuthUtils.parseScope("a b c d");
+ List<String> registeredScopes = OAuthUtils.parseScope("a b d");
+ assertFalse(OAuthUtils.validateScopes(requestScopes, registeredScopes,
false));
+ }
+
+ @Test
+ public void testValidateScopesPartial() {
+ List<String> requestScopes = OAuthUtils.parseScope("a b c-1");
+ List<String> registeredScopes = OAuthUtils.parseScope("a b c");
+ assertTrue(OAuthUtils.validateScopes(requestScopes, registeredScopes,
true));
+ }
+
+ @Test
+ public void testValidateScopesPartialFail() {
+ List<String> requestScopes = OAuthUtils.parseScope("a b c");
+ List<String> registeredScopes = OAuthUtils.parseScope("a b");
+ assertFalse(OAuthUtils.validateScopes(requestScopes, registeredScopes,
true));
+ }
+}
Propchange:
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtilsTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtilsTest.java
------------------------------------------------------------------------------
svn:keywords = Rev Date