cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From serg...@apache.org
Subject svn commit: r1489392 - in /cxf/trunk/rt/rs/security/oauth-parent/oauth2/src: main/java/org/apache/cxf/rs/security/oauth2/common/ main/java/org/apache/cxf/rs/security/oauth2/grants/ main/java/org/apache/cxf/rs/security/oauth2/grants/refresh/ main/java/o...
Date Tue, 04 Jun 2013 11:57:47 GMT
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



Mime
View raw message