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 2016/04/06 16:29:48 UTC

cxf git commit: Prototyping the code for saving code grants and refresh tokens

Repository: cxf
Updated Branches:
  refs/heads/master 8bbe93f36 -> 075b4f205


Prototyping the code for saving code grants and refresh tokens


Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/075b4f20
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/075b4f20
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/075b4f20

Branch: refs/heads/master
Commit: 075b4f205ee1be622dfa37a70f832890929e5163
Parents: 8bbe93f
Author: Sergey Beryozkin <sb...@gmail.com>
Authored: Wed Apr 6 15:29:33 2016 +0100
Committer: Sergey Beryozkin <sb...@gmail.com>
Committed: Wed Apr 6 15:29:33 2016 +0100

----------------------------------------------------------------------
 .../grants/code/AuthorizationCodeGrant.java     |   6 +
 .../oauth2/grants/code/JPACodeDataProvider.java |  64 +++++-
 .../code/ServerAuthorizationCodeGrant.java      |  13 +-
 .../provider/AbstractOAuthDataProvider.java     |  13 +-
 .../oauth2/provider/JPAOAuthDataProvider.java   |  72 +++++--
 .../oauth2/tokens/refresh/RefreshToken.java     |   6 +-
 .../grants/code/JPACodeDataProviderTest.java    |  75 ++-----
 .../provider/JPAOAuthDataProviderTest.java      | 215 +++++++++++++++++++
 .../src/test/resources/META-INF/persistence.xml |   2 +
 9 files changed, 376 insertions(+), 90 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/075b4f20/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeGrant.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeGrant.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeGrant.java
index 80119f1..57a4595 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeGrant.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeGrant.java
@@ -20,6 +20,9 @@ package org.apache.cxf.rs.security.oauth2.grants.code;
 
 import java.net.URI;
 
+import javax.persistence.Id;
+import javax.persistence.MappedSuperclass;
+import javax.persistence.Transient;
 import javax.ws.rs.core.MultivaluedMap;
 
 import org.apache.cxf.jaxrs.impl.MetadataMap;
@@ -32,6 +35,7 @@ import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
  * Base Authorization Code Grant representation, captures the code 
  * and the redirect URI this code has been returned to, visible to the client
  */
