mirror of
https://github.com/keycloak/keycloak.git
synced 2026-05-07 23:50:03 -05:00
Improper Client Certificate Validation for OAuth/OpenID clients (#20)
Co-authored-by: Stian Thorgersen <stianst@gmail.com>
This commit is contained in:
committed by
Bruno Oliveira da Silva
parent
1973d0f0d4
commit
51a9712e59
+11
-15
@@ -130,42 +130,38 @@ public class X509ClientAuthenticator extends AbstractClientAuthenticator {
|
||||
return;
|
||||
}
|
||||
|
||||
Optional<String> matchedCertificate;
|
||||
// Testing only 1st certificate in the chain to match with configured subject
|
||||
X509Certificate certificate = certs[0];
|
||||
boolean matchedCertificate = false;
|
||||
|
||||
if (clientCfg.getAllowRegexPatternComparison()) {
|
||||
Pattern subjectDNPattern = Pattern.compile(subjectDNRegexp);
|
||||
|
||||
matchedCertificate = Arrays.stream(certs)
|
||||
.map(certificate -> certificate.getSubjectDN().getName())
|
||||
.filter(subjectdn -> subjectDNPattern.matcher(subjectdn).matches())
|
||||
.findFirst();
|
||||
String subjectdn = certificate.getSubjectDN().getName();
|
||||
matchedCertificate = subjectDNPattern.matcher(subjectdn).matches();
|
||||
} else {
|
||||
// OIDC/OAuth2 does not use regex comparison as it expects exact DN given in the format according to RFC4514. See RFC8705 for the details.
|
||||
// We allow custom OIDs attributes to be "expanded" or not expanded in the given Subject DN
|
||||
X500Principal expectedDNPrincipal = new X500Principal(subjectDNRegexp, CUSTOM_OIDS_REVERSED);
|
||||
|
||||
matchedCertificate = Arrays.stream(certs)
|
||||
.filter(certificate -> expectedDNPrincipal.getName(X500Principal.RFC2253, CUSTOM_OIDS).equals(certificate.getSubjectX500Principal().getName(X500Principal.RFC2253, CUSTOM_OIDS)))
|
||||
.map(certificate -> certificate.getSubjectDN().getName())
|
||||
.findFirst();
|
||||
matchedCertificate = (expectedDNPrincipal.getName(X500Principal.RFC2253, CUSTOM_OIDS).equals(certificate.getSubjectX500Principal().getName(X500Principal.RFC2253, CUSTOM_OIDS)));
|
||||
}
|
||||
|
||||
if (!matchedCertificate.isPresent()) {
|
||||
if (!matchedCertificate) {
|
||||
// We do quite expensive operation here, so better check the logging level beforehand.
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("[X509ClientCertificateAuthenticator:authenticate] Couldn't match any certificate for expected Subject DN '" + subjectDNRegexp + "' with allow regex pattern '" + clientCfg.getAllowRegexPatternComparison() + "'.");
|
||||
logger.debug("[X509ClientCertificateAuthenticator:authenticate] Available SubjectDNs: " +
|
||||
logger.debug("[X509ClientCertificateAuthenticator:authenticate] Checked Subject DN: " + certificate.getSubjectDN().getName());
|
||||
logger.debug("[X509ClientCertificateAuthenticator:authenticate] All SubjectDNs from the certificate chain: " +
|
||||
Arrays.stream(certs)
|
||||
.map(cert -> cert.getSubjectDN().getName())
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
context.attempted();
|
||||
return;
|
||||
} else {
|
||||
logger.debug("[X509ClientCertificateAuthenticator:authenticate] Matched " + matchedCertificate.get() + " certificate.");
|
||||
logger.debug("[X509ClientCertificateAuthenticator:authenticate] Matched " + certificate.getSubjectDN().getName() + " certificate.");
|
||||
context.success();
|
||||
}
|
||||
|
||||
context.success();
|
||||
}
|
||||
|
||||
public String getDisplayType() {
|
||||
|
||||
Reference in New Issue
Block a user