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 2012/03/07 14:52:47 UTC

svn commit: r1297971 - in /cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2: common/ filters/ grants/ grants/clientcred/ grants/code/ provider/ services/ tokens/bearer/ utils/

Author: sergeyb
Date: Wed Mar  7 13:52:46 2012
New Revision: 1297971

URL: http://svn.apache.org/viewvc?rev=1297971&view=rev
Log:
[CXF-4112,CXF-4151] A lof of refactoring to do with supporting different grants, preauthorized tokens, etc

Added:
    cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/AccessTokenRegistration.java   (with props)
    cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/ImplicitGrantService.java   (with props)
    cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java   (with props)
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/common/OAuthAuthorizationData.java
    cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthContext.java
    cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthPermission.java
    cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/UserSubject.java
    cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/OAuthRequestFilter.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/clientcred/ClientCredentialsGrantHandler.java
    cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeGrantHandler.java
    cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeRegistration.java
    cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/ServerAuthorizationCodeGrant.java
    cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OAuthDataProvider.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/tokens/bearer/BearerAccessToken.java
    cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthConstants.java
    cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java

Added: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/AccessTokenRegistration.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/AccessTokenRegistration.java?rev=1297971&view=auto
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/AccessTokenRegistration.java (added)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/AccessTokenRegistration.java Wed Mar  7 13:52:46 2012
@@ -0,0 +1,65 @@
+/**
+ * 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;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Captures the information associated with the code grant registration request.
+ */
+public class AccessTokenRegistration {
+    private Client client; 
+    private List<String> requestedScope = Collections.emptyList();
+    private List<String> approvedScope = Collections.emptyList();
+    private String grantType;
+    private UserSubject subject;
+    
+    public void setClient(Client client) {
+        this.client = client;
+    }
+    public Client getClient() {
+        return client;
+    }
+    
+    public void setRequestedScope(List<String> requestedScope) {
+        this.requestedScope = requestedScope;
+    }
+    public List<String> getRequestedScope() {
+        return requestedScope;
+    }
+    public void setSubject(UserSubject subject) {
+        this.subject = subject;
+    }
+    public UserSubject getSubject() {
+        return subject;
+    }
+    public void setGrantType(String grantType) {
+        this.grantType = grantType;
+    }
+    public String getGrantType() {
+        return grantType;
+    }
+    public void setApprovedScope(List<String> approvedScope) {
+        this.approvedScope = approvedScope;
+    }
+    public List<String> getApprovedScope() {
+        return approvedScope;
+    }
+}

