Repository: cxf Updated Branches: refs/heads/master e9d6f160f -> 4915ce370
Making OAuth2 module depend on JOSE Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/4915ce37 Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/4915ce37 Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/4915ce37 Branch: refs/heads/master Commit: 4915ce370e5f1905f77ebecc8883cc86fcc3e4f4 Parents: e9d6f16 Author: Sergey Beryozkin <[email protected]> Authored: Fri Nov 7 14:16:46 2014 +0000 Committer: Sergey Beryozkin <[email protected]> Committed: Fri Nov 7 14:16:46 2014 +0000 ---------------------------------------------------------------------- .../features/src/main/resources/features.xml | 8 +- rt/pom.xml | 2 +- .../cxf/rs/security/jose/jws/JwsUtils.java | 4 + rt/rs/security/oauth-parent/oauth2-jose/pom.xml | 56 --------- .../jose/jwt/grant/AbstractJwtBearerGrant.java | 69 ----------- .../jose/jwt/grant/AbstractJwtHandler.java | 100 --------------- .../rs/security/jose/jwt/grant/Constants.java | 33 ----- .../grant/JwtBearerClientCredentialsGrant.java | 41 ------- .../security/jose/jwt/grant/JwtBearerGrant.java | 48 -------- .../jose/jwt/grant/JwtBearerGrantHandler.java | 91 -------------- .../security/jose/jwt/grant/JwtUserSubject.java | 34 ----- .../jose/jwt/token/JwtAccessTokenUtils.java | 123 ------------------- .../jose/jwt/grant/JwtUserSubjectTest.java | 32 ----- rt/rs/security/oauth-parent/oauth2/pom.xml | 12 +- .../grants/jwt/AbstractJwtBearerGrant.java | 69 +++++++++++ .../oauth2/grants/jwt/AbstractJwtHandler.java | 100 +++++++++++++++ .../security/oauth2/grants/jwt/Constants.java | 33 +++++ .../jwt/JwtBearerClientCredentialsGrant.java | 41 +++++++ .../oauth2/grants/jwt/JwtBearerGrant.java | 48 ++++++++ .../grants/jwt/JwtBearerGrantHandler.java | 91 ++++++++++++++ .../oauth2/grants/jwt/JwtUserSubject.java | 34 +++++ .../utils/crypto/JwtAccessTokenUtils.java | 119 ++++++++++++++++++ .../oauth2/grants/jwt/JwtUserSubjectTest.java | 32 +++++ rt/rs/security/oauth-parent/pom.xml | 1 - 24 files changed, 581 insertions(+), 640 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/4915ce37/osgi/karaf/features/src/main/resources/features.xml ---------------------------------------------------------------------- diff --git a/osgi/karaf/features/src/main/resources/features.xml b/osgi/karaf/features/src/main/resources/features.xml index 7393641..ade817d 100644 --- a/osgi/karaf/features/src/main/resources/features.xml +++ b/osgi/karaf/features/src/main/resources/features.xml @@ -201,14 +201,14 @@ <bundle start-level="30" dependency="true">mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.oauth-provider/${cxf.oauth.bundle.version}</bundle> <bundle start-level="40">mvn:org.apache.cxf/cxf-rt-rs-security-oauth/${project.version}</bundle> </feature> - <feature name="cxf-rs-security-oauth2" version="${project.version}" resolver="(obr)"> - <feature version="${project.version}">cxf-jaxrs</feature> - <bundle start-level="40">mvn:org.apache.cxf/cxf-rt-rs-security-oauth2/${project.version}</bundle> - </feature> <feature name="cxf-rs-security-jose" version="${project.version}" resolver="(obr)"> <feature version="${project.version}">cxf-jaxrs</feature> <bundle start-level="40">mvn:org.apache.cxf/cxf-rt-rs-security-jose/${project.version}</bundle> </feature> + <feature name="cxf-rs-security-oauth2" version="${project.version}" resolver="(obr)"> + <feature version="${project.version}">cxf-rs-security-jose</feature> + <bundle start-level="40">mvn:org.apache.cxf/cxf-rt-rs-security-oauth2/${project.version}</bundle> + </feature> <feature name="cxf-databinding-aegis" version="${project.version}" resolver="(obr)"> <feature version="${project.version}">cxf-wsdl</feature> <feature version="${project.version}">cxf-bindings-soap</feature> http://git-wip-us.apache.org/repos/asf/cxf/blob/4915ce37/rt/pom.xml ---------------------------------------------------------------------- diff --git a/rt/pom.xml b/rt/pom.xml index b5975a6..b76a3c9 100644 --- a/rt/pom.xml +++ b/rt/pom.xml @@ -62,9 +62,9 @@ <module>rs/extensions/providers</module> <module>rs/extensions/search</module> <module>rs/security/xml</module> - <module>rs/security/sso/saml</module> <module>rs/security/jose</module> <module>rs/security/oauth-parent</module> + <module>rs/security/sso/saml</module> <module>rs/security/cors</module> <module>management</module> <module>management-web</module> http://git-wip-us.apache.org/repos/asf/cxf/blob/4915ce37/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java index 8a5a151..aa59142 100644 --- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java @@ -48,6 +48,10 @@ public final class JwsUtils { public static String sign(byte[] key, String algo, String content) { return sign(getHmacSignatureProvider(key, algo), content); } + public static String verifyAndGetContent(RSAPublicKey key, String algo, String content) { + JwsCompactConsumer jws = verify(getRSAKeySignatureVerifier(key, algo), content); + return jws.getDecodedJwsPayload(); + } public static String verifyAndGetContent(byte[] key, String algo, String content) { JwsCompactConsumer jws = verify(getHmacSignatureVerifier(key, algo), content); return jws.getDecodedJwsPayload(); http://git-wip-us.apache.org/repos/asf/cxf/blob/4915ce37/rt/rs/security/oauth-parent/oauth2-jose/pom.xml ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jose/pom.xml b/rt/rs/security/oauth-parent/oauth2-jose/pom.xml deleted file mode 100644 index 3f1e1ab..0000000 --- a/rt/rs/security/oauth-parent/oauth2-jose/pom.xml +++ /dev/null @@ -1,56 +0,0 @@ -<?xml version="1.0"?> -<!-- - 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. ---> -<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-jose</artifactId> - <packaging>bundle</packaging> - <name>Apache CXF Runtime OAuth 2.0 JOSE</name> - <description>Apache CXF Runtime OAuth 2.0 JOSE</description> - <url>http://cxf.apache.org</url> - <parent> - <artifactId>cxf-rt-rs-security-oauth-parent</artifactId> - <groupId>org.apache.cxf</groupId> - <version>3.1.0-SNAPSHOT</version> - <relativePath>../pom.xml</relativePath> - </parent> - <dependencies> - <dependency> - <groupId>org.apache.cxf</groupId> - <artifactId>cxf-rt-rs-security-oauth2</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>org.apache.cxf</groupId> - <artifactId>cxf-rt-rs-security-jose</artifactId> - <version>${project.version}</version> - </dependency> - <!--test dependencies--> - <dependency> - <groupId>junit</groupId> - <artifactId>junit</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.easymock</groupId> - <artifactId>easymock</artifactId> - <scope>test</scope> - </dependency> - </dependencies> -</project> http://git-wip-us.apache.org/repos/asf/cxf/blob/4915ce37/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/AbstractJwtBearerGrant.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/AbstractJwtBearerGrant.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/AbstractJwtBearerGrant.java deleted file mode 100644 index f5705ae..0000000 --- a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/AbstractJwtBearerGrant.java +++ /dev/null @@ -1,69 +0,0 @@ -/** - * 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.jose.jwt.grant; - -import javax.ws.rs.core.MultivaluedMap; - -import org.apache.cxf.common.util.Base64UrlUtility; -import org.apache.cxf.jaxrs.impl.MetadataMap; -import org.apache.cxf.rs.security.oauth2.common.AccessTokenGrant; -import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException; -import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants; - -public abstract class AbstractJwtBearerGrant implements AccessTokenGrant { - private static final long serialVersionUID = 5754722119855372511L; - private String assertion; - private String scope; - private boolean encoded; - private String grantType; - protected AbstractJwtBearerGrant(String grantType, String assertion, boolean encoded, String scope) { - this.grantType = grantType; - this.assertion = assertion; - this.encoded = encoded; - this.scope = scope; - } - - public String getType() { - return grantType; - } - - protected MultivaluedMap<String, String> initMap() { - MultivaluedMap<String, String> map = new MetadataMap<String, String>(); - map.putSingle(OAuthConstants.GRANT_TYPE, grantType); - return map; - } - - protected void addScope(MultivaluedMap<String, String> map) { - if (scope != null) { - map.putSingle(OAuthConstants.SCOPE, scope); - } - } - - protected String encodeAssertion() { - if (encoded) { - return assertion; - } - - try { - return Base64UrlUtility.encode(assertion); - } catch (Exception ex) { - throw new OAuthServiceException(ex.getMessage(), ex); - } - } -} http://git-wip-us.apache.org/repos/asf/cxf/blob/4915ce37/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/AbstractJwtHandler.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/AbstractJwtHandler.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/AbstractJwtHandler.java deleted file mode 100644 index ff163b0..0000000 --- a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/AbstractJwtHandler.java +++ /dev/null @@ -1,100 +0,0 @@ -/** - * 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.jose.jwt.grant; - -import java.util.List; -import java.util.Set; - -import org.apache.cxf.rs.security.jose.JoseHeaders; -import org.apache.cxf.rs.security.jose.jws.JwsSignatureVerifier; -import org.apache.cxf.rs.security.jose.jwt.JwtClaims; -import org.apache.cxf.rs.security.oauth2.common.Client; -import org.apache.cxf.rs.security.oauth2.grants.AbstractGrantHandler; -import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException; -import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants; - - -/** - * The "JWT Bearer" grant handler - */ -public abstract class AbstractJwtHandler extends AbstractGrantHandler { - private Set<String> supportedIssuers; - private JwsSignatureVerifier jwsVefifier; - - protected AbstractJwtHandler(List<String> grants) { - super(grants); - } - - protected void validateSignature(JoseHeaders headers, String unsignedText, byte[] signature) { - if (jwsVefifier.verify(headers, unsignedText, signature)) { - throw new OAuthServiceException(OAuthConstants.INVALID_GRANT); - } - } - - protected void validateClaims(Client client, JwtClaims claims) { - validateIssuer(claims.getIssuer()); - validateSubject(client, claims.getSubject()); - validateAudience(client, claims.getAudience()); - validateExpiryTime(claims.getExpiryTime()); - validateNotBeforeTime(claims.getNotBefore()); - validateIssuedAtTime(claims.getIssuedAt()); - validateTokenId(claims.getTokenId()); - } - - protected void validateIssuer(String issuer) { - if (issuer == null || !supportedIssuers.contains(issuer)) { - throw new OAuthServiceException(OAuthConstants.INVALID_GRANT); - } - } - - protected void validateSubject(Client client, String subject) { - //TODO - } - protected void validateAudience(Client client, String audience) { - //TODO - } - protected void validateExpiryTime(Long timestamp) { - if (timestamp != null) { - //TODO - } - } - protected void validateNotBeforeTime(Long timestamp) { - if (timestamp != null) { - //TODO - } - } - protected void validateIssuedAtTime(Long timestamp) { - if (timestamp != null) { - //TODO - } - } - protected void validateTokenId(String tokenId) { - if (tokenId != null) { - //TODO - } - } - public void setSupportedIssuers(Set<String> supportedIssuers) { - this.supportedIssuers = supportedIssuers; - } - - public void setJwsVefifier(JwsSignatureVerifier jwsVefifier) { - this.jwsVefifier = jwsVefifier; - } - -} http://git-wip-us.apache.org/repos/asf/cxf/blob/4915ce37/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/Constants.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/Constants.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/Constants.java deleted file mode 100644 index 8714aac..0000000 --- a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/Constants.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * 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.jose.jwt.grant; - -public final class Constants { - public static final String JWT_BEARER_GRANT = "urn:ietf:params:oauth:grant-type:jwt-bearer"; - public static final String CLIENT_GRANT_ASSERTION_PARAM = "assertion"; - - public static final String CLIENT_AUTH_ASSERTION_PARAM = "client_assertion"; - public static final String CLIENT_AUTH_ASSERTION_TYPE = "client_assertion_type"; - public static final String CLIENT_AUTH_JWT_BEARER = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"; - - - private Constants() { - - } -} http://git-wip-us.apache.org/repos/asf/cxf/blob/4915ce37/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/JwtBearerClientCredentialsGrant.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/JwtBearerClientCredentialsGrant.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/JwtBearerClientCredentialsGrant.java deleted file mode 100644 index f5f86a8..0000000 --- a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/JwtBearerClientCredentialsGrant.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * 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.jose.jwt.grant; - -import javax.ws.rs.core.MultivaluedMap; - -import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants; - -public class JwtBearerClientCredentialsGrant extends AbstractJwtBearerGrant { - - private static final long serialVersionUID = 4801583498206813025L; - - public JwtBearerClientCredentialsGrant(String assertion, boolean encoded, String scope) { - super(OAuthConstants.CLIENT_CREDENTIALS_GRANT, assertion, encoded, scope); - } - - public MultivaluedMap<String, String> toMap() { - MultivaluedMap<String, String> map = initMap(); - map.putSingle(Constants.CLIENT_AUTH_ASSERTION_TYPE, Constants.CLIENT_AUTH_JWT_BEARER); - map.putSingle(Constants.CLIENT_AUTH_ASSERTION_PARAM, encodeAssertion()); - addScope(map); - return map; - } - -} http://git-wip-us.apache.org/repos/asf/cxf/blob/4915ce37/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/JwtBearerGrant.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/JwtBearerGrant.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/JwtBearerGrant.java deleted file mode 100644 index 49041b9..0000000 --- a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/JwtBearerGrant.java +++ /dev/null @@ -1,48 +0,0 @@ -/** - * 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.jose.jwt.grant; - -import javax.ws.rs.core.MultivaluedMap; - -public class JwtBearerGrant extends AbstractJwtBearerGrant { - private static final long serialVersionUID = -7296527609343431294L; - - public JwtBearerGrant(String assertion) { - this(assertion, false); - } - - public JwtBearerGrant(String assertion, boolean encoded) { - this(assertion, false, null); - } - - public JwtBearerGrant(String assertion, String scope) { - this(assertion, false, scope); - } - - public JwtBearerGrant(String assertion, boolean encoded, String scope) { - super(Constants.JWT_BEARER_GRANT, assertion, encoded, scope); - } - - public MultivaluedMap<String, String> toMap() { - MultivaluedMap<String, String> map = initMap(); - map.putSingle(Constants.CLIENT_GRANT_ASSERTION_PARAM, encodeAssertion()); - addScope(map); - return map; - } -} http://git-wip-us.apache.org/repos/asf/cxf/blob/4915ce37/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/JwtBearerGrantHandler.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/JwtBearerGrantHandler.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/JwtBearerGrantHandler.java deleted file mode 100644 index f7b25f8..0000000 --- a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/JwtBearerGrantHandler.java +++ /dev/null @@ -1,91 +0,0 @@ -/** - * 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.jose.jwt.grant; - -import java.util.Arrays; - -import javax.ws.rs.core.MultivaluedMap; - -import org.apache.cxf.jaxrs.utils.HttpUtils; -import org.apache.cxf.rs.security.jose.jws.JwsJwtCompactConsumer; -import org.apache.cxf.rs.security.jose.jwt.JwtToken; -import org.apache.cxf.rs.security.jose.jwt.JwtTokenReader; -import org.apache.cxf.rs.security.oauth2.common.Client; -import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken; -import org.apache.cxf.rs.security.oauth2.common.UserSubject; -import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException; -import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants; -import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils; - -/** - * The "JWT Bearer" grant handler - */ -public class JwtBearerGrantHandler extends AbstractJwtHandler { - private static final String ENCODED_JWT_BEARER_GRANT; - static { - // AccessTokenService may be configured with the form provider - // which will not decode by default - so listing both the actual - // and encoded grant type value will help - ENCODED_JWT_BEARER_GRANT = HttpUtils.urlEncode(Constants.JWT_BEARER_GRANT, "UTF-8"); - } - private JwtTokenReader jwtReader; - public JwtBearerGrantHandler() { - super(Arrays.asList(Constants.JWT_BEARER_GRANT, ENCODED_JWT_BEARER_GRANT)); - } - - @Override - public ServerAccessToken createAccessToken(Client client, MultivaluedMap<String, String> params) - throws OAuthServiceException { - String assertion = params.getFirst(Constants.CLIENT_GRANT_ASSERTION_PARAM); - if (assertion == null) { - throw new OAuthServiceException(OAuthConstants.INVALID_GRANT); - } - try { - JwsJwtCompactConsumer jwsReader = getJwsReader(assertion); - JwtToken jwtToken = jwsReader.getJwtToken(); - super.validateSignature(jwtToken.getHeaders(), - jwsReader.getUnsignedEncodedSequence(), - jwsReader.getDecodedSignature()); - - - super.validateClaims(client, jwtToken.getClaims()); - UserSubject grantSubject = new UserSubject(jwtToken.getClaims().getSubject()); - - return doCreateAccessToken(client, - grantSubject, - Constants.JWT_BEARER_GRANT, - OAuthUtils.parseScope(params.getFirst(OAuthConstants.SCOPE))); - } catch (OAuthServiceException ex) { - throw ex; - } catch (Exception ex) { - throw new OAuthServiceException(OAuthConstants.INVALID_GRANT, ex); - } - - } - - protected JwsJwtCompactConsumer getJwsReader(String assertion) { - return new JwsJwtCompactConsumer(assertion, jwtReader); - } - - public void setJwtReader(JwtTokenReader tokenReader) { - this.jwtReader = tokenReader; - } - - -} http://git-wip-us.apache.org/repos/asf/cxf/blob/4915ce37/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/JwtUserSubject.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/JwtUserSubject.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/JwtUserSubject.java deleted file mode 100644 index 18eaae1..0000000 --- a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/JwtUserSubject.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * 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.jose.jwt.grant; - -import org.apache.cxf.rs.security.jose.jwt.JwtToken; -import org.apache.cxf.rs.security.oauth2.common.UserSubject; - -public class JwtUserSubject extends UserSubject { - private static final long serialVersionUID = -1135272749329239037L; - private JwtToken token; - public JwtUserSubject(String user, JwtToken token) { - super(user); - this.token = token; - } - public JwtToken getToken() { - return token; - } -} http://git-wip-us.apache.org/repos/asf/cxf/blob/4915ce37/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/token/JwtAccessTokenUtils.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/token/JwtAccessTokenUtils.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/token/JwtAccessTokenUtils.java deleted file mode 100644 index 594d777..0000000 --- a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/token/JwtAccessTokenUtils.java +++ /dev/null @@ -1,123 +0,0 @@ -/** - * 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.jose.jwt.token; - -import javax.crypto.SecretKey; - -import org.apache.cxf.rs.security.jose.JoseHeaders; -import org.apache.cxf.rs.security.jose.jwa.Algorithm; -import org.apache.cxf.rs.security.jose.jwe.AesGcmContentDecryptionAlgorithm; -import org.apache.cxf.rs.security.jose.jwe.AesGcmContentEncryptionAlgorithm; -import org.apache.cxf.rs.security.jose.jwe.ContentEncryptionAlgorithm; -import org.apache.cxf.rs.security.jose.jwe.DirectKeyJweDecryption; -import org.apache.cxf.rs.security.jose.jwe.DirectKeyJweEncryption; -import org.apache.cxf.rs.security.jose.jwe.JweDecryptionProvider; -import org.apache.cxf.rs.security.jose.jwe.JweEncryptionProvider; -import org.apache.cxf.rs.security.jose.jws.JwsJwtCompactConsumer; -import org.apache.cxf.rs.security.jose.jws.JwsJwtCompactProducer; -import org.apache.cxf.rs.security.jose.jws.JwsSignature; -import org.apache.cxf.rs.security.jose.jws.JwsSignatureProvider; -import org.apache.cxf.rs.security.jose.jwt.JwtToken; -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.tokens.bearer.BearerAccessToken; - -public final class JwtAccessTokenUtils { - private JwtAccessTokenUtils() { - - } - - public static ServerAccessToken toAccessToken(JwtToken jwt, - Client client, - SecretKey key) { - ContentEncryptionAlgorithm contentEncryption = - new AesGcmContentEncryptionAlgorithm(key, null, Algorithm.A128GCM.getJwtName()); - JweEncryptionProvider jweEncryption = new DirectKeyJweEncryption(contentEncryption); - return toAccessToken(jwt, client, jweEncryption); - - } - - public static ServerAccessToken toAccessToken(JwtToken jwt, - Client client, - JweEncryptionProvider jweEncryption) { - String jwtString = new JwsJwtCompactProducer(jwt) - .signWith(new NoneSignatureProvider()); - String tokenId = jweEncryption.encrypt(getBytes(jwtString), null); - Long issuedAt = jwt.getClaims().getIssuedAt(); - Long notBefore = jwt.getClaims().getNotBefore(); - if (issuedAt == null) { - issuedAt = System.currentTimeMillis(); - notBefore = null; - } - Long expiresIn = null; - if (notBefore == null) { - expiresIn = 3600L; - } else { - expiresIn = notBefore - issuedAt; - } - - return new BearerAccessToken(client, tokenId, issuedAt, expiresIn); - - } - public static JwtToken fromAccessTokenId(String tokenId, SecretKey key) { - DirectKeyJweDecryption jweDecryption = - new DirectKeyJweDecryption(key, - new AesGcmContentDecryptionAlgorithm(Algorithm.A128GCM.getJwtName())); - return fromAccessTokenId(tokenId, jweDecryption); - } - public static JwtToken fromAccessTokenId(String tokenId, JweDecryptionProvider jweDecryption) { - String decrypted = jweDecryption.decrypt(tokenId).getContentText(); - JwsJwtCompactConsumer consumer = new JwsJwtCompactConsumer(decrypted); - return consumer.getJwtToken(); - } - private static class NoneSignatureProvider implements JwsSignatureProvider { - - @Override - public String getAlgorithm() { - return "none"; - } - - @Override - public JwsSignature createJwsSignature(JoseHeaders headers) { - return new NoneJwsSignature(); - } - - } - private static class NoneJwsSignature implements JwsSignature { - - @Override - public void update(byte[] src, int off, int len) { - // complete - } - - @Override - public byte[] sign() { - return new byte[]{}; - } - - } - private static byte[] getBytes(String str) { - try { - return str.getBytes("UTF-8"); - } catch (Exception ex) { - // ignore - } - return null; - } -} http://git-wip-us.apache.org/repos/asf/cxf/blob/4915ce37/rt/rs/security/oauth-parent/oauth2-jose/src/test/java/org/apache/cxf/rs/security/jose/jwt/grant/JwtUserSubjectTest.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/test/java/org/apache/cxf/rs/security/jose/jwt/grant/JwtUserSubjectTest.java b/rt/rs/security/oauth-parent/oauth2-jose/src/test/java/org/apache/cxf/rs/security/jose/jwt/grant/JwtUserSubjectTest.java deleted file mode 100644 index 1be0216..0000000 --- a/rt/rs/security/oauth-parent/oauth2-jose/src/test/java/org/apache/cxf/rs/security/jose/jwt/grant/JwtUserSubjectTest.java +++ /dev/null @@ -1,32 +0,0 @@ -/** - * 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.jose.jwt.grant; - -import org.junit.Assert; -import org.junit.Test; - -public class JwtUserSubjectTest extends Assert { - - @Test - public void testJwtUserSubject() { - // to be expanded - assertNotNull(new JwtUserSubject("user", null)); - } - -} http://git-wip-us.apache.org/repos/asf/cxf/blob/4915ce37/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 5e2661b..9411505 100644 --- a/rt/rs/security/oauth-parent/oauth2/pom.xml +++ b/rt/rs/security/oauth-parent/oauth2/pom.xml @@ -43,6 +43,11 @@ </dependency> <dependency> <groupId>org.apache.cxf</groupId> + <artifactId>cxf-rt-rs-security-jose</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-rs-client</artifactId> <version>${project.version}</version> </dependency> @@ -59,13 +64,6 @@ <scope>provided</scope> <optional>true</optional> </dependency> - <!--test dependencies--> - <dependency> - <groupId>org.apache.cxf</groupId> - <artifactId>cxf-rt-rs-extension-providers</artifactId> - <version>${project.version}</version> - <scope>test</scope> - </dependency> <dependency> <groupId>org.codehaus.jettison</groupId> <artifactId>jettison</artifactId> http://git-wip-us.apache.org/repos/asf/cxf/blob/4915ce37/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/jwt/AbstractJwtBearerGrant.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/jwt/AbstractJwtBearerGrant.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/jwt/AbstractJwtBearerGrant.java new file mode 100644 index 0000000..2e21e8d --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/jwt/AbstractJwtBearerGrant.java @@ -0,0 +1,69 @@ +/** + * 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.jwt; + +import javax.ws.rs.core.MultivaluedMap; + +import org.apache.cxf.common.util.Base64UrlUtility; +import org.apache.cxf.jaxrs.impl.MetadataMap; +import org.apache.cxf.rs.security.oauth2.common.AccessTokenGrant; +import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException; +import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants; + +public abstract class AbstractJwtBearerGrant implements AccessTokenGrant { + private static final long serialVersionUID = 5754722119855372511L; + private String assertion; + private String scope; + private boolean encoded; + private String grantType; + protected AbstractJwtBearerGrant(String grantType, String assertion, boolean encoded, String scope) { + this.grantType = grantType; + this.assertion = assertion; + this.encoded = encoded; + this.scope = scope; + } + + public String getType() { + return grantType; + } + + protected MultivaluedMap<String, String> initMap() { + MultivaluedMap<String, String> map = new MetadataMap<String, String>(); + map.putSingle(OAuthConstants.GRANT_TYPE, grantType); + return map; + } + + protected void addScope(MultivaluedMap<String, String> map) { + if (scope != null) { + map.putSingle(OAuthConstants.SCOPE, scope); + } + } + + protected String encodeAssertion() { + if (encoded) { + return assertion; + } + + try { + return Base64UrlUtility.encode(assertion); + } catch (Exception ex) { + throw new OAuthServiceException(ex.getMessage(), ex); + } + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/4915ce37/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/jwt/AbstractJwtHandler.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/jwt/AbstractJwtHandler.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/jwt/AbstractJwtHandler.java new file mode 100644 index 0000000..33c1ecf --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/jwt/AbstractJwtHandler.java @@ -0,0 +1,100 @@ +/** + * 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.jwt; + +import java.util.List; +import java.util.Set; + +import org.apache.cxf.rs.security.jose.JoseHeaders; +import org.apache.cxf.rs.security.jose.jws.JwsSignatureVerifier; +import org.apache.cxf.rs.security.jose.jwt.JwtClaims; +import org.apache.cxf.rs.security.oauth2.common.Client; +import org.apache.cxf.rs.security.oauth2.grants.AbstractGrantHandler; +import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException; +import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants; + + +/** + * The "JWT Bearer" grant handler + */ +public abstract class AbstractJwtHandler extends AbstractGrantHandler { + private Set<String> supportedIssuers; + private JwsSignatureVerifier jwsVefifier; + + protected AbstractJwtHandler(List<String> grants) { + super(grants); + } + + protected void validateSignature(JoseHeaders headers, String unsignedText, byte[] signature) { + if (jwsVefifier.verify(headers, unsignedText, signature)) { + throw new OAuthServiceException(OAuthConstants.INVALID_GRANT); + } + } + + protected void validateClaims(Client client, JwtClaims claims) { + validateIssuer(claims.getIssuer()); + validateSubject(client, claims.getSubject()); + validateAudience(client, claims.getAudience()); + validateExpiryTime(claims.getExpiryTime()); + validateNotBeforeTime(claims.getNotBefore()); + validateIssuedAtTime(claims.getIssuedAt()); + validateTokenId(claims.getTokenId()); + } + + protected void validateIssuer(String issuer) { + if (issuer == null || !supportedIssuers.contains(issuer)) { + throw new OAuthServiceException(OAuthConstants.INVALID_GRANT); + } + } + + protected void validateSubject(Client client, String subject) { + //TODO + } + protected void validateAudience(Client client, String audience) { + //TODO + } + protected void validateExpiryTime(Long timestamp) { + if (timestamp != null) { + //TODO + } + } + protected void validateNotBeforeTime(Long timestamp) { + if (timestamp != null) { + //TODO + } + } + protected void validateIssuedAtTime(Long timestamp) { + if (timestamp != null) { + //TODO + } + } + protected void validateTokenId(String tokenId) { + if (tokenId != null) { + //TODO + } + } + public void setSupportedIssuers(Set<String> supportedIssuers) { + this.supportedIssuers = supportedIssuers; + } + + public void setJwsVefifier(JwsSignatureVerifier jwsVefifier) { + this.jwsVefifier = jwsVefifier; + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/4915ce37/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/jwt/Constants.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/jwt/Constants.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/jwt/Constants.java new file mode 100644 index 0000000..11a65ff --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/jwt/Constants.java @@ -0,0 +1,33 @@ +/** + * 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.jwt; + +public final class Constants { + public static final String JWT_BEARER_GRANT = "urn:ietf:params:oauth:grant-type:jwt-bearer"; + public static final String CLIENT_GRANT_ASSERTION_PARAM = "assertion"; + + public static final String CLIENT_AUTH_ASSERTION_PARAM = "client_assertion"; + public static final String CLIENT_AUTH_ASSERTION_TYPE = "client_assertion_type"; + public static final String CLIENT_AUTH_JWT_BEARER = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"; + + + private Constants() { + + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/4915ce37/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/jwt/JwtBearerClientCredentialsGrant.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/jwt/JwtBearerClientCredentialsGrant.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/jwt/JwtBearerClientCredentialsGrant.java new file mode 100644 index 0000000..ddd4dd9 --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/jwt/JwtBearerClientCredentialsGrant.java @@ -0,0 +1,41 @@ +/** + * 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.jwt; + +import javax.ws.rs.core.MultivaluedMap; + +import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants; + +public class JwtBearerClientCredentialsGrant extends AbstractJwtBearerGrant { + + private static final long serialVersionUID = 4801583498206813025L; + + public JwtBearerClientCredentialsGrant(String assertion, boolean encoded, String scope) { + super(OAuthConstants.CLIENT_CREDENTIALS_GRANT, assertion, encoded, scope); + } + + public MultivaluedMap<String, String> toMap() { + MultivaluedMap<String, String> map = initMap(); + map.putSingle(Constants.CLIENT_AUTH_ASSERTION_TYPE, Constants.CLIENT_AUTH_JWT_BEARER); + map.putSingle(Constants.CLIENT_AUTH_ASSERTION_PARAM, encodeAssertion()); + addScope(map); + return map; + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/4915ce37/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/jwt/JwtBearerGrant.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/jwt/JwtBearerGrant.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/jwt/JwtBearerGrant.java new file mode 100644 index 0000000..a528705 --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/jwt/JwtBearerGrant.java @@ -0,0 +1,48 @@ +/** + * 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.jwt; + +import javax.ws.rs.core.MultivaluedMap; + +public class JwtBearerGrant extends AbstractJwtBearerGrant { + private static final long serialVersionUID = -7296527609343431294L; + + public JwtBearerGrant(String assertion) { + this(assertion, false); + } + + public JwtBearerGrant(String assertion, boolean encoded) { + this(assertion, false, null); + } + + public JwtBearerGrant(String assertion, String scope) { + this(assertion, false, scope); + } + + public JwtBearerGrant(String assertion, boolean encoded, String scope) { + super(Constants.JWT_BEARER_GRANT, assertion, encoded, scope); + } + + public MultivaluedMap<String, String> toMap() { + MultivaluedMap<String, String> map = initMap(); + map.putSingle(Constants.CLIENT_GRANT_ASSERTION_PARAM, encodeAssertion()); + addScope(map); + return map; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/4915ce37/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/jwt/JwtBearerGrantHandler.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/jwt/JwtBearerGrantHandler.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/jwt/JwtBearerGrantHandler.java new file mode 100644 index 0000000..d0fc0fa --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/jwt/JwtBearerGrantHandler.java @@ -0,0 +1,91 @@ +/** + * 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.jwt; + +import java.util.Arrays; + +import javax.ws.rs.core.MultivaluedMap; + +import org.apache.cxf.jaxrs.utils.HttpUtils; +import org.apache.cxf.rs.security.jose.jws.JwsJwtCompactConsumer; +import org.apache.cxf.rs.security.jose.jwt.JwtToken; +import org.apache.cxf.rs.security.jose.jwt.JwtTokenReader; +import org.apache.cxf.rs.security.oauth2.common.Client; +import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken; +import org.apache.cxf.rs.security.oauth2.common.UserSubject; +import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException; +import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants; +import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils; + +/** + * The "JWT Bearer" grant handler + */ +public class JwtBearerGrantHandler extends AbstractJwtHandler { + private static final String ENCODED_JWT_BEARER_GRANT; + static { + // AccessTokenService may be configured with the form provider + // which will not decode by default - so listing both the actual + // and encoded grant type value will help + ENCODED_JWT_BEARER_GRANT = HttpUtils.urlEncode(Constants.JWT_BEARER_GRANT, "UTF-8"); + } + private JwtTokenReader jwtReader; + public JwtBearerGrantHandler() { + super(Arrays.asList(Constants.JWT_BEARER_GRANT, ENCODED_JWT_BEARER_GRANT)); + } + + @Override + public ServerAccessToken createAccessToken(Client client, MultivaluedMap<String, String> params) + throws OAuthServiceException { + String assertion = params.getFirst(Constants.CLIENT_GRANT_ASSERTION_PARAM); + if (assertion == null) { + throw new OAuthServiceException(OAuthConstants.INVALID_GRANT); + } + try { + JwsJwtCompactConsumer jwsReader = getJwsReader(assertion); + JwtToken jwtToken = jwsReader.getJwtToken(); + super.validateSignature(jwtToken.getHeaders(), + jwsReader.getUnsignedEncodedSequence(), + jwsReader.getDecodedSignature()); + + + super.validateClaims(client, jwtToken.getClaims()); + UserSubject grantSubject = new UserSubject(jwtToken.getClaims().getSubject()); + + return doCreateAccessToken(client, + grantSubject, + Constants.JWT_BEARER_GRANT, + OAuthUtils.parseScope(params.getFirst(OAuthConstants.SCOPE))); + } catch (OAuthServiceException ex) { + throw ex; + } catch (Exception ex) { + throw new OAuthServiceException(OAuthConstants.INVALID_GRANT, ex); + } + + } + + protected JwsJwtCompactConsumer getJwsReader(String assertion) { + return new JwsJwtCompactConsumer(assertion, jwtReader); + } + + public void setJwtReader(JwtTokenReader tokenReader) { + this.jwtReader = tokenReader; + } + + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/4915ce37/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/jwt/JwtUserSubject.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/jwt/JwtUserSubject.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/jwt/JwtUserSubject.java new file mode 100644 index 0000000..2f09e63 --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/jwt/JwtUserSubject.java @@ -0,0 +1,34 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.oauth2.grants.jwt; + +import org.apache.cxf.rs.security.jose.jwt.JwtToken; +import org.apache.cxf.rs.security.oauth2.common.UserSubject; + +public class JwtUserSubject extends UserSubject { + private static final long serialVersionUID = -1135272749329239037L; + private JwtToken token; + public JwtUserSubject(String user, JwtToken token) { + super(user); + this.token = token; + } + public JwtToken getToken() { + return token; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/4915ce37/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/crypto/JwtAccessTokenUtils.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/crypto/JwtAccessTokenUtils.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/crypto/JwtAccessTokenUtils.java new file mode 100644 index 0000000..fd97257 --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/crypto/JwtAccessTokenUtils.java @@ -0,0 +1,119 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.oauth2.utils.crypto; + +import javax.crypto.SecretKey; + +import org.apache.cxf.common.util.StringUtils; +import org.apache.cxf.rs.security.jose.JoseHeaders; +import org.apache.cxf.rs.security.jose.jwa.Algorithm; +import org.apache.cxf.rs.security.jose.jwe.AesGcmContentDecryptionAlgorithm; +import org.apache.cxf.rs.security.jose.jwe.AesGcmContentEncryptionAlgorithm; +import org.apache.cxf.rs.security.jose.jwe.ContentEncryptionAlgorithm; +import org.apache.cxf.rs.security.jose.jwe.DirectKeyJweDecryption; +import org.apache.cxf.rs.security.jose.jwe.DirectKeyJweEncryption; +import org.apache.cxf.rs.security.jose.jwe.JweDecryptionProvider; +import org.apache.cxf.rs.security.jose.jwe.JweEncryptionProvider; +import org.apache.cxf.rs.security.jose.jws.JwsJwtCompactConsumer; +import org.apache.cxf.rs.security.jose.jws.JwsJwtCompactProducer; +import org.apache.cxf.rs.security.jose.jws.JwsSignature; +import org.apache.cxf.rs.security.jose.jws.JwsSignatureProvider; +import org.apache.cxf.rs.security.jose.jwt.JwtToken; +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.tokens.bearer.BearerAccessToken; + +public final class JwtAccessTokenUtils { + private JwtAccessTokenUtils() { + + } + + public static ServerAccessToken toAccessToken(JwtToken jwt, + Client client, + SecretKey key) { + ContentEncryptionAlgorithm contentEncryption = + new AesGcmContentEncryptionAlgorithm(key, null, Algorithm.A128GCM.getJwtName()); + JweEncryptionProvider jweEncryption = new DirectKeyJweEncryption(contentEncryption); + return toAccessToken(jwt, client, jweEncryption); + + } + + public static ServerAccessToken toAccessToken(JwtToken jwt, + Client client, + JweEncryptionProvider jweEncryption) { + String jwtString = new JwsJwtCompactProducer(jwt) + .signWith(new NoneSignatureProvider()); + String tokenId = jweEncryption.encrypt(getBytes(jwtString), null); + Long issuedAt = jwt.getClaims().getIssuedAt(); + Long notBefore = jwt.getClaims().getNotBefore(); + if (issuedAt == null) { + issuedAt = System.currentTimeMillis(); + notBefore = null; + } + Long expiresIn = null; + if (notBefore == null) { + expiresIn = 3600L; + } else { + expiresIn = notBefore - issuedAt; + } + + return new BearerAccessToken(client, tokenId, issuedAt, expiresIn); + + } + public static JwtToken fromAccessTokenId(String tokenId, SecretKey key) { + DirectKeyJweDecryption jweDecryption = + new DirectKeyJweDecryption(key, + new AesGcmContentDecryptionAlgorithm(Algorithm.A128GCM.getJwtName())); + return fromAccessTokenId(tokenId, jweDecryption); + } + public static JwtToken fromAccessTokenId(String tokenId, JweDecryptionProvider jweDecryption) { + String decrypted = jweDecryption.decrypt(tokenId).getContentText(); + JwsJwtCompactConsumer consumer = new JwsJwtCompactConsumer(decrypted); + return consumer.getJwtToken(); + } + private static class NoneSignatureProvider implements JwsSignatureProvider { + + @Override + public String getAlgorithm() { + return "none"; + } + + @Override + public JwsSignature createJwsSignature(JoseHeaders headers) { + return new NoneJwsSignature(); + } + + } + private static class NoneJwsSignature implements JwsSignature { + + @Override + public void update(byte[] src, int off, int len) { + // complete + } + + @Override + public byte[] sign() { + return new byte[]{}; + } + + } + private static byte[] getBytes(String str) { + return StringUtils.toBytesUTF8(str); + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/4915ce37/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/grants/jwt/JwtUserSubjectTest.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/grants/jwt/JwtUserSubjectTest.java b/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/grants/jwt/JwtUserSubjectTest.java new file mode 100644 index 0000000..29bfd25 --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/grants/jwt/JwtUserSubjectTest.java @@ -0,0 +1,32 @@ +/** + * 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.jwt; + +import org.junit.Assert; +import org.junit.Test; + +public class JwtUserSubjectTest extends Assert { + + @Test + public void testJwtUserSubject() { + // to be expanded + assertNotNull(new JwtUserSubject("user", null)); + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/4915ce37/rt/rs/security/oauth-parent/pom.xml ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/pom.xml b/rt/rs/security/oauth-parent/pom.xml index 251689e..ccd1079 100644 --- a/rt/rs/security/oauth-parent/pom.xml +++ b/rt/rs/security/oauth-parent/pom.xml @@ -39,6 +39,5 @@ <module>oauth</module> <module>oauth2</module> <module>oauth2-saml</module> - <module>oauth2-jose</module> </modules> </project>
