[CXF-7069] Major improvements to OAuth2 JPA2 provider and model code, patch from Adrian Gonzalez applied
Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/dba09f00 Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/dba09f00 Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/dba09f00 Branch: refs/heads/master Commit: dba09f00804cc05d943fd95d34882d6368c28edb Parents: d3900dd Author: Sergey Beryozkin <[email protected]> Authored: Fri Sep 23 16:03:15 2016 +0100 Committer: Sergey Beryozkin <[email protected]> Committed: Sun Sep 25 18:20:34 2016 +0100 ---------------------------------------------------------------------- rt/rs/security/oauth-parent/oauth2/pom.xml | 471 +++++++++++-------- .../rs/security/oauth2/common/AccessToken.java | 3 +- .../cxf/rs/security/oauth2/common/Client.java | 143 +++--- .../security/oauth2/common/OAuthPermission.java | 45 +- .../oauth2/common/ServerAccessToken.java | 120 ++--- .../rs/security/oauth2/common/UserSubject.java | 58 ++- .../grants/code/JPACMTCodeDataProvider.java | 63 +++ .../oauth2/grants/code/JPACodeDataProvider.java | 153 ++++-- .../code/ServerAuthorizationCodeGrant.java | 67 +-- .../oauth2/provider/JPAOAuthDataProvider.java | 434 ++++++++++++----- .../oauth2/tokens/refresh/RefreshToken.java | 49 +- .../rs/security/oauth2/utils/OAuthUtils.java | 3 +- .../code/JPACMTCodeDataProviderOpenJPATest.java | 43 ++ .../grants/code/JPACMTCodeDataProviderTest.java | 65 +++ .../JPACMTOAuthDataProviderOpenJPATest.java | 44 ++ .../code/JPACMTOAuthDataProviderTest.java | 67 +++ .../code/JPACodeDataProviderOpenJPATest.java | 26 + .../grants/code/JPACodeDataProviderTest.java | 55 ++- .../JPAOAuthDataProviderOpenJPATest.java | 26 + .../provider/JPAOAuthDataProviderTest.java | 163 ++++--- .../oauth2/src/test/resources/META-INF/orm.xml | 99 ---- .../src/test/resources/META-INF/persistence.xml | 101 ++-- .../grants/code/JPACMTCodeDataProvider.xml | 113 +++++ rt/rs/security/sso/oidc/pom.xml | 362 ++++++++------ .../rs/security/oidc/idp/OidcUserSubject.java | 26 +- .../idp/JPAOidcUserSubjectCMTOpenJPATest.java | 55 +++ .../oidc/idp/JPAOidcUserSubjectCMTTest.java | 55 +++ .../oidc/idp/JPAOidcUserSubjectOpenJPATest.java | 27 ++ .../oidc/idp/JPAOidcUserSubjectTest.java | 56 +-- .../src/test/resources/META-INF/persistence.xml | 95 ++-- .../oidc/idp/JPAOidcUserSubjectCMTTest.xml | 113 +++++ 31 files changed, 2145 insertions(+), 1055 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/dba09f00/rt/rs/security/oauth-parent/oauth2/pom.xml ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/pom.xml b/rt/rs/security/oauth-parent/oauth2/pom.xml index 57d109d..d4fa865 100644 --- a/rt/rs/security/oauth-parent/oauth2/pom.xml +++ b/rt/rs/security/oauth-parent/oauth2/pom.xml @@ -17,203 +17,274 @@ specific language governing permissions and limitations under the License. --> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> - <modelVersion>4.0.0</modelVersion> - <artifactId>cxf-rt-rs-security-oauth2</artifactId> - <packaging>bundle</packaging> - <name>Apache CXF Runtime OAuth 2.0</name> - <description>Apache CXF Runtime OAuth 2.0</description> - <url>http://cxf.apache.org</url> - <parent> - <artifactId>cxf-rt-rs-security-oauth-parent</artifactId> - <groupId>org.apache.cxf</groupId> - <version>3.2.0-SNAPSHOT</version> - <relativePath>../pom.xml</relativePath> - </parent> - <properties> - <cxf.osgi.import> - net.sf.ehcache*;resolution:=optional;version="[2.5, 3.0.0)", - javax.servlet*;version="${cxf.osgi.javax.servlet.version}" - </cxf.osgi.import> - <hibernate.em.version>4.1.0.Final</hibernate.em.version> - <hsqldb.version>2.3.4</hsqldb.version> - </properties> - <dependencies> - <dependency> - <groupId>org.apache.cxf</groupId> - <artifactId>cxf-rt-frontend-jaxrs</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>org.apache.cxf</groupId> - <artifactId>cxf-rt-rs-security-jose-jaxrs</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>org.apache.cxf</groupId> - <artifactId>cxf-rt-rs-client</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>${cxf.servlet-api.group}</groupId> - <artifactId>${cxf.servlet-api.artifact}</artifactId> - <scope>provided</scope> - <optional>true</optional> - </dependency> - <dependency> - <groupId>net.sf.ehcache</groupId> - <artifactId>ehcache</artifactId> - <version>${cxf.ehcache.version}</version> - <scope>provided</scope> - <optional>true</optional> - </dependency> - <dependency> - <groupId>javax.cache</groupId> - <artifactId>cache-api</artifactId> - <version>${cxf.jcache.version}</version> - <scope>provided</scope> - <optional>true</optional> - </dependency> - <dependency> - <groupId>org.apache.geronimo.specs</groupId> - <artifactId>geronimo-jpa_2.0_spec</artifactId> - <version>${cxf.geronimo.jpa.version}</version> - <scope>provided</scope> - <optional>true</optional> - </dependency> - <dependency> - <groupId>org.codehaus.jettison</groupId> - <artifactId>jettison</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.apache.cxf</groupId> - <artifactId>cxf-rt-rs-extension-providers</artifactId> - <version>${project.version}</version> - <scope>test</scope> - </dependency> - <dependency> - <groupId>junit</groupId> - <artifactId>junit</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.easymock</groupId> - <artifactId>easymock</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.hsqldb</groupId> - <artifactId>hsqldb</artifactId> - <version>${hsqldb.version}</version> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.ehcache</groupId> - <artifactId>ehcache</artifactId> - <version>${cxf.ehcache3.version}</version> - <scope>test</scope> - </dependency> - <!-- - <dependency> - <groupId>org.apache.openjpa</groupId> - <artifactId>openjpa</artifactId> - <version>${cxf.openjpa.version}</version> - <scope>provided</scope> - </dependency> - --> - <dependency> - <groupId>org.hibernate</groupId> - <artifactId>hibernate-entitymanager</artifactId> - <version>${hibernate.em.version}</version> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.slf4j</groupId> - <artifactId>slf4j-nop</artifactId> - <version>${cxf.slf4j.version}</version> - <scope>test</scope> - </dependency> - - </dependencies> - <build> - <plugins> - <plugin> - <groupId>org.bsc.maven</groupId> - <artifactId>maven-processor-plugin</artifactId> - <version>3.1.0</version> - <executions> - <execution> - <id>process</id> - <goals> - <goal>process</goal> - </goals> - <phase>generate-sources</phase> - <configuration> - <compilerArguments>-Aopenjpa.source=7 -Aopenjpa.metamodel=true</compilerArguments> - <processors> - <processor>org.apache.openjpa.persistence.meta.AnnotationProcessor6</processor> - </processors> - <outputDirectory>target/generated-sources/metamodel</outputDirectory> - </configuration> - </execution> - </executions> - <dependencies> - <dependency> - <groupId>org.apache.openjpa</groupId> - <artifactId>openjpa</artifactId> - <version>${cxf.openjpa.version}</version> - </dependency> - </dependencies> - </plugin> - <plugin> - <groupId>org.codehaus.mojo</groupId> - <artifactId>build-helper-maven-plugin</artifactId> - <version>1.10</version> - <executions> - <execution> - <id>add-source</id> - <phase>generate-sources</phase> - <goals> - <goal>add-source</goal> - </goals> - <configuration> - <sources> - <source>target/generated-sources/metamodel</source> - </sources> - </configuration> - </execution> - </executions> - </plugin> - <!-- - <plugin> - <groupId>org.apache.openjpa</groupId> - <artifactId>openjpa-maven-plugin</artifactId> - <version>${cxf.openjpa.version}</version> - <configuration> - <includes> - org/apache/cxf/rs/security/oauth2/common/Client.class, - org/apache/cxf/rs/security/oauth2/common/UserSubject.class, - org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeGrant, - org/apache/cxf/rs/security/oauth2/grants/code/ServerAuthorizationCodeGrant.class, - org/apache/cxf/rs/security/oauth2/tokens/bearer/BearerAccessToken.class, - org/apache/cxf/rs/security/oauth2/common/ServerAccessToken.class, - org/apache/cxf/rs/security/oauth2/common/AccessToken.class, - org/apache/cxf/rs/security/oauth2/tokens/refresh/RefreshToken.class, - org/apache/cxf/rs/security/oauth2/common/OAuthPermission.class - </includes> - </configuration> - <executions> - <execution> - <id>enhancer</id> - <phase>process-test-classes</phase> - <goals> - <goal>test-enhance</goal> - </goals> - </execution> - </executions> - </plugin> - --> - </plugins> - </build> - </project> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <artifactId>cxf-rt-rs-security-oauth2</artifactId> + <packaging>bundle</packaging> + <name>Apache CXF Runtime OAuth 2.0</name> + <description>Apache CXF Runtime OAuth 2.0</description> + <url>http://cxf.apache.org</url> + <parent> + <artifactId>cxf-rt-rs-security-oauth-parent</artifactId> + <groupId>org.apache.cxf</groupId> + <version>3.2.0-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + <properties> + <cxf.osgi.import> + net.sf.ehcache*;resolution:=optional;version="[2.5, 3.0.0)", + javax.servlet*;version="${cxf.osgi.javax.servlet.version}" + </cxf.osgi.import> + <hibernate.em.version>4.1.0.Final</hibernate.em.version> + <hsqldb.version>2.3.4</hsqldb.version> + </properties> + <dependencies> + <dependency> + <groupId>org.apache.cxf</groupId> + <artifactId>cxf-rt-frontend-jaxrs</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.cxf</groupId> + <artifactId>cxf-rt-rs-security-jose-jaxrs</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.cxf</groupId> + <artifactId>cxf-rt-rs-client</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>${cxf.servlet-api.group}</groupId> + <artifactId>${cxf.servlet-api.artifact}</artifactId> + <scope>provided</scope> + <optional>true</optional> + </dependency> + <dependency> + <groupId>net.sf.ehcache</groupId> + <artifactId>ehcache</artifactId> + <version>${cxf.ehcache.version}</version> + <scope>provided</scope> + <optional>true</optional> + </dependency> + <dependency> + <groupId>javax.cache</groupId> + <artifactId>cache-api</artifactId> + <version>${cxf.jcache.version}</version> + <scope>provided</scope> + <optional>true</optional> + </dependency> + <dependency> + <groupId>org.apache.geronimo.specs</groupId> + <artifactId>geronimo-jpa_2.0_spec</artifactId> + <version>${cxf.geronimo.jpa.version}</version> + <scope>provided</scope> + <optional>true</optional> + </dependency> + <dependency> + <groupId>org.codehaus.jettison</groupId> + <artifactId>jettison</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.cxf</groupId> + <artifactId>cxf-rt-rs-extension-providers</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.easymock</groupId> + <artifactId>easymock</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.hsqldb</groupId> + <artifactId>hsqldb</artifactId> + <version>${hsqldb.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.ehcache</groupId> + <artifactId>ehcache</artifactId> + <version>${cxf.ehcache3.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.openjpa</groupId> + <artifactId>openjpa</artifactId> + <version>${cxf.openjpa.version}</version> + <scope>test</scope> + <optional>true</optional> + </dependency> + <dependency> + <groupId>org.hibernate</groupId> + <artifactId>hibernate-entitymanager</artifactId> + <version>${hibernate.em.version}</version> + <scope>test</scope> + <optional>true</optional> + </dependency> + <dependency> + <groupId>org.hibernate</groupId> + <artifactId>hibernate-ehcache</artifactId> + <version>${hibernate.em.version}</version> + <scope>test</scope> + <optional>true</optional> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-nop</artifactId> + <version>${cxf.slf4j.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-aop</artifactId> + <version>${cxf.spring.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-context</artifactId> + <version>${cxf.spring.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-orm</artifactId> + <version>${cxf.spring.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-test</artifactId> + <version>${cxf.spring.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-tx</artifactId> + <version>${cxf.spring.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>jcl-over-slf4j</artifactId> + <version>${cxf.slf4j.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.aspectj</groupId> + <artifactId>aspectjweaver</artifactId> + <version>1.8.7</version> + <scope>test</scope> + </dependency> + + </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.bsc.maven</groupId> + <artifactId>maven-processor-plugin</artifactId> + <version>3.1.0</version> + <executions> + <execution> + <id>process</id> + <goals> + <goal>process</goal> + </goals> + <phase>generate-sources</phase> + <configuration> + <compilerArguments>-Aopenjpa.source=7 -Aopenjpa.metamodel=true</compilerArguments> + <processors> + <processor>org.apache.openjpa.persistence.meta.AnnotationProcessor6</processor> + </processors> + <outputDirectory>target/generated-sources/metamodel</outputDirectory> + </configuration> + </execution> + </executions> + <dependencies> + <dependency> + <groupId>org.apache.openjpa</groupId> + <artifactId>openjpa</artifactId> + <version>${cxf.openjpa.version}</version> + </dependency> + </dependencies> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <version>1.10</version> + <executions> + <execution> + <id>add-source</id> + <phase>generate-sources</phase> + <goals> + <goal>add-source</goal> + </goals> + <configuration> + <sources> + <source>target/generated-sources/metamodel</source> + </sources> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-source-plugin</artifactId> + <version>3.0.1</version> + <executions> + <execution> + <id>attach-sources</id> + <phase>verify</phase> + <goals> + <goal>jar-no-fork</goal> + </goals> + </execution> + </executions> + </plugin> + <!-- this configures the surefire plugin to run your tests with the javaagent enabled --> + <!-- (openJPA loadtime weaving) --> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <argLine>-javaagent:${project.basedir}/target/openjpa-${cxf.openjpa.version}.jar</argLine> + <workingDirectory>${project.basedir}/target</workingDirectory> + </configuration> + </plugin> + <!-- this tells maven to copy the openjpa agent jar into your target/ directory --> + <!-- where surefire can see it --> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <executions> + <execution> + <id>copy</id> + <phase>process-resources</phase> + <goals> + <goal>copy</goal> + </goals> + <configuration> + <artifactItems> + <artifactItem> + <groupId>org.apache.openjpa</groupId> + <artifactId>openjpa</artifactId> + <version>${cxf.openjpa.version}</version> + <outputDirectory>${project.build.directory}</outputDirectory> + </artifactItem> + </artifactItems> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> + http://git-wip-us.apache.org/repos/asf/cxf/blob/dba09f00/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/AccessToken.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/AccessToken.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/AccessToken.java index ade93b4..39699d4 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/AccessToken.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/AccessToken.java @@ -23,6 +23,7 @@ import java.util.LinkedHashMap; import java.util.Map; import javax.persistence.ElementCollection; +import javax.persistence.FetchType; import javax.persistence.Id; import javax.persistence.MapKeyColumn; import javax.persistence.MappedSuperclass; @@ -117,7 +118,7 @@ public abstract class AccessToken implements Serializable { * Gets token parameters * @return */ - @ElementCollection + @ElementCollection(fetch = FetchType.EAGER) @MapKeyColumn(name = "propName") public Map<String, String> getParameters() { return parameters; http://git-wip-us.apache.org/repos/asf/cxf/blob/dba09f00/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java index c465d40..5988fcd 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java @@ -26,10 +26,12 @@ import java.util.Map; import javax.persistence.ElementCollection; import javax.persistence.Entity; +import javax.persistence.FetchType; import javax.persistence.Id; import javax.persistence.ManyToOne; import javax.persistence.MapKeyColumn; import javax.persistence.OneToOne; +import javax.persistence.OrderColumn; /** @@ -37,59 +39,59 @@ import javax.persistence.OneToOne; */ @Entity public class Client implements Serializable { - + private static final long serialVersionUID = -5550840247125850922L; - + private String clientId; private String clientSecret; private String clientIpAddress; - + private String applicationName; private String applicationDescription; private String applicationWebUri; private String applicationLogoUri; private List<String> applicationCertificates = new LinkedList<String>(); private List<String> redirectUris = new LinkedList<String>(); - + private boolean isConfidential; private List<String> allowedGrantTypes = new LinkedList<String>(); private List<String> registeredScopes = new LinkedList<String>(); private List<String> registeredAudiences = new LinkedList<String>(); - + private Map<String, String> properties = new HashMap<String, String>(); private UserSubject subject; private UserSubject resourceOwnerSubject; - private long registeredAt; + private long registeredAt; private String homeRealm; - + public Client() { - + } - + public Client(String clientId, String clientSecret, boolean isConfidential) { this.clientId = clientId; this.clientSecret = clientSecret; this.isConfidential = isConfidential; } - public Client(String clientId, + public Client(String clientId, String clientSecret, boolean isConfidential, String applicationName) { this(clientId, clientSecret, isConfidential); this.applicationName = applicationName; } - - public Client(String clientId, + + public Client(String clientId, String clientSecret, boolean isConfidential, String applicationName, String applicationWebUri) { this(clientId, clientSecret, isConfidential, applicationName); this.applicationWebUri = applicationWebUri; - + } - + /** * Get the client registration id * @return the consumer key @@ -102,7 +104,7 @@ public class Client implements Serializable { public void setClientId(String id) { clientId = id; } - + /** * Get the client secret * @return the consumer key @@ -114,7 +116,7 @@ public class Client implements Serializable { public void setClientSecret(String id) { clientSecret = id; } - + /** * Get the name of the third-party application * this client represents @@ -150,6 +152,14 @@ public class Client implements Serializable { } /** + * Get the description of the third-party application. + * @return the application description + */ + public String getApplicationDescription() { + return applicationDescription; + } + + /** * Set the description of the third-party application. * @param applicationDescription the description */ @@ -158,13 +168,13 @@ public class Client implements Serializable { } /** - * Get the description of the third-party application. - * @return the application description + * Get the URI pointing to a logo image of the client application + * @return the logo URI */ - public String getApplicationDescription() { - return applicationDescription; + public String getApplicationLogoUri() { + return applicationLogoUri; } - + /** * Set the URI pointing to a logo image of the client application * @param logoPath the logo URI @@ -174,18 +184,18 @@ public class Client implements Serializable { } /** - * Get the URI pointing to a logo image of the client application - * @return the logo URI + * Get the confidentiality status of this client application. + * @return the confidentiality status */ - public String getApplicationLogoUri() { - return applicationLogoUri; + public boolean isConfidential() { + return isConfidential; } /** * Set the confidentiality status of this client application. * This can be used to restrict which OAuth2 flows this client * can participate in. - * + * * @param isConf true if the client is confidential */ public void setConfidential(boolean isConf) { @@ -193,11 +203,14 @@ public class Client implements Serializable { } /** - * Get the confidentiality status of this client application. - * @return the confidentiality status + * Get a list of URIs the AuthorizationService + * may return the authorization code to + * @return the redirect uris */ - public boolean isConfidential() { - return isConfidential; + @ElementCollection(fetch = FetchType.EAGER) + @OrderColumn + public List<String> getRedirectUris() { + return redirectUris; } /** @@ -210,13 +223,14 @@ public class Client implements Serializable { } /** - * Get a list of URIs the AuthorizationService - * may return the authorization code to - * @return the redirect uris + * Get the list of access token grant types this client + * can use to obtain the access tokens. + * @return the list of grant types */ - @ElementCollection - public List<String> getRedirectUris() { - return redirectUris; + @ElementCollection(fetch = FetchType.EAGER) + @OrderColumn + public List<String> getAllowedGrantTypes() { + return allowedGrantTypes; } /** @@ -229,21 +243,21 @@ public class Client implements Serializable { } /** - * Get the list of access token grant types this client - * can use to obtain the access tokens. - * @return the list of grant types + * Get the {@link UserSubject} representing this Client + * authentication + * @return the user subject */ - @ElementCollection - public List<String> getAllowedGrantTypes() { - return allowedGrantTypes; + @OneToOne + public UserSubject getSubject() { + return subject; } /** - * Set the {@link UserSubject} representing this Client + * Set the {@link UserSubject} representing this Client * authentication. This property may be set during the registration * in cases where a 3rd party client needs to authenticate first before * registering as OAuth2 client. This property may also wrap a clientId - * in cases where a client credentials flow is used + * in cases where a client credentials flow is used * * @param subject the user subject */ @@ -252,43 +266,31 @@ public class Client implements Serializable { } /** - * Get the {@link UserSubject} representing this Client - * authentication - * @return the user subject + * Get the {@link UserSubject} representing the resource owner + * who has registered this client + * @return the resource owner user subject */ - @OneToOne - public UserSubject getSubject() { - return subject; + @ManyToOne + public UserSubject getResourceOwnerSubject() { + return resourceOwnerSubject; } /** - * Set the {@link UserSubject} representing the resource owner + * Set the {@link UserSubject} representing the resource owner * who has registered this client. This property may be set in cases where * each account (resource) owner registers account specific Clients * - * @param subject the resource owner user subject + * @param resourceOwnerSubject the resource owner user subject */ - public void setResourceOwnerSubject(UserSubject resourceOwnerSubject) { this.resourceOwnerSubject = resourceOwnerSubject; } - - /** - * Get the {@link UserSubject} representing the resource owner - * who has registered this client - * @return the resource owner user subject - */ - @ManyToOne - public UserSubject getResourceOwnerSubject() { - return resourceOwnerSubject; - } - /** * Get the list of additional client properties * @return the list of properties */ - @ElementCollection + @ElementCollection(fetch = FetchType.EAGER) @MapKeyColumn(name = "name") public Map<String, String> getProperties() { return properties; @@ -306,7 +308,8 @@ public class Client implements Serializable { * Get the list of registered scopes * @return scopes */ - @ElementCollection + @ElementCollection(fetch = FetchType.EAGER) + @OrderColumn public List<String> getRegisteredScopes() { return registeredScopes; } @@ -316,7 +319,7 @@ public class Client implements Serializable { * Registering the scopes will allow the clients not to include the scopes * and delegate to the runtime to enforce that the current request scopes are * a subset of the pre-registered scopes. - * + * * Client Registration service is expected to reject unknown scopes. * @param registeredScopes the scopes */ @@ -324,7 +327,8 @@ public class Client implements Serializable { this.registeredScopes = registeredScopes; } - @ElementCollection + @ElementCollection(fetch = FetchType.EAGER) + @OrderColumn public List<String> getRegisteredAudiences() { return registeredAudiences; } @@ -337,7 +341,8 @@ public class Client implements Serializable { this.registeredAudiences = registeredAudiences; } - @ElementCollection + @ElementCollection(fetch = FetchType.EAGER) + @OrderColumn public List<String> getApplicationCertificates() { return applicationCertificates; } http://git-wip-us.apache.org/repos/asf/cxf/blob/dba09f00/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthPermission.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthPermission.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthPermission.java index 62a2e4c..5317c63 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthPermission.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthPermission.java @@ -22,12 +22,16 @@ import java.io.Serializable; import java.util.LinkedList; import java.util.List; +import javax.persistence.Cacheable; import javax.persistence.ElementCollection; import javax.persistence.Entity; +import javax.persistence.FetchType; import javax.persistence.Id; +import javax.persistence.OrderColumn; import javax.persistence.Transient; import javax.xml.bind.annotation.XmlRootElement; + /** * Provides the complete information about a given opaque permission. * For example, a scope parameter such as "read_calendar" will be @@ -37,6 +41,7 @@ import javax.xml.bind.annotation.XmlRootElement; */ @XmlRootElement @Entity +@Cacheable public class OAuthPermission implements Serializable { private static final long serialVersionUID = -6486616235830491290L; private List<String> httpVerbs = new LinkedList<String>(); @@ -45,20 +50,29 @@ public class OAuthPermission implements Serializable { private String description; private boolean isDefaultPermission; private boolean invisibleToClient; - public OAuthPermission() { - + } - + public OAuthPermission(String permission) { this.permission = permission; } - + public OAuthPermission(String permission, String description) { this.description = description; this.permission = permission; } - + + /** + * Gets the optional list of HTTP verbs + * @return the list of HTTP verbs + */ + @ElementCollection(fetch = FetchType.EAGER) + @OrderColumn + public List<String> getHttpVerbs() { + return httpVerbs; + } + /** * Sets the optional list of HTTP verbs, example, * "GET" and "POST", etc @@ -69,12 +83,13 @@ public class OAuthPermission implements Serializable { } /** - * Gets the optional list of HTTP verbs - * @return the list of HTTP verbs + * Gets the optional list of relative request URIs + * @return the list of URIs */ - @ElementCollection - public List<String> getHttpVerbs() { - return httpVerbs; + @ElementCollection(fetch = FetchType.EAGER) + @OrderColumn + public List<String> getUris() { + return uris; } /** @@ -85,14 +100,6 @@ public class OAuthPermission implements Serializable { this.uris = uri; } - /** - * Gets the optional list of relative request URIs - * @return the list of URIs - */ - @ElementCollection - public List<String> getUris() { - return uris; - } /** * Gets the permission description @@ -164,7 +171,6 @@ public class OAuthPermission implements Serializable { public void setInvisibleToClient(boolean invisibleToClient) { this.invisibleToClient = invisibleToClient; } - @Override public boolean equals(Object object) { if (!(object instanceof OAuthPermission)) { @@ -197,7 +203,6 @@ public class OAuthPermission implements Serializable { return true; } - @Override public int hashCode() { int hashCode = 17; http://git-wip-us.apache.org/repos/asf/cxf/blob/dba09f00/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/ServerAccessToken.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/ServerAccessToken.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/ServerAccessToken.java index e3b8b05..f758aed 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/ServerAccessToken.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/ServerAccessToken.java @@ -24,10 +24,12 @@ import java.util.List; import java.util.Map; import javax.persistence.ElementCollection; +import javax.persistence.FetchType; import javax.persistence.ManyToMany; import javax.persistence.ManyToOne; import javax.persistence.MapKeyColumn; import javax.persistence.MappedSuperclass; +import javax.persistence.OrderColumn; import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException; import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants; @@ -40,7 +42,7 @@ import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils; @MappedSuperclass public abstract class ServerAccessToken extends AccessToken { private static final long serialVersionUID = 638776204861456064L; - + private String grantType; private Client client; private List<OAuthPermission> scopes = new LinkedList<OAuthPermission>(); @@ -51,34 +53,34 @@ public abstract class ServerAccessToken extends AccessToken { private String responseType; private String grantCode; private Map<String, String> extraProperties = new LinkedHashMap<String, String>(); - + protected ServerAccessToken() { - + } - - protected ServerAccessToken(Client client, - String tokenType, - String tokenKey, - long expiresIn) { + + protected ServerAccessToken(Client client, + String tokenType, + String tokenKey, + long expiresIn) { this(client, tokenType, tokenKey, expiresIn, OAuthUtils.getIssuedAt()); } - - protected ServerAccessToken(Client client, + + protected ServerAccessToken(Client client, String tokenType, String tokenKey, - long expiresIn, + long expiresIn, long issuedAt) { super(tokenType, tokenKey, expiresIn, issuedAt); this.client = client; } - - protected ServerAccessToken(ServerAccessToken token, String key) { - super(token.getTokenType(), - key, - token.getExpiresIn(), - token.getIssuedAt(), - token.getRefreshToken(), - token.getParameters()); + + protected ServerAccessToken(ServerAccessToken token, String key) { + super(token.getTokenType(), + key, + token.getExpiresIn(), + token.getIssuedAt(), + token.getRefreshToken(), + token.getParameters()); this.client = token.getClient(); this.grantType = token.getGrantType(); this.scopes = token.getScopes(); @@ -90,6 +92,13 @@ public abstract class ServerAccessToken extends AccessToken { this.grantCode = token.getGrantCode(); } + protected static ServerAccessToken validateTokenType(ServerAccessToken token, String expectedType) { + if (!token.getTokenType().equals(expectedType)) { + throw new OAuthServiceException(OAuthConstants.SERVER_ERROR); + } + return token; + } + /** * Returns the Client associated with this token * @return the client @@ -102,12 +111,12 @@ public abstract class ServerAccessToken extends AccessToken { public void setClient(Client c) { this.client = c; } - + /** * Returns a list of opaque permissions/scopes * @return the scopes */ - @ManyToMany + @ManyToMany(fetch = FetchType.EAGER) public List<OAuthPermission> getScopes() { return scopes; } @@ -119,16 +128,6 @@ public abstract class ServerAccessToken extends AccessToken { public void setScopes(List<OAuthPermission> scopes) { this.scopes = scopes; } - - /** - * Sets a subject capturing the login name - * the end user used to login to the resource server - * when authorizing a given client request - * @param subject - */ - public void setSubject(UserSubject subject) { - this.subject = subject; - } /** * Returns a subject capturing the login name @@ -142,11 +141,13 @@ public abstract class ServerAccessToken extends AccessToken { } /** - * Sets the grant type which was used to obtain the access token - * @param grantType the grant type + * Sets a subject capturing the login name + * the end user used to login to the resource server + * when authorizing a given client request + * @param subject */ - public void setGrantType(String grantType) { - this.grantType = grantType; + public void setSubject(UserSubject subject) { + this.subject = subject; } /** @@ -156,13 +157,13 @@ public abstract class ServerAccessToken extends AccessToken { public String getGrantType() { return grantType; } - + /** - * Set the response type - * @param responseType the response type + * Sets the grant type which was used to obtain the access token + * @param grantType the grant type */ - public void setResponseType(String responseType) { - this.responseType = responseType; + public void setGrantType(String grantType) { + this.grantType = grantType; } /** @@ -172,8 +173,17 @@ public abstract class ServerAccessToken extends AccessToken { public String getResponseType() { return responseType; } - - @ElementCollection + + /** + * Set the response type + * @param responseType the response type + */ + public void setResponseType(String responseType) { + this.responseType = responseType; + } + + @ElementCollection(fetch = FetchType.EAGER) + @OrderColumn public List<String> getAudiences() { return audiences; } @@ -181,14 +191,7 @@ public abstract class ServerAccessToken extends AccessToken { public void setAudiences(List<String> audiences) { this.audiences = audiences; } - - protected static ServerAccessToken validateTokenType(ServerAccessToken token, String expectedType) { - if (!token.getTokenType().equals(expectedType)) { - throw new OAuthServiceException(OAuthConstants.SERVER_ERROR); - } - return token; - } - + public String getClientCodeVerifier() { return clientCodeVerifier; } @@ -205,7 +208,7 @@ public abstract class ServerAccessToken extends AccessToken { this.nonce = nonce; } - @ElementCollection + @ElementCollection(fetch = FetchType.EAGER) @MapKeyColumn(name = "extraPropName") public Map<String, String> getExtraProperties() { return extraProperties; @@ -214,13 +217,6 @@ public abstract class ServerAccessToken extends AccessToken { public void setExtraProperties(Map<String, String> extraProperties) { this.extraProperties = extraProperties; } - /** - * Set the grant code which was used to request the token - * @param grantCode the grant code - */ - public void setGrantCode(String grantCode) { - this.grantCode = grantCode; - } /** * Get the grant code @@ -229,4 +225,12 @@ public abstract class ServerAccessToken extends AccessToken { public String getGrantCode() { return grantCode; } + + /** + * Set the grant code which was used to request the token + * @param grantCode the grant code + */ + public void setGrantCode(String grantCode) { + this.grantCode = grantCode; + } } http://git-wip-us.apache.org/repos/asf/cxf/blob/dba09f00/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/UserSubject.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/UserSubject.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/UserSubject.java index 8bd9571..8d27148 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/UserSubject.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/UserSubject.java @@ -26,8 +26,10 @@ import java.util.Map; import javax.persistence.ElementCollection; import javax.persistence.Entity; +import javax.persistence.FetchType; import javax.persistence.Id; import javax.persistence.MapKeyColumn; +import javax.persistence.OrderColumn; import javax.xml.bind.annotation.XmlRootElement; /** @@ -37,56 +39,59 @@ import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement @Entity public class UserSubject implements Serializable { - + private static final long serialVersionUID = -1469694589163385689L; - + private String login; private String id; private List<String> roles = new LinkedList<String>(); private Map<String, String> properties = new HashMap<String, String>(); private AuthenticationMethod am; + public UserSubject() { - + } - + public UserSubject(String login) { this.login = login; } - + public UserSubject(String login, List<String> roles) { this.login = login; this.roles = roles; } - - public UserSubject(String login, String id) { + + public UserSubject(String login, String id) { this.login = login; this.id = id; } - + public UserSubject(String login, String id, List<String> roles) { this.login = login; this.id = id; this.roles = roles; } - + public UserSubject(UserSubject sub) { this(sub.getLogin(), sub.getId(), sub.getRoles()); this.properties = sub.getProperties(); this.am = sub.getAuthenticationMethod(); - + } - + /** * Return the user login name + * * @return the login name */ @Id public String getLogin() { return login; } - + /** * Set the user login name + * * @param login the login name */ public void setLogin(String login) { @@ -94,18 +99,21 @@ public class UserSubject implements Serializable { } /** - * Return the optional list of user roles which may have - * been captured during the authentication process + * Return the optional list of user roles which may have + * been captured during the authentication process + * * @return the list of roles */ - @ElementCollection + @ElementCollection(fetch = FetchType.EAGER) + @OrderColumn public List<String> getRoles() { return roles; } - + /** - * Set the optional list of user roles which may have - * been captured during the authentication process + * Set the optional list of user roles which may have + * been captured during the authentication process + * * @param roles the list of roles */ public void setRoles(List<String> roles) { @@ -114,9 +122,10 @@ public class UserSubject implements Serializable { /** * Get the list of additional user subject properties + * * @return the list of properties */ - @ElementCollection + @ElementCollection(fetch = FetchType.EAGER) @MapKeyColumn(name = "name") public Map<String, String> getProperties() { return properties; @@ -124,22 +133,25 @@ public class UserSubject implements Serializable { /** * Set the list of additional user subject properties + * * @param properties the properties */ public void setProperties(Map<String, String> properties) { this.properties = properties; } - + /** * Get the user's unique id + * * @return the user's id - */ + */ public String getId() { return this.id; } - + /** * Set the users unique id + * * @param id the user's id */ public void setId(String id) { @@ -153,5 +165,5 @@ public class UserSubject implements Serializable { public void setAuthenticationMethod(AuthenticationMethod method) { this.am = method; } - + } http://git-wip-us.apache.org/repos/asf/cxf/blob/dba09f00/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/JPACMTCodeDataProvider.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/JPACMTCodeDataProvider.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/JPACMTCodeDataProvider.java new file mode 100644 index 0000000..5eaa39a --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/JPACMTCodeDataProvider.java @@ -0,0 +1,63 @@ +/** + * 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.grants.code; + +import javax.persistence.EntityManager; +import javax.persistence.EntityTransaction; +import javax.persistence.PersistenceContext; + +public class JPACMTCodeDataProvider extends JPACodeDataProvider { + + @PersistenceContext + private EntityManager entityManager; + + /** + * Returns the entityManaged used for the current operation. + */ + @Override + protected EntityManager getEntityManager() { + return this.entityManager; + } + + public void setEntityManager(EntityManager entityManager) { + this.entityManager = entityManager; + } + + /** + * Doesn't do anything, beginning tx is handled by container. + */ + @Override + protected EntityTransaction beginIfNeeded(EntityManager em) { + return null; + } + + /** + * Doesn't do anything, commit is handled by container. + */ + @Override + protected void commitIfNeeded(EntityManager em) { + } + + /** + * Doesn't do anything, em lifecycle is handled by container. + */ + @Override + protected void closeIfNeeded(EntityManager em) { + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/dba09f00/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 9893b2e..84bfb8e 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,6 +20,8 @@ package org.apache.cxf.rs.security.oauth2.grants.code; import java.util.List; +import javax.persistence.EntityManager; +import javax.persistence.EntityNotFoundException; import javax.persistence.TypedQuery; import org.apache.cxf.rs.security.oauth2.common.Client; @@ -28,83 +30,140 @@ 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 { - private static final String CODE_TABLE_NAME = ServerAuthorizationCodeGrant.class.getSimpleName(); private long codeLifetime = 10 * 60; + @Override public ServerAuthorizationCodeGrant createCodeGrant(AuthorizationCodeRegistration reg) - throws OAuthServiceException { + throws OAuthServiceException { ServerAuthorizationCodeGrant grant = doCreateCodeGrant(reg); saveCodeGrant(grant); return grant; } - + protected ServerAuthorizationCodeGrant doCreateCodeGrant(AuthorizationCodeRegistration reg) - throws OAuthServiceException { + throws OAuthServiceException { return AbstractCodeDataProvider.initCodeGrant(reg, codeLifetime); } - protected void saveCodeGrant(ServerAuthorizationCodeGrant grant) { - getEntityManager().getTransaction().begin(); - if (grant.getSubject() != null) { - UserSubject sub = getEntityManager().find(UserSubject.class, grant.getSubject().getLogin()); - if (sub == null) { - getEntityManager().persist(grant.getSubject()); - } else { - sub = getEntityManager().merge(grant.getSubject()); - grant.setSubject(sub); + protected void saveCodeGrant(final ServerAuthorizationCodeGrant grant) { + executeInTransaction(new EntityManagerOperation<Void>() { + @Override + public Void execute(EntityManager em) { + if (grant.getSubject() != null) { + UserSubject sub = em.find(UserSubject.class, grant.getSubject().getLogin()); + if (sub == null) { + em.persist(grant.getSubject()); + } else { + sub = em.merge(grant.getSubject()); + grant.setSubject(sub); + } + } + // ensure we have a managed association + // (needed for OpenJPA : InvalidStateException: Encountered unmanaged object) + if (grant.getClient() != null) { + grant.setClient(em.find(Client.class, grant.getClient().getClientId())); + } + em.persist(grant); + return null; } - } - getEntityManager().persist(grant); - getEntityManager().getTransaction().commit(); + }); } - + @Override - protected void doRemoveClient(Client c) { - removeClientCodeGrants(c); - super.doRemoveClient(c); + protected void doRemoveClient(final Client c) { + executeInTransaction(new EntityManagerOperation<Void>() { + @Override + public Void execute(EntityManager em) { + removeClientCodeGrants(c, em); + Client clientToRemove = em.getReference(Client.class, c.getClientId()); + em.remove(clientToRemove); + return null; + } + }); } - - protected void removeClientCodeGrants(Client c) { - for (ServerAuthorizationCodeGrant grant : getCodeGrants(c, null)) { - removeCodeGrant(grant.getCode()); + + protected void removeClientCodeGrants(final Client c) { + executeInTransaction(new EntityManagerOperation<Void>() { + @Override + public Void execute(EntityManager em) { + removeClientCodeGrants(c, em); + return null; + } + }); + } + + protected void removeClientCodeGrants(final Client c, EntityManager em) { + for (ServerAuthorizationCodeGrant grant : getCodeGrants(c, null, em)) { + removeCodeGrant(grant.getCode(), em); } } - + @Override - public ServerAuthorizationCodeGrant removeCodeGrant(String code) throws OAuthServiceException { - ServerAuthorizationCodeGrant grant = getEntityManager().find(ServerAuthorizationCodeGrant.class, code); - if (grant != null) { - removeEntity(grant); - } + public ServerAuthorizationCodeGrant removeCodeGrant(final String code) throws OAuthServiceException { + return executeInTransaction(new EntityManagerOperation<ServerAuthorizationCodeGrant>() { + @Override + public ServerAuthorizationCodeGrant execute(EntityManager em) { + return removeCodeGrant(code, em); + } + }); + } + + private ServerAuthorizationCodeGrant removeCodeGrant(String code, EntityManager em) throws OAuthServiceException { + ServerAuthorizationCodeGrant grant = em.getReference(ServerAuthorizationCodeGrant.class, code); + try { + em.remove(grant); + } catch (EntityNotFoundException e) { + } return grant; } @Override - public List<ServerAuthorizationCodeGrant> getCodeGrants(Client c, UserSubject subject) - throws OAuthServiceException { - return getCodesQuery(c, subject).getResultList(); + public List<ServerAuthorizationCodeGrant> getCodeGrants(final Client c, final UserSubject subject) + throws OAuthServiceException { + return execute(new EntityManagerOperation<List<ServerAuthorizationCodeGrant>>() { + @Override + public List<ServerAuthorizationCodeGrant> execute(EntityManager em) { + return getCodeGrants(c, subject, em); + } + }); } + + private List<ServerAuthorizationCodeGrant> getCodeGrants(final Client c, final UserSubject subject, + EntityManager em) + throws OAuthServiceException { + return getCodesQuery(c, subject, em).getResultList(); + } + public void setCodeLifetime(long codeLifetime) { this.codeLifetime = codeLifetime; } - protected TypedQuery<ServerAuthorizationCodeGrant> getCodesQuery(Client c, UserSubject resourceOwnerSubject) { + + protected TypedQuery<ServerAuthorizationCodeGrant> getCodesQuery(Client c, UserSubject resourceOwnerSubject, + EntityManager em) { if (c == null && resourceOwnerSubject == null) { - return getEntityManager().createQuery("SELECT c FROM " + CODE_TABLE_NAME + " c", - ServerAuthorizationCodeGrant.class); + return em.createQuery("SELECT c FROM ServerAuthorizationCodeGrant 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); + return em.createQuery( + "SELECT c FROM ServerAuthorizationCodeGrant" + + " c JOIN c.subject s" + + " WHERE s.login = :login", ServerAuthorizationCodeGrant.class) + .setParameter("login", resourceOwnerSubject.getLogin()); } else if (resourceOwnerSubject == null) { - return getEntityManager().createQuery( - "SELECT code FROM " + CODE_TABLE_NAME + " code JOIN code.client c WHERE c.clientId = '" - + c.getClientId() + "'", ServerAuthorizationCodeGrant.class); + return em.createQuery( + "SELECT code FROM ServerAuthorizationCodeGrant code" + + " JOIN code.client c" + + " WHERE c.clientId = :clientId", ServerAuthorizationCodeGrant.class) + .setParameter("clientId", c.getClientId()); } 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); + return em.createQuery( + "SELECT code FROM ServerAuthorizationCodeGrant code" + + " JOIN code.subject s" + + " JOIN code.client c" + + " WHERE s.login = :login" + + " AND c.clientId = :clientId", ServerAuthorizationCodeGrant.class) + .setParameter("clientId", c.getClientId()) + .setParameter("login", resourceOwnerSubject.getLogin()); } } } http://git-wip-us.apache.org/repos/asf/cxf/blob/dba09f00/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 932d690..3ad5b36 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 @@ -25,8 +25,10 @@ import java.util.Map; import javax.persistence.ElementCollection; import javax.persistence.Entity; +import javax.persistence.FetchType; import javax.persistence.ManyToOne; import javax.persistence.MapKeyColumn; +import javax.persistence.OrderColumn; import org.apache.cxf.rs.security.oauth2.common.Client; import org.apache.cxf.rs.security.oauth2.common.UserSubject; @@ -39,7 +41,7 @@ import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils; @Entity public class ServerAuthorizationCodeGrant extends AuthorizationCodeGrant { private static final long serialVersionUID = -5004608901535459036L; - + private long issuedAt; private long expiresIn; private Client client; @@ -52,21 +54,21 @@ public class ServerAuthorizationCodeGrant extends AuthorizationCodeGrant { private String nonce; private boolean preauthorizedTokenAvailable; private Map<String, String> extraProperties = new LinkedHashMap<String, String>(); - + public ServerAuthorizationCodeGrant() { - + } - - public ServerAuthorizationCodeGrant(Client client, + + public ServerAuthorizationCodeGrant(Client client, long lifetime) { this(client, OAuthUtils.generateRandomTokenKey(), lifetime, - OAuthUtils.getIssuedAt()); + OAuthUtils.getIssuedAt()); } - - public ServerAuthorizationCodeGrant(Client client, - String code, - long expiresIn, - long issuedAt) { + + public ServerAuthorizationCodeGrant(Client client, + String code, + long expiresIn, + long issuedAt) { super(code); this.client = client; this.expiresIn = expiresIn; @@ -80,7 +82,7 @@ public class ServerAuthorizationCodeGrant extends AuthorizationCodeGrant { public long getIssuedAt() { return issuedAt; } - + public void setIssuedAt(long issuedAt) { this.issuedAt = issuedAt; } @@ -92,7 +94,7 @@ public class ServerAuthorizationCodeGrant extends AuthorizationCodeGrant { public long getExpiresIn() { return expiresIn; } - + public void setExpiresIn(long expiresIn) { this.expiresIn = expiresIn; } @@ -109,35 +111,27 @@ public class ServerAuthorizationCodeGrant extends AuthorizationCodeGrant { public void setClient(Client c) { this.client = c; } - - /** - * Sets the scopes explicitly approved by the end user. - * If this list is empty then the end user had no way to down-scope. - * @param approvedScope the approved scopes - */ - - public void setApprovedScopes(List<String> scopes) { - this.approvedScopes = scopes; - } /** * Gets the scopes explicitly approved by the end user * @return the approved scopes */ - @ElementCollection + @ElementCollection(fetch = FetchType.EAGER) + @OrderColumn public List<String> getApprovedScopes() { return approvedScopes; } - /** - * Sets the user subject representing the end user - * @param subject the subject + * Sets the scopes explicitly approved by the end user. + * If this list is empty then the end user had no way to down-scope. + * @param scopes the approved scopes */ - public void setSubject(UserSubject subject) { - this.subject = subject; + + public void setApprovedScopes(List<String> scopes) { + this.approvedScopes = scopes; } - + /** * Gets the user subject representing the end user * @return the subject @@ -147,6 +141,14 @@ public class ServerAuthorizationCodeGrant extends AuthorizationCodeGrant { return subject; } + /** + * Sets the user subject representing the end user + * @param subject the subject + */ + public void setSubject(UserSubject subject) { + this.subject = subject; + } + public String getAudience() { return audience; } @@ -163,7 +165,8 @@ public class ServerAuthorizationCodeGrant extends AuthorizationCodeGrant { this.clientCodeChallenge = clientCodeChallenge; } - @ElementCollection + @ElementCollection(fetch = FetchType.EAGER) + @OrderColumn public List<String> getRequestedScopes() { return requestedScopes; } @@ -188,7 +191,7 @@ public class ServerAuthorizationCodeGrant extends AuthorizationCodeGrant { this.preauthorizedTokenAvailable = preauthorizedTokenAvailable; } - @ElementCollection + @ElementCollection(fetch = FetchType.EAGER) @MapKeyColumn(name = "extraPropName") public Map<String, String> getExtraProperties() { return extraProperties;