Propchange: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/AccessTokenRegistration.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/AccessTokenRegistration.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

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=1297971&r1=1297970&r2=1297971&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 Wed Mar  7 13:52:46 2012
@@ -35,11 +35,12 @@ public class Client {
     private String applicationDescription;
     private String applicationWebUri;
     private String applicationLogoUri;
-    
     private List<String> redirectUris = Collections.emptyList();
+    
     private boolean isConfidential;
+    private List<String> allowedGrantTypes = Collections.emptyList();
     
-    private String loginName;
+    private UserSubject subject;
         
     public Client(String clientId, String clientSecret, boolean isConfidential) {
         this.clientId = clientId;
@@ -137,24 +138,6 @@ public class Client {
         return applicationLogoUri;
     }
 
-    /**
-     * Gets the optional login name which does not necessarily matches
-     * the clientId; can be used for enforcing the existing RBAC rules.
-     *  
-     * @return the login name
-     */
-    public String getLoginName() {
-        return loginName;
-    }
-    
-    /**
-     * Sets the optional login name
-     * @param name the login name
-     */
-    public void setLoginName(String name) {
-        this.loginName = name;
-    }
-
     public void setConfidential(boolean isConf) {
         this.isConfidential = isConf;
     }
@@ -170,4 +153,20 @@ public class Client {
     public List<String> getRedirectUris() {
         return redirectUris;
     }
+
+    public void setAllowedGrantTypes(List<String> allowedGrantTypes) {
+        this.allowedGrantTypes = allowedGrantTypes;
+    }
+
+    public List<String> getAllowedGrantTypes() {
+        return allowedGrantTypes;
+    }
+
+    public void setSubject(UserSubject subject) {
+        this.subject = subject;
+    }
+
+    public UserSubject getSubject() {
+        return subject;
+    }
 }

Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthAuthorizationData.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/OAuthAuthorizationData.java?rev=1297971&r1=1297970&r2=1297971&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthAuthorizationData.java (original)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthAuthorizationData.java Wed Mar  7 13:52:46 2012
@@ -37,6 +37,7 @@ public class OAuthAuthorizationData impl
     private String redirectUri;
     private String state;
     private String proposedScope;
+    
     private String authenticityToken;
     private String replyTo;
     

Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthContext.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/OAuthContext.java?rev=1297971&r1=1297970&r2=1297971&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthContext.java (original)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthContext.java Wed Mar  7 13:52:46 2012
@@ -47,7 +47,6 @@ public class OAuthContext {
         return Collections.unmodifiableList(permissions);
     }
 
-    
     public String getTokenGrantType() {
         return tokenGrantType;
     }

Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthPermission.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/OAuthPermission.java?rev=1297971&r1=1297970&r2=1297971&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthPermission.java (original)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthPermission.java Wed Mar  7 13:52:46 2012
@@ -25,7 +25,6 @@ import java.util.List;
  * Provides the complete information about a given opaque permission.
  */
 public class OAuthPermission extends Permission {
-    private List<String> roles = Collections.emptyList();
     private List<String> httpVerbs = Collections.emptyList();
     private List<String> uris = Collections.emptyList();
     
@@ -33,19 +32,6 @@ public class OAuthPermission extends Per
         super(permission, description);
     }
     
-    public OAuthPermission(String permission, String description, List<String> roles) {
-        super(permission, description);
-        this.roles = roles;
-    }
-
-    public void setRoles(List<String> roles) {
-        this.roles = roles;
-    }
-
-    public List<String> getRoles() {
-        return roles;
-    }
-
     public void setHttpVerbs(List<String> httpVerbs) {
         this.httpVerbs = httpVerbs;
     }

Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/UserSubject.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/UserSubject.java?rev=1297971&r1=1297970&r2=1297971&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/UserSubject.java (original)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/UserSubject.java Wed Mar  7 13:52:46 2012
@@ -28,7 +28,11 @@ import java.util.List;
 public class UserSubject {
     
     private String login;
-    private List<String> roles;
+    private List<String> roles = Collections.emptyList();
+    
+    public UserSubject(String login) {
+        this.login = login;
+    }
     
     public UserSubject(String login, List<String> roles) {
         this.login = login;

Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/OAuthRequestFilter.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/OAuthRequestFilter.java?rev=1297971&r1=1297970&r2=1297971&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/OAuthRequestFilter.java (original)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/OAuthRequestFilter.java Wed Mar  7 13:52:46 2012
@@ -94,10 +94,11 @@ public class OAuthRequestFilter implemen
             throw new WebApplicationException(403);
         }
       
-        OAuthInfo info = new OAuthInfo(accessToken, matchingPermissions);
-        SecurityContext sc = createSecurityContext(req, info);
+        SecurityContext sc = createSecurityContext(req, accessToken);
         m.put(SecurityContext.class, sc);
-        m.setContent(OAuthContext.class, createOAuthContext(info));
+        m.setContent(OAuthContext.class, new OAuthContext(accessToken.getSubject(),
+                                                          matchingPermissions,
+                                                          accessToken.getGrantType()));
         
         return null;
     }
@@ -192,66 +193,27 @@ public class OAuthRequestFilter implemen
     }
     
     protected SecurityContext createSecurityContext(HttpServletRequest request, 
-                                                    final OAuthInfo info) {
-        UserSubject subject = info.getToken().getSubject();
+                                                    ServerAccessToken token) {
+        UserSubject endUserSubject = token.getSubject();
+        UserSubject clientSubject = token.getClient().getSubject();
 
-        final UserSubject theSubject = subject;
-        final String login = OAuthRequestFilter.this.useUserSubject 
-                    ? (theSubject != null ? theSubject.getLogin() : null)
-                        : info.getToken().getClient().getLoginName();
+        final UserSubject theSubject = 
+            OAuthRequestFilter.this.useUserSubject ? endUserSubject : clientSubject;
                     
         return new SecurityContext() {
 
             public Principal getUserPrincipal() {
-                return login != null ? new SimplePrincipal(login) : null;
+                return theSubject != null ? new SimplePrincipal(theSubject.getLogin()) : null;
             }
 
             public boolean isUserInRole(String role) {
-                if (login == null) {
+                if (theSubject == null) {
                     return false;
                 }
-                List<String> roles = null;
-                if (OAuthRequestFilter.this.useUserSubject && theSubject != null) {
-                    roles = theSubject.getRoles();    
-                } else {
-                    roles = info.getRoles();
-                }
-                return roles == null ? false : roles.contains(role);
+                return theSubject.getRoles().contains(role);
             }
-             
         };
     }
     
-    private OAuthContext createOAuthContext(OAuthInfo info) {
-        return new OAuthContext(info.getToken().getSubject(),
-                                info.getMatchedPermissions(),
-                                info.getToken().getGrantType());
-    }
-    
-    private static class OAuthInfo {
-        private ServerAccessToken token;
-        private List<OAuthPermission> permissions;
-        public OAuthInfo(ServerAccessToken token, 
-                         List<OAuthPermission> matchedPermissions) {
-            this.token = token;
-            this.permissions = matchedPermissions;
-        }
-        public ServerAccessToken getToken() {
-            return token;
-        }
-        
-        public List<String> getRoles() {
-            List<String> authorities = new ArrayList<String>();
-            for (OAuthPermission permission : permissions) {
-                authorities.addAll(permission.getRoles());
-            }
-            return authorities;
-        }
-        
-        public List<OAuthPermission> getMatchedPermissions() {
-            return permissions;
-        }
-        
-            
-    }
+    
 }

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=1297971&r1=1297970&r2=1297971&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 Wed Mar  7 13:52:46 2012
@@ -21,26 +21,27 @@ package org.apache.cxf.rs.security.oauth
 
 import java.util.Collections;
 import java.util.List;
-import java.util.UUID;
 
+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.ServerAccessToken;
+import org.apache.cxf.rs.security.oauth2.common.UserSubject;
 import org.apache.cxf.rs.security.oauth2.provider.AccessTokenGrantHandler;
 import org.apache.cxf.rs.security.oauth2.provider.OAuthDataProvider;
 import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException;
-import org.apache.cxf.rs.security.oauth2.utils.MD5SequenceGenerator;
 import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
+import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils;
 
 
 
 public abstract class AbstractGrantHandler implements AccessTokenGrantHandler {
     
-    private static final long DEFAULT_TOKEN_LIFETIME = 3600L;
-    
-    private long tokenLifetime = DEFAULT_TOKEN_LIFETIME;
-    private List<String> supportedGrants;
+    private String supportedGrant;
     private OAuthDataProvider dataProvider;
-        
-    protected AbstractGrantHandler(String grant) {
-        supportedGrants = Collections.singletonList(grant);
+    private boolean isClientConfidential;    
+    protected AbstractGrantHandler(String grant, boolean isClientConfidential) {
+        supportedGrant = grant;
+        this.isClientConfidential = isClientConfidential;
     }
     
     public void setDataProvider(OAuthDataProvider dataProvider) {
@@ -51,25 +52,30 @@ public abstract class AbstractGrantHandl
     }
     
     public List<String> getSupportedGrantTypes() {
-        return supportedGrants;
+        return Collections.singletonList(supportedGrant);
     }
     
-    protected static String generateRandomTokenKey() throws OAuthServiceException {
-        try {
-            byte[] bytes = UUID.randomUUID().toString().getBytes("UTF-8");
-            return new MD5SequenceGenerator().generate(bytes);
-        } catch (Exception ex) {
-            throw new OAuthServiceException(OAuthConstants.SERVER_ERROR, ex);
+    protected void checkIfGrantSupported(Client client) {
+        if (!OAuthUtils.isGrantSupportedForClient(client, isClientConfidential, supportedGrant)) {
+            throw new OAuthServiceException(OAuthConstants.UNAUTHORIZED_CLIENT);    
         }
     }
-
-    public void setTokenLifetime(long tokenLifetime) {
-        this.tokenLifetime = tokenLifetime;
-    }
-
-    public long getTokenLifetime() {
-        return tokenLifetime;
-    }
-    
     
+    protected ServerAccessToken doCreateAccessToken(Client client,
+                                                    UserSubject subject,
+                                                    List<String> requestedScope) {
+        ServerAccessToken token = dataProvider.getPreauthorizedToken(
+                                     client, subject, supportedGrant);
+        if (token != null) {
+            return token;
+        }
+        
+        AccessTokenRegistration reg = new AccessTokenRegistration();
+        reg.setClient(client);
+        reg.setGrantType(supportedGrant);
+        reg.setSubject(subject);
+        reg.setRequestedScope(requestedScope);        
+        
+        return dataProvider.createAccessToken(reg);
+    }
 }

Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/clientcred/ClientCredentialsGrantHandler.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/clientcred/ClientCredentialsGrantHandler.java?rev=1297971&r1=1297970&r2=1297971&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/clientcred/ClientCredentialsGrantHandler.java (original)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/clientcred/ClientCredentialsGrantHandler.java Wed Mar  7 13:52:46 2012
@@ -24,30 +24,26 @@ import org.apache.cxf.rs.security.oauth2
 import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken;
 import org.apache.cxf.rs.security.oauth2.grants.AbstractGrantHandler;
 import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException;
-import org.apache.cxf.rs.security.oauth2.tokens.bearer.BearerAccessToken;
 import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
+import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils;
 
-public class ClientCredentialsGrantHandler  extends AbstractGrantHandler {
+public class ClientCredentialsGrantHandler extends AbstractGrantHandler {
+   
     
     public ClientCredentialsGrantHandler() {
-        super(OAuthConstants.CLIENT_CREDENTIALS_GRANT);
+        super(OAuthConstants.CLIENT_CREDENTIALS_GRANT, true);
     }
 
     public ServerAccessToken createAccessToken(Client client, MultivaluedMap<String, String> params)
         throws OAuthServiceException {
-        if (!client.isConfidential()) {
-            throw new OAuthServiceException(OAuthConstants.UNAUTHORIZED_CLIENT);    
-        }
-        BearerAccessToken token = new BearerAccessToken(client, 
-                                                        generateRandomTokenKey(),
-                                                        getTokenLifetime(), 
-                                                        System.currentTimeMillis() / 1000);
-        token.setGrantType(OAuthConstants.CLIENT_CREDENTIALS_GRANT);
-        // the OAuth filter will use Client.getLoginName() to initialize 
-        // the Principal when setting up the security context 
-        
-        return token;
+        checkIfGrantSupported(client);
         
+        // the OAuth filter will use Client.getLoginName() to initialize 
+        // the Principal when setting up the security context
+        // TODO: consider setting the UserSubject representing the authenticated Client instead
+        return doCreateAccessToken(client, 
+                                   null, 
+                                   OAuthUtils.parseScope(params.getFirst(OAuthConstants.SCOPE)));
     }
 
 

Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeGrantHandler.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/code/AuthorizationCodeGrantHandler.java?rev=1297971&r1=1297970&r2=1297971&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeGrantHandler.java (original)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeGrantHandler.java Wed Mar  7 13:52:46 2012
@@ -25,7 +25,6 @@ import org.apache.cxf.rs.security.oauth2
 import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken;
 import org.apache.cxf.rs.security.oauth2.grants.AbstractGrantHandler;
 import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException;
-import org.apache.cxf.rs.security.oauth2.tokens.bearer.BearerAccessToken;
 import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
 import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils;
 
@@ -34,11 +33,13 @@ import org.apache.cxf.rs.security.oauth2
 public class AuthorizationCodeGrantHandler extends AbstractGrantHandler {
     
     public AuthorizationCodeGrantHandler() {
-        super(OAuthConstants.AUTHORIZATION_CODE_GRANT);
+        super(OAuthConstants.AUTHORIZATION_CODE_GRANT, true);
     }
     
     public ServerAccessToken createAccessToken(Client client, MultivaluedMap<String, String> params) 
         throws OAuthServiceException {
+        checkIfGrantSupported(client);
+        
         String codeValue = params.getFirst(OAuthConstants.AUTHORIZATION_CODE_VALUE);
         ServerAuthorizationCodeGrant grant = 
             ((AuthorizationCodeDataProvider)getDataProvider()).removeCodeGrant(codeValue);
@@ -48,22 +49,18 @@ public class AuthorizationCodeGrantHandl
         if (OAuthUtils.isExpired(grant.getIssuedAt(), grant.getLifetime())) {
             throw new OAuthServiceException(OAuthConstants.INVALID_GRANT);
         }
-        
+        if (!grant.getClient().getClientId().equals(client.getClientId())) {
+            throw new OAuthServiceException(OAuthConstants.INVALID_GRANT);
+        }
         String expectedRedirectUri = grant.getRedirectUri();
         if (expectedRedirectUri != null) {
             String providedRedirectUri = params.getFirst(OAuthConstants.REDIRECT_URI);
-            if (providedRedirectUri == null || !providedRedirectUri.equals(expectedRedirectUri)) {
+            
+            if (providedRedirectUri != null && !providedRedirectUri.equals(expectedRedirectUri)) {
                 throw new OAuthServiceException(OAuthConstants.INVALID_REQUEST);
             }
         }
-        BearerAccessToken token = new BearerAccessToken(client, 
-                                                        generateRandomTokenKey(),
-                                                        getTokenLifetime(), 
-                                                        System.currentTimeMillis() / 1000);
-        token.setScopes(grant.getApprovedScopes());
-        token.setSubject(grant.getSubject());
-        token.setGrantType(OAuthConstants.AUTHORIZATION_CODE_GRANT);
-        return token;
+        return doCreateAccessToken(client, grant.getSubject(), grant.getApprovedScopes());
     }
     
 }

Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeRegistration.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/code/AuthorizationCodeRegistration.java?rev=1297971&r1=1297970&r2=1297971&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeRegistration.java (original)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeRegistration.java Wed Mar  7 13:52:46 2012
@@ -18,6 +18,7 @@
  */
 package org.apache.cxf.rs.security.oauth2.grants.code;
 
+import java.util.Collections;
 import java.util.List;
 
 import org.apache.cxf.rs.security.oauth2.common.Client;
@@ -29,10 +30,8 @@ import org.apache.cxf.rs.security.oauth2
  */
 public class AuthorizationCodeRegistration {
     private Client client; 
-    private List<String> requestedScope;
-    private List<String> approvedScope;
-    private long lifetime;
-    private long issuedAt;
+    private List<String> requestedScope = Collections.emptyList();
+    private List<String> approvedScope = Collections.emptyList();
     private String redirectUri;
     private UserSubject subject;
     
@@ -43,18 +42,6 @@ public class AuthorizationCodeRegistrati
         return client;
     }
     
-    public void setLifetime(long lifetime) {
-        this.lifetime = lifetime;
-    }
-    public long getLifetime() {
-        return lifetime;
-    }
-    public void setIssuedAt(long issuedAt) {
-        this.issuedAt = issuedAt;
-    }
-    public long getIssuedAt() {
-        return issuedAt;
-    }
     public void setRedirectUri(String redirectUri) {
         this.redirectUri = redirectUri;
     }

Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/ServerAuthorizationCodeGrant.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/code/ServerAuthorizationCodeGrant.java?rev=1297971&r1=1297970&r2=1297971&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/ServerAuthorizationCodeGrant.java (original)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/ServerAuthorizationCodeGrant.java Wed Mar  7 13:52:46 2012
@@ -22,8 +22,8 @@ import java.util.Collections;
 import java.util.List;
 
 import org.apache.cxf.rs.security.oauth2.common.Client;
-import org.apache.cxf.rs.security.oauth2.common.OAuthPermission;
 import org.apache.cxf.rs.security.oauth2.common.UserSubject;
+import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils;
 
 
 /**
@@ -33,10 +33,16 @@ public class ServerAuthorizationCodeGran
     private long issuedAt;
     private long lifetime;
     private Client client;
-    private List<OAuthPermission> approvedScopes = Collections.emptyList();
+    private List<String> approvedScopes = Collections.emptyList();
     private UserSubject subject;
     
     public ServerAuthorizationCodeGrant(Client client, 
+                                        long lifetime) {
+        this(client, OAuthUtils.generateRandomTokenKey(), lifetime,
+             System.currentTimeMillis() / 1000);
+    }
+    
+    public ServerAuthorizationCodeGrant(Client client, 
                                   String code,
                                   long lifetime, 
                                   long issuedAt) {
@@ -60,12 +66,12 @@ public class ServerAuthorizationCodeGran
     }
 
 
-    public void setApprovedScopes(List<OAuthPermission> scopes) {
+    public void setApprovedScopes(List<String> scopes) {
         this.approvedScopes = scopes;
     }
 
 
-    public List<OAuthPermission> getApprovedScopes() {
+    public List<String> getApprovedScopes() {
         return approvedScopes;
     }
 

Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OAuthDataProvider.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/OAuthDataProvider.java?rev=1297971&r1=1297970&r2=1297971&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OAuthDataProvider.java (original)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OAuthDataProvider.java Wed Mar  7 13:52:46 2012
@@ -21,9 +21,11 @@ package org.apache.cxf.rs.security.oauth
 
 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.OAuthPermission;
 import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken;
+import org.apache.cxf.rs.security.oauth2.common.UserSubject;
 
 /**
  * OAuth provider responsible for persisting the information about 
@@ -46,7 +48,7 @@ public interface OAuthDataProvider {
      * @return AccessToken
      * @throws OAuthServiceException
      */
-    void persistAccessToken(ServerAccessToken accessToken) throws OAuthServiceException;
+    ServerAccessToken createAccessToken(AccessTokenRegistration accessToken) throws OAuthServiceException;
     
     /**
      * Get access token 
@@ -57,6 +59,16 @@ public interface OAuthDataProvider {
     ServerAccessToken getAccessToken(String accessToken) throws OAuthServiceException;
     
     /**
+     * TODO: Consider introducing a dedicated entity representing a user pre authorization
+     * Get preauthorized access token 
+     * @param accessToken the token key 
+     * @return AccessToken
+     * @throws OAuthServiceException
+     */
+    ServerAccessToken getPreauthorizedToken(Client client, UserSubject subject, String grantType) 
+        throws OAuthServiceException;
+    
+    /**
      * Refresh access token 
      * @param clientId the client id
      * @param refreshToken the token key 

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=1297971&r1=1297970&r2=1297971&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 Wed Mar  7 13:52:46 2012
@@ -73,7 +73,6 @@ public class AccessTokenService extends 
         if (serverToken == null) {
             return createErrorResponse(params, OAuthConstants.INVALID_GRANT);
         }
-        getDataProvider().persistAccessToken(serverToken);
         
         ClientAccessToken clientToken = new ClientAccessToken(serverToken.getTokenType(),
                                                               serverToken.getTokenKey());

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=1297971&r1=1297970&r2=1297971&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 Wed Mar  7 13:52:46 2012
@@ -19,37 +19,21 @@
 
 package org.apache.cxf.rs.security.oauth2.services;
 
-import java.security.Principal;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.LinkedList;
 import java.util.List;
-import java.util.Set;
-import java.util.UUID;
 
-import javax.servlet.http.HttpSession;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
 import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriBuilder;
 
-import org.apache.cxf.common.util.StringUtils;
 import org.apache.cxf.rs.security.oauth2.common.Client;
-import org.apache.cxf.rs.security.oauth2.common.OAuthAuthorizationData;
-import org.apache.cxf.rs.security.oauth2.common.OAuthPermission;
+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.utils.OAuthConstants;
-import org.apache.cxf.security.LoginSecurityContext;
-import org.apache.cxf.security.SecurityContext;
 
 
 /**
@@ -60,182 +44,38 @@ import org.apache.cxf.security.SecurityC
  * a request token verifier (aka authorization code)
  */
 @Path("/authorize")
-public class AuthorizationCodeGrantService extends AbstractOAuthService {
-    private static final long DEFAULT_CODE_GRANT_LIFETIME = 3600L;
-    
-    private long grantLifetime = DEFAULT_CODE_GRANT_LIFETIME;
-    
-    @GET
-    @Produces({"application/xhtml+xml", "text/html", "application/xml", "application/json" })
-    public Response authorize() {
-        MultivaluedMap<String, String> params = getQueryParameters();
-        return startAuthorization(params);
-    }
-    
-    @GET
-    @Path("/decision")
-    public Response authorizeDecision() {
-        MultivaluedMap<String, String> params = getQueryParameters();
-        return completeAuthorization(params);
-    }
-    
-    @POST
-    @Path("/decision")
-    @Consumes("application/x-www-form-urlencoded")
-    public Response authorizeDecisionForm(MultivaluedMap<String, String> params) {
-        return completeAuthorization(params);
-    }
-    
-    protected Response startAuthorization(MultivaluedMap<String, String> params) {
-        getAndValidateSecurityContext();
-        
-        Client client = getClient(params); 
-        String redirectUri = validateRedirectUri(client, params.getFirst(OAuthConstants.REDIRECT_URI)); 
-        if (!client.isConfidential()) {
-            return createErrorResponse(params, redirectUri, OAuthConstants.UNAUTHORIZED_CLIENT);
-        }
-        String responseType = params.getFirst(OAuthConstants.RESPONSE_TYPE);
-        if (responseType == null || !responseType.equals(OAuthConstants.CODE_RESPONSE_TYPE)) {
-            return createErrorResponse(params, redirectUri, OAuthConstants.UNSUPPORTED_RESPONSE_TYPE);
-        }
-        
-        List<OAuthPermission> permissions = null;
-        try {
-            permissions = convertScopeToPermissions(client, params.getFirst(OAuthConstants.SCOPE));
-        } catch (OAuthServiceException ex) {
-            return createErrorResponse(params, redirectUri, OAuthConstants.INVALID_SCOPE);
-        }
-        OAuthAuthorizationData data = 
-            createAuthorizationData(client, params, permissions);
-        return Response.ok(data).build();
-        
-    }
-    
-    public void setGrantLifetime(long lifetime) {
-        this.grantLifetime = lifetime;
+public class AuthorizationCodeGrantService extends RedirectionBasedGrantService {
+    public AuthorizationCodeGrantService() {
+        super(OAuthConstants.CODE_RESPONSE_TYPE, OAuthConstants.AUTHORIZATION_CODE_GRANT, true);
     }
     
-    protected List<OAuthPermission> convertScopeToPermissions(Client client, String scope) 
-        throws OAuthServiceException {
-        List<String> list = parseScope(scope);
-        
-        List<OAuthPermission> permissions = getDataProvider()
-            .convertScopeToPermissions(client, list);
-        
-        return permissions;
-    }
-    
-    protected OAuthAuthorizationData createAuthorizationData(
-        Client client, MultivaluedMap<String, String> params, List<OAuthPermission> perms) {
-        
-        OAuthAuthorizationData secData = new OAuthAuthorizationData();
-        
-        addAuthenticityTokenToSession(secData);
-                
-        secData.setPermissions(perms);
-        
-        StringBuilder sb = new StringBuilder();
-        for (OAuthPermission perm : perms) {
-            if (sb.length() > 0) {
-                sb.append(" ");
-            }
-            sb.append(perm.getPermission());
-        }
-        secData.setProposedScope(sb.toString());
-        
-        secData.setClientId(client.getClientId());
-        secData.setRedirectUri(params.getFirst(OAuthConstants.REDIRECT_URI));
-        secData.setState(params.getFirst(OAuthConstants.STATE));
-        
-        secData.setApplicationName(client.getApplicationName()); 
-        secData.setApplicationWebUri(client.getApplicationWebUri());
-        secData.setApplicationDescription(client.getApplicationDescription());
-        secData.setApplicationLogoUri(client.getApplicationLogoUri());
-        
-        String replyTo = getMessageContext().getUriInfo()
-            .getAbsolutePathBuilder().path("decision").build().toString();
-        secData.setReplyTo(replyTo);
-        
-        return secData;
-    }
-    
-    protected Response completeAuthorization(MultivaluedMap<String, String> params) {
-        SecurityContext securityContext = getAndValidateSecurityContext();
-        
-        if (!compareRequestAndSessionTokens(params.getFirst(OAuthConstants.SESSION_AUTHENTICITY_TOKEN))) {
-            throw new WebApplicationException(400);     
-        }
-        //TODO: additionally we can check that the Principal that got authenticated
-        // in startAuthorization is the same that got authenticated in completeAuthorization
-        
-        Client client = getClient(params);
-        String originalRedirectUri = params.getFirst(OAuthConstants.REDIRECT_URI);
-        String actualRedirectUri = validateRedirectUri(client, originalRedirectUri);
-        
-        String decision = params.getFirst(OAuthConstants.AUTHORIZATION_DECISION_KEY);
-        boolean allow = OAuthConstants.AUTHORIZATION_DECISION_ALLOW.equals(decision);
-
-        if (!allow) {
-            return createErrorResponse(params, actualRedirectUri, OAuthConstants.ACCESS_DENIED);
-        }
-        
+    protected Response createGrant(MultivaluedMap<String, String> params,
+                                   Client client,
+                                   String redirectUri,
+                                   List<String> requestedScope,
+                                   List<String> approvedScope,
+                                   UserSubject userSubject,
+                                   ServerAccessToken preauthorizedToken) {
+        // in this flow the code is still created, the preauthorized token
+        // will be retrieved by the authorization code grant handler
         AuthorizationCodeRegistration codeReg = new AuthorizationCodeRegistration(); 
         
         codeReg.setClient(client);
-        codeReg.setRedirectUri(originalRedirectUri);
-        codeReg.setLifetime(grantLifetime);
-        codeReg.setIssuedAt(System.currentTimeMillis() / 1000);
-        
-        List<String> requestedScope = parseScope(params.getFirst(OAuthConstants.SCOPE));
+        codeReg.setRedirectUri(redirectUri);
         codeReg.setRequestedScope(requestedScope);
-
-        List<String> approvedScope = new LinkedList<String>(); 
-        for (String rScope : requestedScope) {
-            String param = params.getFirst(rScope + "_status");
-            if (param != null && OAuthConstants.AUTHORIZATION_DECISION_ALLOW.equals(param)) {
-                approvedScope.add(rScope);
-            }
-        }
-        if (!requestedScope.containsAll(approvedScope)) {
-            return createErrorResponse(params, actualRedirectUri, OAuthConstants.INVALID_SCOPE);
-        }
-        // the decision was allow but the approved scopes end up being empty
-        // in this case we default to the requestedScope
-        if (approvedScope.isEmpty()) {
-            approvedScope = requestedScope;
-        }
         codeReg.setApprovedScope(approvedScope);
-        
-        List<String> roleNames = Collections.emptyList();
-        if (securityContext instanceof LoginSecurityContext) {
-            roleNames = new ArrayList<String>();
-            Set<Principal> roles = ((LoginSecurityContext)securityContext).getUserRoles();
-            for (Principal p : roles) {
-                roleNames.add(p.getName());
-            }
-        }
-        codeReg.setSubject(new UserSubject(securityContext.getUserPrincipal().getName(), roleNames));
+        codeReg.setSubject(userSubject);
         
         ServerAuthorizationCodeGrant grant = null;
         try {
             grant = ((AuthorizationCodeDataProvider)getDataProvider()).createCodeGrant(codeReg);
         } catch (OAuthServiceException ex) {
-            return createErrorResponse(params, actualRedirectUri, OAuthConstants.ACCESS_DENIED);
+            return createErrorResponse(params, redirectUri, OAuthConstants.ACCESS_DENIED);
         }
         
-        UriBuilder ub = getRedirectUriBuilder(params.getFirst(OAuthConstants.STATE), actualRedirectUri);
+        UriBuilder ub = getRedirectUriBuilder(params.getFirst(OAuthConstants.STATE), redirectUri);
         ub.queryParam(OAuthConstants.AUTHORIZATION_CODE_VALUE, grant.getCode());
-        return Response.seeOther(ub.build()).build();    
-    }
-    
-    private SecurityContext getAndValidateSecurityContext() {
-        SecurityContext securityContext =  
-            (SecurityContext)getMessageContext().get(SecurityContext.class.getName());
-        if (securityContext == null || securityContext.getUserPrincipal() == null) {
-            throw new WebApplicationException(401);
-        }
-        checkTransportSecurity();
-        return securityContext;
+        return Response.seeOther(ub.build()).build();
     }
     
     protected Response createErrorResponse(MultivaluedMap<String, String> params,
@@ -246,62 +86,13 @@ public class AuthorizationCodeGrantServi
         return Response.seeOther(ub.build()).build();
     }
     
-    private List<String> parseScope(String requestedScope) {
-        List<String> list = new LinkedList<String>();
-        if (requestedScope != null) {
-            String[] scopeValues = requestedScope.split(" ");
-            for (String scope : scopeValues) {
-                if (!StringUtils.isEmpty(scope)) {        
-                    list.add(scope);
-                }
-            }
-        }
-        return list;
-    }
-    
-    private UriBuilder getRedirectUriBuilder(String state, String redirectUri) {
+    protected UriBuilder getRedirectUriBuilder(String state, String redirectUri) {
         UriBuilder ub = UriBuilder.fromUri(redirectUri);
         if (state != null) { 
             ub.queryParam(OAuthConstants.STATE, state);
         }
         return ub;
     }
-    
-    protected String validateRedirectUri(Client client, String redirectUri) {
-        
-        List<String> uris = client.getRedirectUris();
-        if (redirectUri != null) {
-            String webUri = client.getApplicationWebUri();
-            if (uris.size() > 0 && !uris.contains(redirectUri)
-                || webUri != null && !redirectUri.startsWith(webUri)) {
-                redirectUri = null;
-            } 
-        } else if (uris.size() == 1) {
-            redirectUri = uris.get(0);
-        }
-        if (redirectUri == null) {
-            reportInvalidRequestError("Client Redirect Uri is invalid");
-        }
-        return redirectUri;
-    }
-    
-    private void addAuthenticityTokenToSession(OAuthAuthorizationData secData) {
-        HttpSession session = getMessageContext().getHttpServletRequest().getSession();
-        String value = UUID.randomUUID().toString();
-        secData.setAuthenticityToken(value);
-        session.setAttribute(OAuthConstants.SESSION_AUTHENTICITY_TOKEN, value);
-    }
-    
-    private boolean compareRequestAndSessionTokens(String requestToken) {
-        HttpSession session = getMessageContext().getHttpServletRequest().getSession();
-        String sessionToken = (String)session.getAttribute(OAuthConstants.SESSION_AUTHENTICITY_TOKEN);
-        
-        if (StringUtils.isEmpty(sessionToken)) {
-            return false;
-        }
-        
-        session.removeAttribute(OAuthConstants.SESSION_AUTHENTICITY_TOKEN);
-        return requestToken.equals(sessionToken);
-    }
-    
 }
+
+

Added: 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=1297971&view=auto
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/ImplicitGrantService.java (added)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/ImplicitGrantService.java Wed Mar  7 13:52:46 2012
@@ -0,0 +1,101 @@
+/**
+ * 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.services;
+
+import java.net.URI;
+import java.util.List;
+
+import javax.ws.rs.Path;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+
+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.ServerAccessToken;
+import org.apache.cxf.rs.security.oauth2.common.UserSubject;
+import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
+
+
+/**
+ * This resource handles the End User authorising
+ * or denying the Client to access its resources.
+ * If End User approves the access this resource will
+ * return the token directly.
+ * 
+ * We can consider having a single authorization service dealing with either
+ * authorization code or implicit grant.
+ */
+@Path("/authorize-implicit")
+public class ImplicitGrantService extends RedirectionBasedGrantService {
+    public ImplicitGrantService() {
+        super(OAuthConstants.TOKEN_RESPONSE_TYPE, OAuthConstants.IMPLICIT_GRANT, false);
+    }
+    
+    protected Response createGrant(MultivaluedMap<String, String> params,
+                                   Client client,
+                                   String redirectUri,
+                                   List<String> requestedScope,
+                                   List<String> approvedScope,
+                                   UserSubject userSubject,
+                                   ServerAccessToken preAuthorizedToken) {
+        ServerAccessToken token = null;
+        if (preAuthorizedToken != null) {
+            AccessTokenRegistration reg = new AccessTokenRegistration();
+            reg.setClient(client);
+            reg.setGrantType(OAuthConstants.IMPLICIT_GRANT);
+            reg.setSubject(userSubject);
+            reg.setRequestedScope(requestedScope);        
+            reg.setApprovedScope(approvedScope);
+            token = getDataProvider().createAccessToken(reg);
+        } else {
+            token = preAuthorizedToken;
+        }
+
+        
+        StringBuilder sb = getUriWithFragment(params.getFirst(OAuthConstants.STATE), redirectUri);
+        sb.append(OAuthConstants.ACCESS_TOKEN).append("=").append(token.getTokenKey());
+        sb.append(OAuthConstants.ACCESS_TOKEN_TYPE).append("=").append(token.getTokenType());
+        //TODO: token parameters should also be included probably
+        //      though it's not obvious the embedded client can deal with
+        //      MAC tokens or other sophisticated tokens 
+        return Response.seeOther(URI.create(sb.toString())).build();
+    }
+    
+    protected Response createErrorResponse(MultivaluedMap<String, String> params,
+                                           String redirectUri,
+                                           String error) {
+        StringBuilder sb = getUriWithFragment(params.getFirst(OAuthConstants.STATE), redirectUri);
+        sb.append(OAuthConstants.ERROR_KEY).append("=").append(error);
+        return Response.seeOther(URI.create(sb.toString())).build();
+    }
+    
+    private StringBuilder getUriWithFragment(String state, String redirectUri) {
+        StringBuilder sb = new StringBuilder();
+        sb.append(redirectUri);
+        sb.append("#");
+        if (state != null) {
+            sb.append(OAuthConstants.STATE).append("=").append(state);   
+        }
+        return sb;
+    }
+    
+}
+
+

Propchange: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/ImplicitGrantService.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/ImplicitGrantService.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: 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=1297971&view=auto
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java (added)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java Wed Mar  7 13:52:46 2012
@@ -0,0 +1,284 @@
+/**
+ * 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.services;
+
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+
+import javax.servlet.http.HttpSession;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+
+import org.apache.cxf.common.util.StringUtils;
+import org.apache.cxf.rs.security.oauth2.common.Client;
+import org.apache.cxf.rs.security.oauth2.common.OAuthAuthorizationData;
+import org.apache.cxf.rs.security.oauth2.common.OAuthPermission;
+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.OAuthServiceException;
+import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
+import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils;
+import org.apache.cxf.security.LoginSecurityContext;
+import org.apache.cxf.security.SecurityContext;
+
+
+/**
+ * This resource handles the End User authorising
+ * or denying the Client to access its resources.
+ * If End User approves the access this resource will
+ * redirect End User back to the Client, supplying 
+ * a request token verifier (aka authorization code)
+ */
+public abstract class RedirectionBasedGrantService extends AbstractOAuthService {
+    private String supportedResponseType;
+    private String supportedGrantType;
+    private boolean isClientConfidential;
+    protected RedirectionBasedGrantService(String supportedResponseType,
+                                           String supportedGrantType,
+                                           boolean isConfidential) {
+        this.supportedResponseType = supportedResponseType;
+        this.supportedGrantType = supportedGrantType;
+        this.isClientConfidential = isConfidential;
+    }
+    
+    @GET
+    @Produces({"application/xhtml+xml", "text/html", "application/xml", "application/json" })
+    public Response authorize() {
+        MultivaluedMap<String, String> params = getQueryParameters();
+        return startAuthorization(params);
+    }
+    
+    @GET
+    @Path("/decision")
+    public Response authorizeDecision() {
+        MultivaluedMap<String, String> params = getQueryParameters();
+        return completeAuthorization(params);
+    }
+    
+    @POST
+    @Path("/decision")
+    @Consumes("application/x-www-form-urlencoded")
+    public Response authorizeDecisionForm(MultivaluedMap<String, String> params) {
+        return completeAuthorization(params);
+    }
+    
+    protected Response startAuthorization(MultivaluedMap<String, String> params) {
+        SecurityContext sc = getAndValidateSecurityContext();
+        
+        Client client = getClient(params); 
+        String redirectUri = validateRedirectUri(client, params.getFirst(OAuthConstants.REDIRECT_URI)); 
+        
+        if (!OAuthUtils.isGrantSupportedForClient(client, isClientConfidential, supportedGrantType)) {
+            return createErrorResponse(params, redirectUri, OAuthConstants.UNAUTHORIZED_CLIENT);
+        }
+        String responseType = params.getFirst(OAuthConstants.RESPONSE_TYPE);
+        if (responseType == null || !responseType.equals(supportedResponseType)) {
+            return createErrorResponse(params, redirectUri, OAuthConstants.UNSUPPORTED_RESPONSE_TYPE);
+        }
+        List<String> requestedScope = OAuthUtils.parseScope(params.getFirst(OAuthConstants.SCOPE));
+        
+        UserSubject userSubject = createUserSubject(sc);
+        ServerAccessToken preauthorizedToken = getDataProvider().getPreauthorizedToken(
+            client, userSubject, supportedGrantType);
+        if (preauthorizedToken != null) {
+            return createGrant(params,
+                               client, 
+                               redirectUri,
+                               requestedScope,
+                               Collections.<String>emptyList(),
+                               userSubject,
+                               preauthorizedToken);
+        }
+        
+        List<OAuthPermission> permissions = null;
+        try {
+            permissions = getDataProvider().convertScopeToPermissions(client, requestedScope);
+        } catch (OAuthServiceException ex) {
+            return createErrorResponse(params, redirectUri, OAuthConstants.INVALID_SCOPE);
+        }
+    
+        OAuthAuthorizationData data = 
+            createAuthorizationData(client, params, permissions);
+        return Response.ok(data).build();
+        
+    }
+    
+    
+    protected OAuthAuthorizationData createAuthorizationData(
+        Client client, MultivaluedMap<String, String> params, List<OAuthPermission> perms) {
+        
+        OAuthAuthorizationData secData = new OAuthAuthorizationData();
+        
+        addAuthenticityTokenToSession(secData);
+                
+        secData.setPermissions(perms);
+        
+        StringBuilder sb = new StringBuilder();
+        for (OAuthPermission perm : perms) {
+            if (sb.length() > 0) {
+                sb.append(" ");
+            }
+            sb.append(perm.getPermission());
+        }
+        secData.setProposedScope(sb.toString());
+        
+        secData.setClientId(client.getClientId());
+        secData.setRedirectUri(params.getFirst(OAuthConstants.REDIRECT_URI));
+        secData.setState(params.getFirst(OAuthConstants.STATE));
+        
+        secData.setApplicationName(client.getApplicationName()); 
+        secData.setApplicationWebUri(client.getApplicationWebUri());
+        secData.setApplicationDescription(client.getApplicationDescription());
+        secData.setApplicationLogoUri(client.getApplicationLogoUri());
+        
+        String replyTo = getMessageContext().getUriInfo()
+            .getAbsolutePathBuilder().path("decision").build().toString();
+        secData.setReplyTo(replyTo);
+        
+        return secData;
+    }
+    
+    protected Response completeAuthorization(MultivaluedMap<String, String> params) {
+        SecurityContext securityContext = getAndValidateSecurityContext();
+        
+        if (!compareRequestAndSessionTokens(params.getFirst(OAuthConstants.SESSION_AUTHENTICITY_TOKEN))) {
+            throw new WebApplicationException(400);     
+        }
+        //TODO: additionally we can check that the Principal that got authenticated
+        // in startAuthorization is the same that got authenticated in completeAuthorization
+        
+        Client client = getClient(params);
+        String redirectUri = validateRedirectUri(client, params.getFirst(OAuthConstants.REDIRECT_URI));
+        
+        String decision = params.getFirst(OAuthConstants.AUTHORIZATION_DECISION_KEY);
+        boolean allow = OAuthConstants.AUTHORIZATION_DECISION_ALLOW.equals(decision);
+
+        if (!allow) {
+            return createErrorResponse(params, redirectUri, OAuthConstants.ACCESS_DENIED);
+        }
+        
+        List<String> requestedScope = OAuthUtils.parseScope(params.getFirst(OAuthConstants.SCOPE));
+        List<String> approvedScope = new LinkedList<String>(); 
+        for (String rScope : requestedScope) {
+            String param = params.getFirst(rScope + "_status");
+            if (param != null && OAuthConstants.AUTHORIZATION_DECISION_ALLOW.equals(param)) {
+                approvedScope.add(rScope);
+            }
+        }
+        if (!requestedScope.containsAll(approvedScope)) {
+            return createErrorResponse(params, redirectUri, OAuthConstants.INVALID_SCOPE);
+        }
+        
+        UserSubject userSubject = createUserSubject(securityContext);
+        
+        return createGrant(params,
+                           client, 
+                           redirectUri,
+                           requestedScope,
+                           approvedScope,
+                           userSubject,
+                           null);
+        
+    }
+    
+    private UserSubject createUserSubject(SecurityContext securityContext) {
+        List<String> roleNames = Collections.emptyList();
+        if (securityContext instanceof LoginSecurityContext) {
+            roleNames = new ArrayList<String>();
+            Set<Principal> roles = ((LoginSecurityContext)securityContext).getUserRoles();
+            for (Principal p : roles) {
+                roleNames.add(p.getName());
+            }
+        }
+        return 
+            new UserSubject(securityContext.getUserPrincipal().getName(), roleNames);
+    }
+    
+    protected abstract Response createErrorResponse(MultivaluedMap<String, String> params,
+                                                    String redirectUri,
+                                                    String error);
+    
+    protected abstract Response createGrant(MultivaluedMap<String, String> params,
+                                            Client client,
+                                            String redirectUri,
+                                            List<String> requestedScope,
+                                            List<String> approvedScope,
+                                            UserSubject userSubject,
+                                            ServerAccessToken preAuthorizedToken);
+    
+    private SecurityContext getAndValidateSecurityContext() {
+        SecurityContext securityContext =  
+            (SecurityContext)getMessageContext().get(SecurityContext.class.getName());
+        if (securityContext == null || securityContext.getUserPrincipal() == null) {
+            throw new WebApplicationException(401);
+        }
+        checkTransportSecurity();
+        return securityContext;
+    }
+    
+    protected String validateRedirectUri(Client client, String redirectUri) {
+        
+        List<String> uris = client.getRedirectUris();
+        if (redirectUri != null) {
+            String webUri = client.getApplicationWebUri();
+            if (uris.size() > 0 && !uris.contains(redirectUri)
+                || webUri != null && !redirectUri.startsWith(webUri)) {
+                redirectUri = null;
+            } 
+        } else if (uris.size() == 1) {
+            redirectUri = uris.get(0);
+        }
+        if (redirectUri == null) {
+            reportInvalidRequestError("Client Redirect Uri is invalid");
+        }
+        return redirectUri;
+    }
+    
+    private void addAuthenticityTokenToSession(OAuthAuthorizationData secData) {
+        HttpSession session = getMessageContext().getHttpServletRequest().getSession();
+        String value = UUID.randomUUID().toString();
+        secData.setAuthenticityToken(value);
+        session.setAttribute(OAuthConstants.SESSION_AUTHENTICITY_TOKEN, value);
+    }
+    
+    private boolean compareRequestAndSessionTokens(String requestToken) {
+        HttpSession session = getMessageContext().getHttpServletRequest().getSession();
+        String sessionToken = (String)session.getAttribute(OAuthConstants.SESSION_AUTHENTICITY_TOKEN);
+        
+        if (StringUtils.isEmpty(sessionToken)) {
+            return false;
+        }
+        
+        session.removeAttribute(OAuthConstants.SESSION_AUTHENTICITY_TOKEN);
+        return requestToken.equals(sessionToken);
+    }
+    
+}

Propchange: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/bearer/BearerAccessToken.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/bearer/BearerAccessToken.java?rev=1297971&r1=1297970&r2=1297971&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/bearer/BearerAccessToken.java (original)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/bearer/BearerAccessToken.java Wed Mar  7 13:52:46 2012
@@ -21,9 +21,18 @@ package org.apache.cxf.rs.security.oauth
 import org.apache.cxf.rs.security.oauth2.common.Client;
 import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken;
 import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
+import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils;
 
 public class BearerAccessToken extends ServerAccessToken {
     public BearerAccessToken(Client client, 
+                             long lifetime) {
+        super(client, 
+              OAuthConstants.BEARER_TOKEN_TYPE, 
+              OAuthUtils.generateRandomTokenKey(), 
+              lifetime, 
+              System.currentTimeMillis() / 1000);
+    }
+    public BearerAccessToken(Client client, 
                              String tokenKey,
                              long lifetime, 
                              long issuedAt) {

Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthConstants.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/OAuthConstants.java?rev=1297971&r1=1297970&r2=1297971&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthConstants.java (original)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthConstants.java Wed Mar  7 13:52:46 2012
@@ -38,6 +38,7 @@ public final class OAuthConstants {
     // Well-known grant types
     public static final String AUTHORIZATION_CODE_GRANT = "authorization_code";
     public static final String CLIENT_CREDENTIALS_GRANT = "client_credentials";
+    public static final String IMPLICIT_GRANT = "implicit";
     // etc
     
     // Well-known token types

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=1297971&r1=1297970&r2=1297971&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 Wed Mar  7 13:52:46 2012
@@ -18,11 +18,17 @@
  */
 package org.apache.cxf.rs.security.oauth2.utils;
 
+import java.util.LinkedList;
+import java.util.List;
+import java.util.UUID;
+
 import javax.ws.rs.core.MultivaluedMap;
 
 import org.apache.cxf.common.util.StringUtils;
 import org.apache.cxf.jaxrs.impl.MetadataMap;
 import org.apache.cxf.jaxrs.model.URITemplate;
+import org.apache.cxf.rs.security.oauth2.common.Client;
+import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException;
 
 /**
  * Various utility methods 
@@ -32,6 +38,36 @@ public final class OAuthUtils {
     private OAuthUtils() {
     }
 
+    public static boolean isGrantSupportedForClient(Client client, 
+                                                    boolean isConfidential, 
+                                                    String grantType) {
+        List<String> allowedGrants = client.getAllowedGrantTypes();
+        return isConfidential == client.isConfidential()
+            && (allowedGrants.isEmpty() || allowedGrants.contains(grantType));
+    }
+    
+    public static List<String> parseScope(String requestedScope) {
+        List<String> list = new LinkedList<String>();
+        if (requestedScope != null) {
+            String[] scopeValues = requestedScope.split(" ");
+            for (String scope : scopeValues) {
+                if (!StringUtils.isEmpty(scope)) {        
+                    list.add(scope);
+                }
+            }
+        }
+        return list;
+    }
+
+    public static String generateRandomTokenKey() throws OAuthServiceException {
+        try {
+            byte[] bytes = UUID.randomUUID().toString().getBytes("UTF-8");
+            return new MD5SequenceGenerator().generate(bytes);
+        } catch (Exception ex) {
+            throw new OAuthServiceException(OAuthConstants.SERVER_ERROR, ex);
+        }
+    }
+    
     public static boolean isExpired(Long issuedAt, Long lifetime) {
         return lifetime != -1
             && issuedAt + lifetime < System.currentTimeMillis() / 1000;