You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2017/04/07 12:36:31 UTC
cxf git commit: Propagating X509 cert hash to OAuth2 providers,
minor updates to the JOSE code
Repository: cxf
Updated Branches:
refs/heads/master df9af7a3e -> 0eef86f37
Propagating X509 cert hash to OAuth2 providers, minor updates to the JOSE code
Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/0eef86f3
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/0eef86f3
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/0eef86f3
Branch: refs/heads/master
Commit: 0eef86f37288f71fd96506fb2ac7fa27169d1e43
Parents: df9af7a
Author: Sergey Beryozkin <sb...@gmail.com>
Authored: Fri Apr 7 13:36:16 2017 +0100
Committer: Sergey Beryozkin <sb...@gmail.com>
Committed: Fri Apr 7 13:36:16 2017 +0100
----------------------------------------------------------------------
.../rs/security/jose/common/JoseConstants.java | 10 +++
.../jose/common/KeyManagementUtils.java | 5 +-
.../cxf/rs/security/jose/jwe/JweUtils.java | 34 +++++++++-
.../cxf/rs/security/jose/jws/JwsUtils.java | 31 ++++++++-
.../oauth2/services/AbstractTokenService.java | 69 ++++----------------
.../rs/security/oauth2/utils/OAuthUtils.java | 67 +++++++++++++++++++
6 files changed, 151 insertions(+), 65 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cxf/blob/0eef86f3/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/JoseConstants.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/JoseConstants.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/JoseConstants.java
index 6abbd5f..bcf9d79 100644
--- a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/JoseConstants.java
+++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/JoseConstants.java
@@ -173,6 +173,11 @@ public final class JoseConstants {
* Include the X.509 certificate SHA-1 digest for signature in the "x5t" header.
*/
public static final String RSSEC_SIGNATURE_INCLUDE_CERT_SHA1 = "rs.security.signature.include.cert.sha1";
+
+ /**
+ * Include the X.509 certificate SHA-256 digest for signature in the "x5t#S256" header.
+ */
+ public static final String RSSEC_SIGNATURE_INCLUDE_CERT_SHA256 = "rs.security.signature.include.cert.sha1";
//
// JWE specific Configuration
@@ -236,6 +241,11 @@ public final class JoseConstants {
* Include the X.509 certificate SHA-1 digest for encryption in the "x5t" header.
*/
public static final String RSSEC_ENCRYPTION_INCLUDE_CERT_SHA1 = "rs.security.encryption.include.cert.sha1";
+
+ /**
+ * Include the X.509 certificate SHA-246 digest for encryption in the "x5t#S256" header.
+ */
+ public static final String RSSEC_ENCRYPTION_INCLUDE_CERT_SHA256 = "rs.security.encryption.include.cert.sha256";
//
// JWT specific configuration
http://git-wip-us.apache.org/repos/asf/cxf/blob/0eef86f3/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/KeyManagementUtils.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/KeyManagementUtils.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/KeyManagementUtils.java
index f599e5b..63c0b08 100644
--- a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/KeyManagementUtils.java
+++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/KeyManagementUtils.java
@@ -69,13 +69,12 @@ public final class KeyManagementUtils {
return encodeX509CertificateChain(chain);
}
- public static String loadDigestAndEncodeX509Certificate(Message m, Properties props) {
+ public static String loadDigestAndEncodeX509Certificate(Message m, Properties props, String digestAlgo) {
X509Certificate[] certs = loadX509CertificateOrChain(m, props);
if (certs != null && certs.length > 0) {
try {
byte[] digest =
- MessageDigestUtils.createDigest(certs[0].getEncoded(),
- MessageDigestUtils.ALGO_SHA_1);
+ MessageDigestUtils.createDigest(certs[0].getEncoded(), digestAlgo);
return Base64UrlUtility.encode(digest);
} catch (NoSuchAlgorithmException ex) {
LOG.log(Level.FINE, "Error creating digest", ex);
http://git-wip-us.apache.org/repos/asf/cxf/blob/0eef86f3/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java
index 613fc77..3d851f8 100644
--- a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java
+++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java
@@ -347,6 +347,8 @@ public final class JweUtils {
m, JoseConstants.RSSEC_ENCRYPTION_INCLUDE_CERT, false);
boolean includeCertSha1 = headers != null && MessageUtils.getContextualBoolean(
m, JoseConstants.RSSEC_ENCRYPTION_INCLUDE_CERT_SHA1, false);
+ boolean includeCertSha256 = !includeCertSha1 && headers != null && MessageUtils.getContextualBoolean(
+ m, JoseConstants.RSSEC_ENCRYPTION_INCLUDE_CERT_SHA256, false);
KeyEncryptionProvider keyEncryptionProvider = null;
KeyAlgorithm keyAlgo = getKeyEncryptionAlgorithm(m, props, null, null);
@@ -377,10 +379,17 @@ public final class JweUtils {
JwkUtils.includeCertChain(jwk, headers, keyAlgo.getJwaName());
}
if (includeCertSha1) {
- String digest = KeyManagementUtils.loadDigestAndEncodeX509Certificate(m, props);
+ String digest = KeyManagementUtils.loadDigestAndEncodeX509Certificate(m,
+ props, MessageDigestUtils.ALGO_SHA_1);
if (digest != null) {
headers.setX509Thumbprint(digest);
}
+ } else if (includeCertSha256) {
+ String digest = KeyManagementUtils.loadDigestAndEncodeX509Certificate(m,
+ props, MessageDigestUtils.ALGO_SHA_256);
+ if (digest != null) {
+ headers.setX509ThumbprintSHA256(digest);
+ }
}
if (includePublicKey) {
JwkUtils.includePublicKey(jwk, headers, keyAlgo.getJwaName());
@@ -398,10 +407,17 @@ public final class JweUtils {
headers.setX509Chain(KeyManagementUtils.loadAndEncodeX509CertificateOrChain(m, props));
}
if (includeCertSha1) {
- String digest = KeyManagementUtils.loadDigestAndEncodeX509Certificate(m, props);
+ String digest = KeyManagementUtils.loadDigestAndEncodeX509Certificate(m,
+ props, MessageDigestUtils.ALGO_SHA_1);
if (digest != null) {
headers.setX509Thumbprint(digest);
}
+ } else if (includeCertSha256) {
+ String digest = KeyManagementUtils.loadDigestAndEncodeX509Certificate(m,
+ props, MessageDigestUtils.ALGO_SHA_256);
+ if (digest != null) {
+ headers.setX509ThumbprintSHA256(digest);
+ }
}
}
@@ -460,6 +476,20 @@ public final class JweUtils {
contentAlgo = inHeaders.getContentEncryptionAlgorithm();
keyDecryptionProvider = getPrivateKeyDecryptionProvider(privateKey, keyAlgo);
}
+ } else if (inHeaders != null && inHeaders.getHeader(JoseConstants.HEADER_X509_THUMBPRINT_SHA256) != null) {
+ X509Certificate foundCert =
+ KeyManagementUtils.getCertificateFromThumbprint(inHeaders.getX509ThumbprintSHA256(),
+ MessageDigestUtils.ALGO_SHA_256,
+ m, props);
+ if (foundCert != null) {
+ PrivateKey privateKey =
+ KeyManagementUtils.loadPrivateKey(m, props, foundCert, KeyOperation.DECRYPT);
+ if (keyAlgo == null) {
+ keyAlgo = getDefaultPrivateKeyAlgorithm(privateKey);
+ }
+ contentAlgo = inHeaders.getContentEncryptionAlgorithm();
+ keyDecryptionProvider = getPrivateKeyDecryptionProvider(privateKey, keyAlgo);
+ }
} else {
if (JoseConstants.HEADER_JSON_WEB_KEY.equals(props.get(JoseConstants.RSSEC_KEY_STORE_TYPE))) {
JsonWebKey jwk = JwkUtils.loadJsonWebKey(m, props, KeyOperation.DECRYPT);
http://git-wip-us.apache.org/repos/asf/cxf/blob/0eef86f3/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java
index 25f12ba..cd5a008 100644
--- a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java
+++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java
@@ -342,6 +342,8 @@ public final class JwsUtils {
m, JoseConstants.RSSEC_SIGNATURE_INCLUDE_CERT, false);
boolean includeCertSha1 = headers != null && MessageUtils.getContextualBoolean(
m, JoseConstants.RSSEC_SIGNATURE_INCLUDE_CERT_SHA1, false);
+ boolean includeCertSha256 = !includeCertSha1 && headers != null && MessageUtils.getContextualBoolean(
+ m, JoseConstants.RSSEC_SIGNATURE_INCLUDE_CERT_SHA256, false);
boolean includeKeyId = headers != null && MessageUtils.getContextualBoolean(
m, JoseConstants.RSSEC_SIGNATURE_INCLUDE_KEY_ID, false);
@@ -361,10 +363,17 @@ public final class JwsUtils {
JwkUtils.includeCertChain(jwk, headers, signatureAlgo.getJwaName());
}
if (includeCertSha1) {
- String digest = KeyManagementUtils.loadDigestAndEncodeX509Certificate(m, props);
+ String digest = KeyManagementUtils.loadDigestAndEncodeX509Certificate(m,
+ props, MessageDigestUtils.ALGO_SHA_1);
if (digest != null) {
headers.setX509Thumbprint(digest);
}
+ } else if (includeCertSha256) {
+ String digest = KeyManagementUtils.loadDigestAndEncodeX509Certificate(m,
+ props, MessageDigestUtils.ALGO_SHA_256);
+ if (digest != null) {
+ headers.setX509ThumbprintSHA256(digest);
+ }
}
if (includePublicKey) {
JwkUtils.includePublicKey(jwk, headers, signatureAlgo.getJwaName());
@@ -388,11 +397,18 @@ public final class JwsUtils {
headers.setX509Chain(KeyManagementUtils.loadAndEncodeX509CertificateOrChain(m, props));
}
if (includeCertSha1) {
- String digest = KeyManagementUtils.loadDigestAndEncodeX509Certificate(m, props);
+ String digest = KeyManagementUtils.loadDigestAndEncodeX509Certificate(m,
+ props, MessageDigestUtils.ALGO_SHA_1);
if (digest != null) {
headers.setX509Thumbprint(digest);
}
- }
+ } else if (includeCertSha256) {
+ String digest = KeyManagementUtils.loadDigestAndEncodeX509Certificate(m,
+ props, MessageDigestUtils.ALGO_SHA_256);
+ if (digest != null) {
+ headers.setX509ThumbprintSHA256(digest);
+ }
+ }
if (includeKeyId && props.containsKey(JoseConstants.RSSEC_KEY_STORE_ALIAS)) {
headers.setKeyId(props.getProperty(JoseConstants.RSSEC_KEY_STORE_ALIAS));
}
@@ -440,6 +456,15 @@ public final class JwsUtils {
return getPublicKeySignatureVerifier(foundCert,
inHeaders.getSignatureAlgorithm());
}
+ } else if (inHeaders.getHeader(JoseConstants.HEADER_X509_THUMBPRINT_SHA256) != null) {
+ X509Certificate foundCert =
+ KeyManagementUtils.getCertificateFromThumbprint(inHeaders.getX509ThumbprintSHA256(),
+ MessageDigestUtils.ALGO_SHA_256,
+ m, props);
+ if (foundCert != null) {
+ return getPublicKeySignatureVerifier(foundCert,
+ inHeaders.getSignatureAlgorithm());
+ }
}
}
http://git-wip-us.apache.org/repos/asf/cxf/blob/0eef86f3/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractTokenService.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractTokenService.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractTokenService.java
index 5992d04..826e86d 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractTokenService.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractTokenService.java
@@ -20,19 +20,15 @@
package org.apache.cxf.rs.security.oauth2.services;
import java.security.Principal;
-import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
-import java.util.Arrays;
import java.util.List;
-import javax.security.auth.x500.X500Principal;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.SecurityContext;
-import org.apache.cxf.common.util.Base64Utility;
import org.apache.cxf.common.util.StringUtils;
import org.apache.cxf.jaxrs.utils.ExceptionUtils;
import org.apache.cxf.jaxrs.utils.JAXRSUtils;
@@ -43,6 +39,7 @@ import org.apache.cxf.rs.security.oauth2.provider.ClientSecretVerifier;
import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException;
import org.apache.cxf.rs.security.oauth2.utils.AuthorizationUtils;
import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
+import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils;
import org.apache.cxf.security.transport.TLSSessionInfo;
public class AbstractTokenService extends AbstractOAuthService {
@@ -65,7 +62,7 @@ public class AbstractTokenService extends AbstractOAuthService {
String clientSecret = params.getFirst(OAuthConstants.CLIENT_SECRET);
if (clientSecret != null) {
client = getAndValidateClientFromIdAndSecret(clientId, clientSecret, params);
- } else if (isMutualTls(sc, getTlsSessionInfo())) {
+ } else if (OAuthUtils.isMutualTls(sc, getTlsSessionInfo())) {
client = getClient(clientId, params);
checkCertificateBinding(client, getTlsSessionInfo());
}
@@ -154,21 +151,23 @@ public class AbstractTokenService extends AbstractOAuthService {
LOG.warning("Client \"" + client.getClientId() + "\" can not be bound to the TLS cerificate");
reportInvalidClient();
}
+ X509Certificate cert = OAuthUtils.getRootTLSCertificate(tlsSessionInfo);
if (subjectDn != null
- && !subjectDn.equals(getSubjectDnFromTLSCertificates(tlsSessionInfo))) {
+ && !subjectDn.equals(OAuthUtils.getSubjectDnFromTLSCertificates(cert))) {
LOG.warning("Client \"" + client.getClientId() + "\" can not be bound to the TLS cerificate");
reportInvalidClient();
}
String issuerDn = client.getProperties().get(OAuthConstants.TLS_CLIENT_AUTH_ISSUER_DN);
if (issuerDn != null
- && !issuerDn.equals(getIssuerDnFromTLSCertificates(tlsSessionInfo))) {
+ && !issuerDn.equals(OAuthUtils.getIssuerDnFromTLSCertificates(cert))) {
LOG.warning("Client \"" + client.getClientId() + "\" can not be bound to the TLS cerificate");
reportInvalidClient();
}
if (!client.getApplicationCertificates().isEmpty()) {
compareTlsCertificates(tlsSessionInfo, client.getApplicationCertificates());
}
+ OAuthUtils.setCertificateThumbprintConfirmation(getMessageContext(), cert);
}
private TLSSessionInfo getTlsSessionInfo() {
@@ -181,71 +180,27 @@ public class AbstractTokenService extends AbstractOAuthService {
TLSSessionInfo tlsSessionInfo,
MultivaluedMap<String, String> params) {
Client client = null;
- if (isMutualTls(sc, tlsSessionInfo)) {
- String subjectDn = getSubjectDnFromTLSCertificates(tlsSessionInfo);
+ if (OAuthUtils.isMutualTls(sc, tlsSessionInfo)) {
+ X509Certificate cert = OAuthUtils.getRootTLSCertificate(tlsSessionInfo);
+ String subjectDn = OAuthUtils.getSubjectDnFromTLSCertificates(cert);
if (!StringUtils.isEmpty(subjectDn)) {
client = getClient(subjectDn, params);
// The certificates must be registered with the client and match TLS certificates
// in case of the binding where Client's clientId is a subject distinguished name
compareTlsCertificates(tlsSessionInfo, client.getApplicationCertificates());
+ OAuthUtils.setCertificateThumbprintConfirmation(getMessageContext(), cert);
}
}
return client;
}
- protected boolean isMutualTls(SecurityContext sc, TLSSessionInfo tlsSessionInfo) {
- // Pure 2-way TLS authentication
- return tlsSessionInfo != null && StringUtils.isEmpty(sc.getAuthenticationScheme());
- }
-
- protected String getSubjectDnFromTLSCertificates(TLSSessionInfo tlsInfo) {
- X509Certificate cert = getRootTLSCertificate(tlsInfo);
- if (cert != null) {
- X500Principal x509Principal = cert.getSubjectX500Principal();
- return x509Principal.getName();
- }
- return null;
- }
-
- protected String getIssuerDnFromTLSCertificates(TLSSessionInfo tlsInfo) {
- X509Certificate cert = getRootTLSCertificate(tlsInfo);
- if (cert != null) {
- X500Principal x509Principal = cert.getIssuerX500Principal();
- return x509Principal.getName();
- }
- return null;
- }
- protected X509Certificate getRootTLSCertificate(TLSSessionInfo tlsInfo) {
- Certificate[] clientCerts = tlsInfo.getPeerCertificates();
- if (clientCerts != null && clientCerts.length > 0) {
- return (X509Certificate)clientCerts[0];
- }
- return null;
- }
-
protected void compareTlsCertificates(TLSSessionInfo tlsInfo,
List<String> base64EncodedCerts) {
- Certificate[] clientCerts = tlsInfo.getPeerCertificates();
- if (clientCerts.length == base64EncodedCerts.size()) {
- try {
- for (int i = 0; i < clientCerts.length; i++) {
- X509Certificate x509Cert = (X509Certificate)clientCerts[i];
- byte[] encodedKey = x509Cert.getEncoded();
- byte[] clientKey = Base64Utility.decode(base64EncodedCerts.get(i));
- if (!Arrays.equals(encodedKey, clientKey)) {
- reportInvalidClient();
- }
- }
- return;
- } catch (Exception ex) {
- // throw exception later
- }
+ if (!OAuthUtils.compareTlsCertificates(tlsInfo, base64EncodedCerts)) {
+ reportInvalidClient();
}
- reportInvalidClient();
}
-
-
protected Response handleException(OAuthServiceException ex, String error) {
OAuthError customError = ex.getError();
if (writeCustomErrors && customError != null) {
http://git-wip-us.apache.org/repos/asf/cxf/blob/0eef86f3/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 743147e..c742e58 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
@@ -20,7 +20,10 @@ package org.apache.cxf.rs.security.oauth2.utils;
import java.lang.reflect.Method;
import java.security.Principal;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
@@ -28,9 +31,12 @@ import java.util.List;
import java.util.Properties;
import java.util.Set;
+import javax.security.auth.x500.X500Principal;
import javax.servlet.http.HttpSession;
import javax.ws.rs.core.MultivaluedMap;
+import org.apache.cxf.common.util.Base64UrlUtility;
+import org.apache.cxf.common.util.Base64Utility;
import org.apache.cxf.common.util.StringUtils;
import org.apache.cxf.jaxrs.ext.MessageContext;
import org.apache.cxf.jaxrs.impl.MetadataMap;
@@ -55,8 +61,10 @@ 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.rt.security.crypto.CryptoUtils;
+import org.apache.cxf.rt.security.crypto.MessageDigestUtils;
import org.apache.cxf.security.LoginSecurityContext;
import org.apache.cxf.security.SecurityContext;
+import org.apache.cxf.security.transport.TLSSessionInfo;
/**
* Various utility methods
@@ -66,6 +74,65 @@ public final class OAuthUtils {
private OAuthUtils() {
}
+
+ public static void setCertificateThumbprintConfirmation(MessageContext mc, X509Certificate cert) {
+ try {
+ byte[] thumbprint =
+ MessageDigestUtils.createDigest(cert.getEncoded(), MessageDigestUtils.ALGO_SHA_256);
+ String encodedThumbprint = Base64UrlUtility.encode(thumbprint);
+ mc.put("x5t#S256", encodedThumbprint);
+ } catch (Exception ex) {
+ throw new OAuthServiceException(ex);
+ }
+ }
+
+
+ public static boolean compareTlsCertificates(TLSSessionInfo tlsInfo,
+ List<String> base64EncodedCerts) {
+ Certificate[] clientCerts = tlsInfo.getPeerCertificates();
+ if (clientCerts.length == base64EncodedCerts.size()) {
+ try {
+ for (int i = 0; i < clientCerts.length; i++) {
+ X509Certificate x509Cert = (X509Certificate)clientCerts[i];
+ byte[] encodedKey = x509Cert.getEncoded();
+ byte[] clientKey = Base64Utility.decode(base64EncodedCerts.get(i));
+ if (!Arrays.equals(encodedKey, clientKey)) {
+ return false;
+ }
+ }
+ return true;
+ } catch (Exception ex) {
+ // throw exception later
+ }
+ }
+ return false;
+ }
+
+ public static boolean isMutualTls(javax.ws.rs.core.SecurityContext sc, TLSSessionInfo tlsSessionInfo) {
+ // Pure 2-way TLS authentication
+ return tlsSessionInfo != null
+ && StringUtils.isEmpty(sc.getAuthenticationScheme())
+ && getRootTLSCertificate(tlsSessionInfo) != null;
+ }
+
+ public static String getSubjectDnFromTLSCertificates(X509Certificate cert) {
+ X500Principal x509Principal = cert.getSubjectX500Principal();
+ return x509Principal.getName();
+ }
+
+ public static String getIssuerDnFromTLSCertificates(X509Certificate cert) {
+ X500Principal x509Principal = cert.getIssuerX500Principal();
+ return x509Principal.getName();
+ }
+
+ public static X509Certificate getRootTLSCertificate(TLSSessionInfo tlsInfo) {
+ Certificate[] clientCerts = tlsInfo.getPeerCertificates();
+ if (clientCerts != null && clientCerts.length > 0) {
+ return (X509Certificate)clientCerts[0];
+ }
+ return null;
+ }
+
public static void injectContextIntoOAuthProvider(MessageContext context, Object provider) {
Method dataProviderContextMethod = null;
try {