+@MappedSuperclass
 public class AuthorizationCodeGrant implements AccessTokenGrant {
     private static final long serialVersionUID = -3738825769770411453L;
     private String code;
@@ -72,6 +76,7 @@ public class AuthorizationCodeGrant implements AccessTokenGrant {
      * Gets the authorization code
      * @return the code
      */
+    @Id
     public String getCode() {
         return code;
     }
@@ -83,6 +88,7 @@ public class AuthorizationCodeGrant implements AccessTokenGrant {
     /**
      * {@inheritDoc}
      */
+    @Transient
     public String getType() {
         return OAuthConstants.AUTHORIZATION_CODE_GRANT;
     }

http://git-wip-us.apache.org/repos/asf/cxf/blob/075b4f20/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/JPACodeDataProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/JPACodeDataProvider.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/JPACodeDataProvider.java
index 55b7de2..ba7a11a 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/JPACodeDataProvider.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/JPACodeDataProvider.java
@@ -20,32 +20,76 @@ package org.apache.cxf.rs.security.oauth2.grants.code;
 
 import java.util.List;
 
+import javax.persistence.NoResultException;
+import javax.persistence.TypedQuery;
+
 import org.apache.cxf.rs.security.oauth2.common.Client;
 import org.apache.cxf.rs.security.oauth2.common.UserSubject;
 import org.apache.cxf.rs.security.oauth2.provider.JPAOAuthDataProvider;
 import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException;
 
-public class JPACodeDataProvider extends JPAOAuthDataProvider 
-    implements AuthorizationCodeDataProvider {
-
+public class JPACodeDataProvider extends JPAOAuthDataProvider implements AuthorizationCodeDataProvider {
+    private static final String CODE_TABLE_NAME = ServerAuthorizationCodeGrant.class.getSimpleName();
+    private long codeLifetime = 10 * 60;
     @Override
     public ServerAuthorizationCodeGrant createCodeGrant(AuthorizationCodeRegistration reg)
         throws OAuthServiceException {
-        // TODO Auto-generated method stub
-        return null;
+        ServerAuthorizationCodeGrant grant = doCreateCodeGrant(reg);
+        saveCodeGrant(grant);
+        return grant;
+    }
+    
+    protected ServerAuthorizationCodeGrant doCreateCodeGrant(AuthorizationCodeRegistration reg)
+        throws OAuthServiceException {
+        return AbstractCodeDataProvider.initCodeGrant(reg, codeLifetime);
     }
 
+    protected void saveCodeGrant(ServerAuthorizationCodeGrant grant) { 
+        persistEntity(grant);
+    }
+    
     @Override
     public ServerAuthorizationCodeGrant removeCodeGrant(String code) throws OAuthServiceException {
-        // TODO Auto-generated method stub
-        return null;
+        try {
+            ServerAuthorizationCodeGrant grant = getCodeQuery(code).getSingleResult();
+            removeEntity(grant);
+            return grant;
+        } catch (NoResultException ex) {
+            return null;
+        }
     }
 
     @Override
     public List<ServerAuthorizationCodeGrant> getCodeGrants(Client c, UserSubject subject)
         throws OAuthServiceException {
-        // TODO Auto-generated method stub
-        return null;
+        return getCodesQuery(c, subject).getResultList();
+    }
+    public void setCodeLifetime(long codeLifetime) {
+        this.codeLifetime = codeLifetime;
+    }
+    protected TypedQuery<ServerAuthorizationCodeGrant> getCodeQuery(String code) {
+        return getEntityManager().createQuery(
+            "SELECT c FROM " + CODE_TABLE_NAME + " c WHERE c.code = '" + code + "'", 
+            ServerAuthorizationCodeGrant.class);
+    }
+    protected TypedQuery<ServerAuthorizationCodeGrant> getCodesQuery(Client c, UserSubject resourceOwnerSubject) {
+        if (c == null && resourceOwnerSubject == null) {
+            return getEntityManager().createQuery("SELECT c FROM " + CODE_TABLE_NAME + " c", 
+                                             ServerAuthorizationCodeGrant.class);
+        } else if (c == null) {
+            return getEntityManager().createQuery(
+                "SELECT c FROM " + CODE_TABLE_NAME + " c JOIN c.subject s WHERE s.login = '" 
+                + resourceOwnerSubject.getLogin() + "'", ServerAuthorizationCodeGrant.class);
+        } else if (resourceOwnerSubject == null) {
+            return getEntityManager().createQuery(
+                "SELECT code FROM " + CODE_TABLE_NAME + " code JOIN code.cliednt c WHERE c.clientId = '" 
+                    + c.getClientId() + "'", ServerAuthorizationCodeGrant.class);
+        } else {
+            return getEntityManager().createQuery(
+                "SELECT code FROM " + CODE_TABLE_NAME 
+                + " code JOIN code.subject s JOIN code.client c WHERE s.login = '" 
+                + resourceOwnerSubject.getLogin() + "' AND c.clientId = '" + c.getClientId() + "'",
+                ServerAuthorizationCodeGrant.class);
+        }
     }
-
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/075b4f20/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/ServerAuthorizationCodeGrant.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/ServerAuthorizationCodeGrant.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/ServerAuthorizationCodeGrant.java
index d345fb2..97f8e1f 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/ServerAuthorizationCodeGrant.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/ServerAuthorizationCodeGrant.java
@@ -23,6 +23,11 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
+import javax.persistence.ElementCollection;
+import javax.persistence.Entity;
+import javax.persistence.MapKeyColumn;
+import javax.persistence.OneToOne;
+
 import org.apache.cxf.rs.security.oauth2.common.Client;
 import org.apache.cxf.rs.security.oauth2.common.UserSubject;
 import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils;
@@ -31,6 +36,7 @@ import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils;
 /**
  * The Authorization Code Grant representation visible to the server
  */
+@Entity
 public class ServerAuthorizationCodeGrant extends AuthorizationCodeGrant {
     private static final long serialVersionUID = -5004608901535459036L;
     
@@ -94,6 +100,7 @@ public class ServerAuthorizationCodeGrant extends AuthorizationCodeGrant {
      * Returns the reference to {@link Client}
      * @return the client
      */
+    @OneToOne
     public Client getClient() {
         return client;
     }
@@ -116,7 +123,7 @@ public class ServerAuthorizationCodeGrant extends AuthorizationCodeGrant {
      * Gets the scopes explicitly approved by the end user
      * @return the approved scopes
      */
-    
+    @ElementCollection
     public List<String> getApprovedScopes() {
         return approvedScopes;
     }
@@ -134,6 +141,7 @@ public class ServerAuthorizationCodeGrant extends AuthorizationCodeGrant {
      * Gets the user subject representing the end user
      * @return the subject
      */
+    @OneToOne
     public UserSubject getSubject() {
         return subject;
     }
@@ -154,6 +162,7 @@ public class ServerAuthorizationCodeGrant extends AuthorizationCodeGrant {
         this.clientCodeChallenge = clientCodeChallenge;
     }
 
+    @ElementCollection
     public List<String> getRequestedScopes() {
         return requestedScopes;
     }
@@ -178,6 +187,8 @@ public class ServerAuthorizationCodeGrant extends AuthorizationCodeGrant {
         this.preauthorizedTokenAvailable = preauthorizedTokenAvailable;
     }
 
+    @ElementCollection
+    @MapKeyColumn(name = "extraPropName")
     public Map<String, String> getExtraProperties() {
         return extraProperties;
     }

http://git-wip-us.apache.org/repos/asf/cxf/blob/075b4f20/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java
index 827a0c3..c971985 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java
@@ -21,6 +21,7 @@ package org.apache.cxf.rs.security.oauth2.provider;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 
@@ -225,9 +226,17 @@ public abstract class AbstractOAuthDataProvider implements OAuthDataProvider, Cl
     }
     protected RefreshToken doCreateNewRefreshToken(ServerAccessToken at) {
         RefreshToken rt = new RefreshToken(at.getClient(), refreshTokenLifetime);
-        rt.setAudiences(at.getAudiences());
+        if (at.getAudiences() != null) {
+            List<String> audiences = new LinkedList<String>();
+            audiences.addAll(at.getAudiences());
+            rt.setAudiences(audiences);
+        }
         rt.setGrantType(at.getGrantType());
-        rt.setScopes(at.getScopes());
+        if (at.getScopes() != null) {
+            List<OAuthPermission> scopes = new LinkedList<OAuthPermission>();
+            scopes.addAll(at.getScopes());
+            rt.setScopes(scopes);
+        }
         rt.setSubject(at.getSubject());
         rt.setClientCodeVerifier(at.getClientCodeVerifier());
         linkRefreshAccessTokens(rt, at);

http://git-wip-us.apache.org/repos/asf/cxf/blob/075b4f20/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/JPAOAuthDataProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/JPAOAuthDataProvider.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/JPAOAuthDataProvider.java
index 4045f91..bc9db23 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/JPAOAuthDataProvider.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/JPAOAuthDataProvider.java
@@ -18,7 +18,6 @@
  */
 package org.apache.cxf.rs.security.oauth2.provider;
 
-import java.util.Collections;
 import java.util.List;
 
 import javax.persistence.EntityExistsException;
@@ -35,7 +34,7 @@ import org.apache.cxf.rs.security.oauth2.tokens.refresh.RefreshToken;
 public class JPAOAuthDataProvider extends AbstractOAuthDataProvider {
     private static final String CLIENT_TABLE_NAME = Client.class.getSimpleName();
     private static final String BEARER_TOKEN_TABLE_NAME = BearerAccessToken.class.getSimpleName();
-    private static final String REFRESH_TOKEN_TABLE_NAME = BearerAccessToken.class.getSimpleName();
+    private static final String REFRESH_TOKEN_TABLE_NAME = RefreshToken.class.getSimpleName();
     private EntityManager entityManager;
     
     public JPAOAuthDataProvider() {
@@ -51,7 +50,7 @@ public class JPAOAuthDataProvider extends AbstractOAuthDataProvider {
     }
     
     public void setClient(Client client) {
-        persistEntity(client.getResourceOwnerSubject());
+        persistEntityWithPossibleRollback(client.getResourceOwnerSubject());
         persistEntity(client);
     }
     
@@ -67,12 +66,12 @@ public class JPAOAuthDataProvider extends AbstractOAuthDataProvider {
 
     @Override
     public List<ServerAccessToken> getAccessTokens(Client c, UserSubject sub) {
-        return Collections.emptyList();
+        return getTokensQuery(c, sub).getResultList();
     }
 
     @Override
     public List<RefreshToken> getRefreshTokens(Client c, UserSubject sub) {
-        return Collections.emptyList();
+        return getRefreshTokensQuery(c, sub).getResultList();
     }
     
     @Override
@@ -105,8 +104,9 @@ public class JPAOAuthDataProvider extends AbstractOAuthDataProvider {
     }
     
     protected void saveRefreshToken(ServerAccessToken at, RefreshToken refreshToken) {
+        persistEntity(refreshToken);
     }
-    protected void persistEntity(Object entity) {
+    protected void persistEntityWithPossibleRollback(Object entity) {
         try {
             entityManager.getTransaction().begin();
             entityManager.persist(entity);
@@ -115,6 +115,11 @@ public class JPAOAuthDataProvider extends AbstractOAuthDataProvider {
             entityManager.getTransaction().rollback();
         }
     }
+    protected void persistEntity(Object entity) {
+        entityManager.getTransaction().begin();
+        entityManager.persist(entity);
+        entityManager.getTransaction().commit();
+    }
     protected void removeEntity(Object entity) {
         entityManager.getTransaction().begin();
         entityManager.remove(entity);
@@ -124,28 +129,69 @@ public class JPAOAuthDataProvider extends AbstractOAuthDataProvider {
         return entityManager.createQuery(
             "SELECT c FROM " + CLIENT_TABLE_NAME + " c WHERE c.clientId = '" + clientId + "'", Client.class);
     }
-    protected TypedQuery<ServerAccessToken> getTokenQuery(String tokenKey) {
+    protected TypedQuery<Client> getClientsQuery(UserSubject resourceOwnerSubject) {
+        if (resourceOwnerSubject == null) {
+            return entityManager.createQuery("SELECT c FROM " + CLIENT_TABLE_NAME + " c", Client.class);
+        } else {
+            return entityManager.createQuery(
+                "SELECT c FROM " + CLIENT_TABLE_NAME + " c JOIN c.resourceOwnerSubject r WHERE r.login = '" 
+                + resourceOwnerSubject.getLogin() + "'", Client.class);
+        }
+    }
+    protected TypedQuery<BearerAccessToken> getTokenQuery(String tokenKey) {
         return entityManager.createQuery(
             "SELECT t FROM " + BEARER_TOKEN_TABLE_NAME + " t WHERE t.tokenKey = '" + tokenKey + "'", 
-            ServerAccessToken.class);
+            BearerAccessToken.class);
+    }
+    protected TypedQuery<ServerAccessToken> getTokensQuery(Client c, UserSubject resourceOwnerSubject) {
+        if (c == null && resourceOwnerSubject == null) {
+            return entityManager.createQuery("SELECT t FROM " + BEARER_TOKEN_TABLE_NAME + " t", 
+                                             ServerAccessToken.class);
+        } else if (c == null) {
+            return entityManager.createQuery(
+                "SELECT t FROM " + BEARER_TOKEN_TABLE_NAME + " t JOIN t.subject s WHERE s.login = '" 
+                + resourceOwnerSubject.getLogin() + "'", ServerAccessToken.class);
+        } else if (resourceOwnerSubject == null) {
+            return entityManager.createQuery(
+                "SELECT t FROM " + BEARER_TOKEN_TABLE_NAME + " t JOIN t.client c WHERE c.clientId = '" 
+                    + c.getClientId() + "'", ServerAccessToken.class);
+        } else {
+            return entityManager.createQuery(
+                "SELECT t FROM " + BEARER_TOKEN_TABLE_NAME + " t JOIN t.subject s JOIN t.client c WHERE s.login = '" 
+                + resourceOwnerSubject.getLogin() + "' AND c.clientId = '" + c.getClientId() + "'",
+                ServerAccessToken.class);
+        }
     }
     protected TypedQuery<RefreshToken> getRefreshTokenQuery(String tokenKey) {
         return entityManager.createQuery(
             "SELECT t FROM " + REFRESH_TOKEN_TABLE_NAME + " t WHERE t.tokenKey = '" + tokenKey + "'", 
             RefreshToken.class);
     }
-    protected TypedQuery<Client> getClientsQuery(UserSubject resourceOwnerSubject) {
-        if (resourceOwnerSubject == null) {
-            return entityManager.createQuery("SELECT c FROM " + CLIENT_TABLE_NAME + " c", Client.class);
+    protected TypedQuery<RefreshToken> getRefreshTokensQuery(Client c, UserSubject resourceOwnerSubject) {
+        if (c == null && resourceOwnerSubject == null) {
+            return entityManager.createQuery("SELECT t FROM " + REFRESH_TOKEN_TABLE_NAME + " t", 
+                                             RefreshToken.class);
+        } else if (c == null) {
+            return entityManager.createQuery(
+                "SELECT t FROM " + REFRESH_TOKEN_TABLE_NAME + " t JOIN t.subject s WHERE s.login = '" 
+                + resourceOwnerSubject.getLogin() + "'", RefreshToken.class);
+        } else if (resourceOwnerSubject == null) {
+            return entityManager.createQuery(
+                "SELECT t FROM " + REFRESH_TOKEN_TABLE_NAME + " t JOIN t.client c WHERE c.clientId = '" 
+                    + c.getClientId() + "'", RefreshToken.class);
         } else {
             return entityManager.createQuery(
-                "SELECT c FROM " + CLIENT_TABLE_NAME + " c JOIN c.resourceOwnerSubject r WHERE r.login = '" 
-                + resourceOwnerSubject.getLogin() + "'", Client.class);
+                "SELECT t FROM " + REFRESH_TOKEN_TABLE_NAME + " t JOIN t.subject s JOIN t.client c WHERE s.login = '" 
+                + resourceOwnerSubject.getLogin() + "' AND c.clientId = '" + c.getClientId() + "'",
+                RefreshToken.class);
         }
     }
     public void setEntityManager(EntityManager entityManager) {
         this.entityManager = entityManager;
     }
+    public EntityManager getEntityManager() {
+        return entityManager;
+    }
     @Override
     public void close() {
         entityManager.close();

http://git-wip-us.apache.org/repos/asf/cxf/blob/075b4f20/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/refresh/RefreshToken.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/refresh/RefreshToken.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/refresh/RefreshToken.java
index 5bcf8ed..2d1caad 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/refresh/RefreshToken.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/refresh/RefreshToken.java
@@ -21,6 +21,9 @@ package org.apache.cxf.rs.security.oauth2.tokens.refresh;
 import java.util.LinkedList;
 import java.util.List;
 
+import javax.persistence.ElementCollection;
+import javax.persistence.Entity;
+
 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;
@@ -29,6 +32,7 @@ import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils;
 /**
  * Simple Refresh Token implementation
  */
+@Entity
 public class RefreshToken extends ServerAccessToken {
     
     private static final long serialVersionUID = 2837120382251693874L;
@@ -63,7 +67,7 @@ public class RefreshToken extends ServerAccessToken {
     public RefreshToken() {
         
     }
-    
+    @ElementCollection
     public List<String> getAccessTokens() {
         return accessTokens;
     }

http://git-wip-us.apache.org/repos/asf/cxf/blob/075b4f20/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/grants/code/JPACodeDataProviderTest.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/grants/code/JPACodeDataProviderTest.java b/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/grants/code/JPACodeDataProviderTest.java
index 9cf80e5..8bb74aa 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/grants/code/JPACodeDataProviderTest.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/grants/code/JPACodeDataProviderTest.java
@@ -27,12 +27,8 @@ import javax.persistence.EntityManager;
 import javax.persistence.EntityManagerFactory;
 import javax.persistence.Persistence;
 
-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;
-import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
 
 import org.junit.After;
 import org.junit.Assert;
@@ -65,61 +61,23 @@ public class JPACodeDataProviderTest extends Assert {
     }
 
     @Test
-    public void testAddGetDeleteClient() {
-        Client c = addClient("12345", "alice");
-        Client c2 = provider.getClient(c.getClientId());
-        compareClients(c, c2);
+    public void testAddGetDeleteCodeGrants() {
+        Client c = addClient("111", "bob");
         
-        provider.removeClient(c.getClientId());
-        Client c3 = provider.getClient(c.getClientId());
-        assertNull(c3);
-    }
-    
-    @Test
-    public void testAddGetDeleteClients() {
-        Client c = addClient("12345", "alice");
-        Client c2 = addClient("56789", "alice");
-        Client c3 = addClient("09876", "bob");
-        
-        List<Client> aliceClients = provider.getClients(new UserSubject("alice"));
-        assertNotNull(aliceClients);
-        assertEquals(2, aliceClients.size());
-        compareClients(c, aliceClients.get(0).getClientId().equals("12345") 
-                       ? aliceClients.get(0) : aliceClients.get(1));
-        compareClients(c2, aliceClients.get(0).getClientId().equals("56789") 
-                       ? aliceClients.get(0) : aliceClients.get(1));
-        
-        List<Client> bobClients = provider.getClients(new UserSubject("bob"));
-        assertNotNull(bobClients);
-        assertEquals(1, bobClients.size());
-        Client bobClient = bobClients.get(0);
-        compareClients(c3, bobClient);
-        
-        List<Client> allClients = provider.getClients(null);
-        assertNotNull(allClients);
-        assertEquals(3, allClients.size());
-        
-    }
-    
-    @Test
-    public void testAddGetDeleteAccessToken() {
-        Client c = addClient("101", "bob");
-        
-        AccessTokenRegistration atr = new AccessTokenRegistration();
+        AuthorizationCodeRegistration atr = new AuthorizationCodeRegistration();
         atr.setClient(c);
         atr.setApprovedScope(Collections.singletonList("a"));
         atr.setSubject(c.getResourceOwnerSubject());
         
-        ServerAccessToken at = provider.createAccessToken(atr);
-        ServerAccessToken at2 = provider.getAccessToken(at.getTokenKey());
-        assertEquals(at.getTokenKey(), at2.getTokenKey());
-        List<OAuthPermission> scopes = at2.getScopes();
-        assertNotNull(scopes);
-        assertEquals(1, scopes.size());
-        OAuthPermission perm = scopes.get(0);
-        assertEquals("a", perm.getPermission());
-        provider.revokeToken(c, at.getTokenKey(), OAuthConstants.ACCESS_TOKEN);
-        assertNull(provider.getAccessToken(at.getTokenKey()));
+        ServerAuthorizationCodeGrant grant = provider.createCodeGrant(atr);
+        
+        List<ServerAuthorizationCodeGrant> grants = provider.getCodeGrants(c, c.getResourceOwnerSubject());
+        assertNotNull(grants);
+        assertEquals(1, grants.size());
+        assertEquals(grant.getCode(), grants.get(0).getCode());
+        
+        ServerAuthorizationCodeGrant grant2 = provider.removeCodeGrant(grant.getCode());
+        assertEquals(grant.getCode(), grant2.getCode());
     }
     
     private Client addClient(String clientId, String userLogin) {
@@ -130,15 +88,6 @@ public class JPACodeDataProviderTest extends Assert {
         provider.setClient(c);
         return c;
     }
-    private void compareClients(Client c, Client c2) {
-        assertNotNull(c2);
-        assertEquals(c.getClientId(), c2.getClientId());
-        assertEquals(1, c.getRedirectUris().size());
-        assertEquals(1, c2.getRedirectUris().size());
-        assertEquals("http://client/redirect", c.getRedirectUris().get(0));
-        assertEquals(c.getResourceOwnerSubject().getLogin(), c2.getResourceOwnerSubject().getLogin());
-    }
-    
     @After
     public void tearDown() throws Exception {
         try {

http://git-wip-us.apache.org/repos/asf/cxf/blob/075b4f20/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/provider/JPAOAuthDataProviderTest.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/provider/JPAOAuthDataProviderTest.java b/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/provider/JPAOAuthDataProviderTest.java
new file mode 100644
index 0000000..25d981e
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/provider/JPAOAuthDataProviderTest.java
@@ -0,0 +1,215 @@
+/**
+ * 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 java.sql.Connection;
+import java.sql.DriverManager;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+
+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;
+import org.apache.cxf.rs.security.oauth2.tokens.refresh.RefreshToken;
+import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class JPAOAuthDataProviderTest extends Assert {
+    private EntityManagerFactory emFactory;
+    private Connection connection;
+    private JPAOAuthDataProvider provider;
+    @Before
+    public void setUp() throws Exception {
+        try {
+            Class.forName("org.hsqldb.jdbcDriver");
+            connection = DriverManager.getConnection("jdbc:hsqldb:mem:oauth-jpa", "sa", "");
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            fail("Exception during HSQL database init.");
+        }
+        try {
+            emFactory = Persistence.createEntityManagerFactory("testUnitHibernate");
+            EntityManager em = emFactory.createEntityManager();
+            provider = new JPAOAuthDataProvider();
+            provider.setEntityManager(em);
+            provider.setSupportedScopes(Collections.singletonMap("a", "A Scope"));
+            provider.setSupportedScopes(Collections.singletonMap("refreshToken", "RefreshToken"));
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            fail("Exception during JPA EntityManager creation.");
+        }
+    }
+
+    @Test
+    public void testAddGetDeleteClient() {
+        Client c = addClient("12345", "alice");
+        Client c2 = provider.getClient(c.getClientId());
+        compareClients(c, c2);
+        
+        provider.removeClient(c.getClientId());
+        Client c3 = provider.getClient(c.getClientId());
+        assertNull(c3);
+    }
+    
+    @Test
+    public void testAddGetDeleteClients() {
+        Client c = addClient("12345", "alice");
+        Client c2 = addClient("56789", "alice");
+        Client c3 = addClient("09876", "bob");
+        
+        List<Client> aliceClients = provider.getClients(new UserSubject("alice"));
+        assertNotNull(aliceClients);
+        assertEquals(2, aliceClients.size());
+        compareClients(c, aliceClients.get(0).getClientId().equals("12345") 
+                       ? aliceClients.get(0) : aliceClients.get(1));
+        compareClients(c2, aliceClients.get(0).getClientId().equals("56789") 
+                       ? aliceClients.get(0) : aliceClients.get(1));
+        
+        List<Client> bobClients = provider.getClients(new UserSubject("bob"));
+        assertNotNull(bobClients);
+        assertEquals(1, bobClients.size());
+        Client bobClient = bobClients.get(0);
+        compareClients(c3, bobClient);
+        
+        List<Client> allClients = provider.getClients(null);
+        assertNotNull(allClients);
+        assertEquals(3, allClients.size());
+        
+    }
+    
+    @Test
+    public void testAddGetDeleteAccessToken() {
+        Client c = addClient("101", "bob");
+        
+        AccessTokenRegistration atr = new AccessTokenRegistration();
+        atr.setClient(c);
+        atr.setApprovedScope(Collections.singletonList("a"));
+        atr.setSubject(c.getResourceOwnerSubject());
+        
+        ServerAccessToken at = provider.createAccessToken(atr);
+        ServerAccessToken at2 = provider.getAccessToken(at.getTokenKey());
+        assertEquals(at.getTokenKey(), at2.getTokenKey());
+        List<OAuthPermission> scopes = at2.getScopes();
+        assertNotNull(scopes);
+        assertEquals(1, scopes.size());
+        OAuthPermission perm = scopes.get(0);
+        assertEquals("a", perm.getPermission());
+        
+        List<ServerAccessToken> tokens = provider.getAccessTokens(c, c.getResourceOwnerSubject());
+        assertNotNull(tokens);
+        assertEquals(1, tokens.size());
+        assertEquals(at.getTokenKey(), tokens.get(0).getTokenKey());
+        
+        tokens = provider.getAccessTokens(null, c.getResourceOwnerSubject());
+        assertNotNull(tokens);
+        assertEquals(1, tokens.size());
+        assertEquals(at.getTokenKey(), tokens.get(0).getTokenKey());
+        
+        tokens = provider.getAccessTokens(null, null);
+        assertNotNull(tokens);
+        assertEquals(1, tokens.size());
+        assertEquals(at.getTokenKey(), tokens.get(0).getTokenKey());
+        
+        provider.revokeToken(c, at.getTokenKey(), OAuthConstants.ACCESS_TOKEN);
+        assertNull(provider.getAccessToken(at.getTokenKey()));
+    }
+    
+    @Test
+    public void testAddGetDeleteRefreshToken() {
+        Client c = addClient("101", "bob");
+        
+        AccessTokenRegistration atr = new AccessTokenRegistration();
+        atr.setClient(c);
+        atr.setApprovedScope(Arrays.asList("a", "refreshToken"));
+        atr.setSubject(c.getResourceOwnerSubject());
+        
+        ServerAccessToken at = provider.createAccessToken(atr);
+        ServerAccessToken at2 = provider.getAccessToken(at.getTokenKey());
+        assertEquals(at.getTokenKey(), at2.getTokenKey());
+        List<OAuthPermission> scopes = at2.getScopes();
+        assertNotNull(scopes);
+        assertEquals(2, scopes.size());
+        OAuthPermission perm = scopes.get(0);
+        assertEquals("a", perm.getPermission());
+        OAuthPermission perm2 = scopes.get(1);
+        assertEquals("refreshToken", perm2.getPermission());
+        
+        RefreshToken rt = provider.getRefreshToken(at2.getRefreshToken());
+        assertNotNull(rt);
+        assertEquals(at2.getTokenKey(), rt.getAccessTokens().get(0));
+        
+        List<RefreshToken> tokens = provider.getRefreshTokens(c, c.getResourceOwnerSubject());
+        assertNotNull(tokens);
+        assertEquals(1, tokens.size());
+        assertEquals(rt.getTokenKey(), tokens.get(0).getTokenKey());
+        
+        provider.revokeToken(c, rt.getTokenKey(), OAuthConstants.REFRESH_TOKEN);
+        
+        assertNull(provider.getRefreshToken(rt.getTokenKey()));
+    }
+    
+    private Client addClient(String clientId, String userLogin) {
+        Client c = new Client();
+        c.setRedirectUris(Collections.singletonList("http://client/redirect"));
+        c.setClientId(clientId);
+        c.setResourceOwnerSubject(new UserSubject(userLogin));
+        provider.setClient(c);
+        return c;
+    }
+    private void compareClients(Client c, Client c2) {
+        assertNotNull(c2);
+        assertEquals(c.getClientId(), c2.getClientId());
+        assertEquals(1, c.getRedirectUris().size());
+        assertEquals(1, c2.getRedirectUris().size());
+        assertEquals("http://client/redirect", c.getRedirectUris().get(0));
+        assertEquals(c.getResourceOwnerSubject().getLogin(), c2.getResourceOwnerSubject().getLogin());
+    }
+    
+    @After
+    public void tearDown() throws Exception {
+        try {
+            if (provider != null) {
+                provider.close();
+            }
+            if (emFactory != null) {
+                emFactory.close();
+            }
+        } catch (Throwable ex) {
+            ex.printStackTrace();    
+        } finally {    
+            try {
+                connection.createStatement().execute("SHUTDOWN");
+            } catch (Throwable ex) {
+                ex.printStackTrace();
+            }
+        }
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/075b4f20/rt/rs/security/oauth-parent/oauth2/src/test/resources/META-INF/persistence.xml
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/test/resources/META-INF/persistence.xml b/rt/rs/security/oauth-parent/oauth2/src/test/resources/META-INF/persistence.xml
index eb413f0..7d6193b 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/test/resources/META-INF/persistence.xml
+++ b/rt/rs/security/oauth-parent/oauth2/src/test/resources/META-INF/persistence.xml
@@ -8,6 +8,7 @@
      <class>org.apache.cxf.rs.security.oauth2.common.UserSubject</class>
      <class>org.apache.cxf.rs.security.oauth2.tokens.bearer.BearerAccessToken</class>
      <class>org.apache.cxf.rs.security.oauth2.tokens.refresh.RefreshToken</class>
+     <class>org.apache.cxf.rs.security.oauth2.grants.code.ServerAuthorizationCodeGrant</class>
      <exclude-unlisted-classes>true</exclude-unlisted-classes>
      <properties>
         <property name="hibernate.connection.url" value="jdbc:hsqldb:mem:oauth-jpa"/>
@@ -25,6 +26,7 @@
      <class>org.apache.cxf.rs.security.oauth2.common.UserSubject</class>
      <class>org.apache.cxf.rs.security.oauth2.tokens.bearer.BearerAccessToken</class>
      <class>org.apache.cxf.rs.security.oauth2.tokens.refresh.RefreshToken</class>
+     <class>org.apache.cxf.rs.security.oauth2.grants.code.ServerAuthorizationCodeGrant</class>
      <exclude-unlisted-classes>true</exclude-unlisted-classes>
      <properties>
         <property name="openjpa.ConnectionURL" value="jdbc:hsqldb:mem:oauth-jpa"/>