Return-Path: X-Original-To: apmail-cxf-commits-archive@www.apache.org Delivered-To: apmail-cxf-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 1D66210EC3 for ; Tue, 8 Dec 2015 14:19:08 +0000 (UTC) Received: (qmail 78781 invoked by uid 500); 8 Dec 2015 14:19:03 -0000 Delivered-To: apmail-cxf-commits-archive@cxf.apache.org Received: (qmail 78671 invoked by uid 500); 8 Dec 2015 14:19:02 -0000 Mailing-List: contact commits-help@cxf.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cxf.apache.org Delivered-To: mailing list commits@cxf.apache.org Received: (qmail 78636 invoked by uid 99); 8 Dec 2015 14:19:02 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 08 Dec 2015 14:19:02 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id A1327DFE01; Tue, 8 Dec 2015 14:19:02 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: sergeyb@apache.org To: commits@cxf.apache.org Message-Id: <385daf66a4334f8ab2bdfc8520197353@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: cxf git commit: Prototyping the code for setting an access token hash in id_token Date: Tue, 8 Dec 2015 14:19:02 +0000 (UTC) Repository: cxf Updated Branches: refs/heads/3.1.x-fixes 14e7cea44 -> 32c0aca5f Prototyping the code for setting an access token hash in id_token Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/32c0aca5 Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/32c0aca5 Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/32c0aca5 Branch: refs/heads/3.1.x-fixes Commit: 32c0aca5fa2a6473dc3e3257fcaaef6efea66874 Parents: 14e7cea Author: Sergey Beryozkin Authored: Tue Dec 8 14:08:19 2015 +0000 Committer: Sergey Beryozkin Committed: Tue Dec 8 14:15:40 2015 +0000 ---------------------------------------------------------------------- .../cxf/rs/security/oauth2/common/Client.java | 22 +++++++++-- .../rs/security/oauth2/utils/OAuthUtils.java | 41 +++++++++++++------- .../cxf/rs/security/oidc/common/IdToken.java | 17 +++++++- .../cxf/rs/security/oidc/common/UserInfo.java | 3 +- .../oidc/idp/IdTokenResponseFilter.java | 28 +++++++++++-- .../cxf/rs/security/oidc/utils/OidcUtils.java | 20 +++++++--- 6 files changed, 104 insertions(+), 27 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/32c0aca5/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 4f1b395..bc5c756 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 @@ -50,7 +50,8 @@ public class Client implements Serializable { private Map properties = new HashMap(); private UserSubject subject; private UserSubject resourceOwnerSubject; - + private boolean registeredAt; + public Client() { } @@ -64,10 +65,17 @@ public class Client implements Serializable { public Client(String clientId, String clientSecret, boolean isConfidential, - String applicationName, - String applicationWebUri) { + String applicationName) { this(clientId, clientSecret, isConfidential); this.applicationName = applicationName; + } + + public Client(String clientId, + String clientSecret, + boolean isConfidential, + String applicationName, + String applicationWebUri) { + this(clientId, clientSecret, isConfidential, applicationName); this.applicationWebUri = applicationWebUri; } @@ -330,4 +338,12 @@ public class Client implements Serializable { public void setClientIpAddress(String clientIpAddress) { this.clientIpAddress = clientIpAddress; } + + public boolean isRegisteredAt() { + return registeredAt; + } + + public void setRegisteredAt(boolean registeredAt) { + this.registeredAt = registeredAt; + } } http://git-wip-us.apache.org/repos/asf/cxf/blob/32c0aca5/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java index 5e8ed8a..0db2313 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java @@ -35,6 +35,7 @@ import org.apache.cxf.jaxrs.impl.MetadataMap; import org.apache.cxf.jaxrs.model.URITemplate; import org.apache.cxf.jaxrs.utils.JAXRSUtils; import org.apache.cxf.message.Message; +import org.apache.cxf.rs.security.jose.common.JoseConstants; import org.apache.cxf.rs.security.jose.jwa.AlgorithmUtils; import org.apache.cxf.rs.security.jose.jwa.ContentAlgorithm; import org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm; @@ -268,37 +269,51 @@ public final class OAuthUtils { } public static JwsSignatureProvider getClientSecretSignatureProvider(String clientSecret) { - return JwsUtils.getHmacSignatureProvider(clientSecret, getClientSecretSignatureAlgorithm()); + Properties sigProps = JwsUtils.loadSignatureOutProperties(false); + return JwsUtils.getHmacSignatureProvider(clientSecret, + getClientSecretSignatureAlgorithm(sigProps)); } public static JwsSignatureVerifier getClientSecretSignatureVerifier(String clientSecret) { - return JwsUtils.getHmacSignatureVerifier(clientSecret, getClientSecretSignatureAlgorithm()); + Properties sigProps = JwsUtils.loadSignatureOutProperties(false); + return JwsUtils.getHmacSignatureVerifier(clientSecret, + getClientSecretSignatureAlgorithm(sigProps)); } public static JweDecryptionProvider getClientSecretDecryptionProvider(String clientSecret) { + Properties props = JweUtils.loadEncryptionInProperties(false); byte[] key = StringUtils.toBytesUTF8(clientSecret); - return JweUtils.getDirectKeyJweDecryption(key, getClientSecretContentAlgorithm()); + return JweUtils.getDirectKeyJweDecryption(key, getClientSecretContentAlgorithm(props)); } public static JweEncryptionProvider getClientSecretEncryptionProvider(String clientSecret) { + Properties props = JweUtils.loadEncryptionInProperties(false); byte[] key = StringUtils.toBytesUTF8(clientSecret); - return JweUtils.getDirectKeyJweEncryption(key, getClientSecretContentAlgorithm()); + return JweUtils.getDirectKeyJweEncryption(key, getClientSecretContentAlgorithm(props)); } - private static ContentAlgorithm getClientSecretContentAlgorithm() { - Properties props = JweUtils.loadEncryptionInProperties(false); - ContentAlgorithm ctAlgo = ContentAlgorithm.getAlgorithm( - props.getProperty(OAuthConstants.CLIENT_SECRET_CONTENT_ENCRYPTION_ALGORITHM)); + private static ContentAlgorithm getClientSecretContentAlgorithm(Properties props) { + String ctAlgoProp = props.getProperty(OAuthConstants.CLIENT_SECRET_CONTENT_ENCRYPTION_ALGORITHM); + if (ctAlgoProp == null) { + ctAlgoProp = props.getProperty(JoseConstants.RSSEC_ENCRYPTION_CONTENT_ALGORITHM); + } + ContentAlgorithm ctAlgo = ContentAlgorithm.getAlgorithm(ctAlgoProp); ctAlgo = ctAlgo != null ? ctAlgo : ContentAlgorithm.A128GCM; return ctAlgo; } - private static SignatureAlgorithm getClientSecretSignatureAlgorithm() { - Properties sigProps = JwsUtils.loadSignatureOutProperties(false); - SignatureAlgorithm sigAlgo = SignatureAlgorithm.getAlgorithm( - sigProps.getProperty(OAuthConstants.CLIENT_SECRET_SIGNATURE_ALGORITHM)); + public static SignatureAlgorithm getClientSecretSignatureAlgorithm(Properties sigProps) { + + String clientSecretSigProp = sigProps.getProperty(OAuthConstants.CLIENT_SECRET_SIGNATURE_ALGORITHM); + if (clientSecretSigProp == null) { + String sigProp = sigProps.getProperty(JoseConstants.RSSEC_SIGNATURE_ALGORITHM); + if (AlgorithmUtils.isHmacSign(sigProp)) { + clientSecretSigProp = sigProp; + } + } + SignatureAlgorithm sigAlgo = SignatureAlgorithm.getAlgorithm(clientSecretSigProp); sigAlgo = sigAlgo != null ? sigAlgo : SignatureAlgorithm.HS256; if (!AlgorithmUtils.isHmacSign(sigAlgo)) { - // Must be HS-based for the symmetric signature + // Must be HS-based for the symmetric signature throw new OAuthServiceException(OAuthConstants.SERVER_ERROR); } else { return sigAlgo; http://git-wip-us.apache.org/repos/asf/cxf/blob/32c0aca5/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/common/IdToken.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/common/IdToken.java b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/common/IdToken.java index 63dfca3..6687e8b 100644 --- a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/common/IdToken.java +++ b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/common/IdToken.java @@ -18,6 +18,7 @@ */ package org.apache.cxf.rs.security.oidc.common; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -31,6 +32,8 @@ public class IdToken extends AbstractUserInfo { public static final String ACR_CLAIM = "acr"; public static final String AZP_CLAIM = "azp"; public static final String AMR_CLAIM = "amr"; + public static final String ACCESS_TOKEN_HASH_CLAIM = "at_hash"; + public static final String AUTH_CODE_HASH_CLAIM = "c_hash"; public IdToken() { } @@ -40,7 +43,7 @@ public class IdToken extends AbstractUserInfo { } public IdToken(Map claims) { - super(claims); + super(new LinkedHashMap(claims)); } public void setAuthenticationTime(Long time) { setProperty(AUTH_TIME_CLAIM, time); @@ -72,5 +75,17 @@ public class IdToken extends AbstractUserInfo { public String getAuthorizedParty() { return (String)getProperty(AZP_CLAIM); } + public void setAccessTokenHash(String at) { + setProperty(ACCESS_TOKEN_HASH_CLAIM, at); + } + public String getAccessTokenHash() { + return (String)getProperty(ACCESS_TOKEN_HASH_CLAIM); + } + public void setAuthCodeHash(String at) { + setProperty(AUTH_CODE_HASH_CLAIM, at); + } + public String getAuthCodeHash() { + return (String)getProperty(AUTH_CODE_HASH_CLAIM); + } } http://git-wip-us.apache.org/repos/asf/cxf/blob/32c0aca5/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/common/UserInfo.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/common/UserInfo.java b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/common/UserInfo.java index f8da67a..1ac2986 100644 --- a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/common/UserInfo.java +++ b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/common/UserInfo.java @@ -18,6 +18,7 @@ */ package org.apache.cxf.rs.security.oidc.common; +import java.util.LinkedHashMap; import java.util.Map; import org.apache.cxf.rs.security.jose.jwt.JwtClaims; @@ -29,6 +30,6 @@ public class UserInfo extends AbstractUserInfo { this(claims.asMap()); } public UserInfo(Map claims) { - super(claims); + super(new LinkedHashMap(claims)); } } http://git-wip-us.apache.org/repos/asf/cxf/blob/32c0aca5/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/IdTokenResponseFilter.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/IdTokenResponseFilter.java b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/IdTokenResponseFilter.java index 0d10d4e..0a19d8e 100644 --- a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/IdTokenResponseFilter.java +++ b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/IdTokenResponseFilter.java @@ -18,11 +18,16 @@ */ package org.apache.cxf.rs.security.oidc.idp; +import java.util.Properties; + +import org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm; +import org.apache.cxf.rs.security.jose.jws.JwsUtils; import org.apache.cxf.rs.security.jose.jwt.JwtToken; import org.apache.cxf.rs.security.oauth2.common.ClientAccessToken; import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken; import org.apache.cxf.rs.security.oauth2.provider.AbstractOAuthServerJoseJwtProducer; import org.apache.cxf.rs.security.oauth2.provider.AccessTokenResponseFilter; +import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils; import org.apache.cxf.rs.security.oidc.common.IdToken; import org.apache.cxf.rs.security.oidc.utils.OidcUtils; @@ -39,18 +44,35 @@ public class IdTokenResponseFilter extends AbstractOAuthServerJoseJwtProducer im } private String getProcessedIdToken(ServerAccessToken st) { if (userInfoProvider != null) { - IdToken token = + IdToken idToken = userInfoProvider.getIdToken(st.getClient().getClientId(), st.getSubject(), st.getScopes()); - return super.processJwt(new JwtToken(token), st.getClient()); + setAtHash(idToken, st); + return super.processJwt(new JwtToken(idToken), st.getClient()); } else if (st.getSubject().getProperties().containsKey(OidcUtils.ID_TOKEN)) { return st.getSubject().getProperties().get(OidcUtils.ID_TOKEN); } else if (st.getSubject() instanceof OidcUserSubject) { OidcUserSubject sub = (OidcUserSubject)st.getSubject(); - return super.processJwt(new JwtToken(sub.getIdToken()), st.getClient()); + IdToken idToken = new IdToken(sub.getIdToken()); + setAtHash(idToken, st); + return super.processJwt(new JwtToken(idToken), st.getClient()); } else { return null; } } + private void setAtHash(IdToken idToken, ServerAccessToken st) { + Properties props = JwsUtils.loadSignatureOutProperties(false); + SignatureAlgorithm sigAlgo = null; + if (super.isSignWithClientSecret()) { + sigAlgo = OAuthUtils.getClientSecretSignatureAlgorithm(props); + } else { + sigAlgo = JwsUtils.getSignatureAlgorithm(props, SignatureAlgorithm.RS256); + } + if (sigAlgo != SignatureAlgorithm.NONE) { + String atHash = OidcUtils.calculateAccessTokenHash(st.getTokenKey(), sigAlgo); + idToken.setAccessTokenHash(atHash); + } + + } public void setUserInfoProvider(UserInfoProvider userInfoProvider) { this.userInfoProvider = userInfoProvider; } http://git-wip-us.apache.org/repos/asf/cxf/blob/32c0aca5/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/utils/OidcUtils.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/utils/OidcUtils.java b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/utils/OidcUtils.java index 42837fd..1e42454 100644 --- a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/utils/OidcUtils.java +++ b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/utils/OidcUtils.java @@ -26,8 +26,10 @@ import java.util.Map; import org.apache.cxf.common.util.Base64UrlUtility; import org.apache.cxf.common.util.StringUtils; +import org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm; import org.apache.cxf.rs.security.jose.jwt.JwtToken; import org.apache.cxf.rs.security.oauth2.common.ClientAccessToken; +import org.apache.cxf.rs.security.oidc.common.IdToken; import org.apache.cxf.rs.security.oidc.common.UserInfo; import org.apache.cxf.rt.security.crypto.MessageDigestUtils; @@ -94,8 +96,8 @@ public final class OidcUtils { public static void validateAccessTokenHash(ClientAccessToken at, JwtToken jwt, boolean required) { if (required) { validateHash(at.getTokenKey(), - (String)jwt.getClaims().getClaim("at_hash"), - jwt.getJwsHeaders().getAlgorithm()); + (String)jwt.getClaims().getClaim(IdToken.ACCESS_TOKEN_HASH_CLAIM), + jwt.getJwsHeaders().getSignatureAlgorithm()); } } public static void validateCodeHash(String code, JwtToken jwt) { @@ -104,17 +106,23 @@ public final class OidcUtils { public static void validateCodeHash(String code, JwtToken jwt, boolean required) { if (required) { validateHash(code, - (String)jwt.getClaims().getClaim("c_hash"), - jwt.getJwsHeaders().getAlgorithm()); + (String)jwt.getClaims().getClaim(IdToken.AUTH_CODE_HASH_CLAIM), + jwt.getJwsHeaders().getSignatureAlgorithm()); } } - private static void validateHash(String value, String theHash, String joseAlgo) { + private static void validateHash(String value, String theHash, SignatureAlgorithm joseAlgo) { String hash = calculateHash(value, joseAlgo); if (!hash.equals(theHash)) { throw new SecurityException("Invalid hash"); } } - public static String calculateHash(String value, String joseAlgo) { + public static String calculateAccessTokenHash(String value, SignatureAlgorithm joseAlgo) { + return calculateHash(value, joseAlgo); + } + public static String calculateAuthorizationCodeHash(String value, SignatureAlgorithm joseAlgo) { + return calculateHash(value, joseAlgo); + } + public static String calculateHash(String value, SignatureAlgorithm joseAlgo) { //TODO: map from the JOSE alg to a signature alg, // for example, RS256 -> SHA-256 // and calculate the chunk size based on the algo key size