-
Bug
-
Resolution: Done
-
Undefined
-
None
-
False
-
-
False
-
-
Before reporting an issue
[X] I have searched existing issues
[X] I have reproduced the issue with the latest release
Area
authentication
Describe the bug
Behavior:
When we Enable X509 Browser certificate authentication and turn CRL checking on with the CRL file option, the user always fails to authenticate. This seems to be due to Keycloak expecting a chain of certificates from the Client cert rather than just the client cert. As far as I can tell, it is not standard for the client cert to contain the CA Chain, so Keycloak always end up with this error:
```20T21:27:46.901Z","sequence":8562,"loggerClassName":"org.jboss.logging.DelegatingBasicLogger","loggerName":"org.keycloak.services","level":"ERROR","message":"Not possible to verify signature on CRL. X509 certificate doesn't have CA chain available on it","threadName":"executor-thread-3","threadId":118,"mdc":{},"ndc":"","hostName":"ip-10-38-1-109.us-gov-west-1.compute.internal","processName":"QuarkusEntryPoint","processId":77,"exception":{"refId":1,"exceptionType":"java.security.GeneralSecurityException","message":"Not possible to verify signature on CRL. X509 certificate doesn't have CA chain available on it","frames":[
{"class":"org.keycloak.utils.CRLUtils","method":"check","line":55},
{"class":"org.keycloak.authentication.authenticators.x509.CertificateValidator","method":"checkRevocationStatusUsingCRL","line":737},
{"class":"org.keycloak.authentication.authenticators.x509.CertificateValidator","method":"checkRevocationStatusUsingCRLDistributionPoints","line":760},```
Can this be fixed to accept the child client cert and get its issuer from there? Rather than forcing a minimum length of two certificates?
```
public static void check(X509Certificate[] certs, X509CRL crl, KeycloakSession session) throws GeneralSecurityException { if (certs.length < 1) { throw new GeneralSecurityException("Not possible to verify signature on CRL. X509 certificate doesn't exist"); }
X500Principal crlIssuerPrincipal = crl.getIssuerX500Principal();
X509Certificate crlSignatureCertificate = null;
// Try to find the certificate in the CA chain, which was used to sign the CRL for (int i=0 ; i<certs.length ; i++) { X509Certificate currentCert = certs[i]; if (crlIssuerPrincipal.equals(currentCert.getIssuerX500Principal())) { crlSignatureCertificate = currentCert;
log.tracef("Found certificate used to sign CRL in the CA chain of the certificate. CRL issuer: %s", crlIssuerPrincipal); break; } }
```
-
-
- Version
-
21.1.0
-
-
- Expected behavior
-
Users be able to login with x509 Certificate and CRL checking to be working.
-
-
- Actual behavior
-
When CRL checking is turned on in the browser auth flow, and a CRL file is specified. Users gets rejected due to failed CRL verification.
``{{20T21:27:46.901Z","sequence":8562,"loggerClassName":"org.jboss.logging.DelegatingBasicLogger","loggerName":"org.keycloak.services","level":"ERROR","message":"Not possible to verify signature on CRL. X509 certificate doesn't have CA chain available on it","threadName":"executor-thread-3","threadId":118,"mdc":{},"ndc":"","hostName":"ip-10-38-1-109.us-gov-west-1.compute.internal","processName":"QuarkusEntryPoint","processId":77,"exception":{"refId":1,"exceptionType":"java.security.GeneralSecurityException","message":"Not possible to verify signature on CRL. X509 certificate doesn't have CA chain available on it","frames":[
{"class":"org.keycloak.utils.CRLUtils","method":"check","line":55},
{"class":"org.keycloak.authentication.authenticators.x509.CertificateValidator","method":"checkRevocationStatusUsingCRL","line":737},
{"class":"org.keycloak.authentication.authenticators.x509.CertificateValidator","method":"checkRevocationStatusUsingCRLDistributionPoints","line":760},}}``
Can this be fixed to accept the child client cert and get its issuer from there? Rather than forcing a minimum length of two certificates?
```
public static void check(X509Certificate[] certs, X509CRL crl, KeycloakSession session) throws GeneralSecurityException { if (certs.length < 1) { throw new GeneralSecurityException("Not possible to verify signature on CRL. X509 certificate doesn't exist"); }
X500Principal crlIssuerPrincipal = crl.getIssuerX500Principal();
X509Certificate crlSignatureCertificate = null;
// Try to find the certificate in the CA chain, which was used to sign the CRL for (int i=0 ; i<certs.length ; i++) { X509Certificate currentCert = certs[i]; if (crlIssuerPrincipal.equals(currentCert.getIssuerX500Principal())) { crlSignatureCertificate = currentCert;
log.tracef("Found certificate used to sign CRL in the CA chain of the certificate. CRL issuer: %s", crlIssuerPrincipal); break; } }
```
How to Reproduce?
1. Create a login Browser flow using x509 certificate check
2. Turn on CRL checking and specify a CRL file
3. Login with a certificate that is signed by a single root CA
Anything else?
No response
- links to