Keycloak x509 client authentication configuration - authentication

I need some tips in order to understand how to perform a client authentication with x509 certificate against Keycloak.
We have a simple Spring Boot Web App (API REST) into a Kubernetes cluster.
This Web App is public exsposed through an API Gateway (Ambassador) and currently protected with a browser redirection to the Keycloak login page where user can input his username and password.
However this is not what we want.
What is necessary for us is a client authentication (React Native Mobile App) where:
Mobile App try to call our Server API REST endpoints
Ambassador check for a valid access token and (if not) respond with a 403 http status (no browser redirection)
Mobile App then redirect to Keycloak in order to perform the authentication
Keycloak doesn't show username/password login page but, instead, Mobile App pass a x509 user certificate through its Browser.
Unfortunately I can't understand how to generate a valid and trusted x509 certificate with user data (info, roles ecc.) in order to get an access token from the IdP.
And ... how can IdP check and validate this client certificate? Is it necessary a Server certificate counterpart somewhere installed on Keycloak?
What's the correct form (ex with CURL) to pass the client certificate to keycloak?
Is it neccessary to pass also the private key and why?

Please check the section X.509 Client Certificate User Authentication in section 6 of Keycloak Server Administration Guide, which describes:
how to enable and configure client certificate authentication in Wildfly and Keycloak
how to map certificate fields to user attributes
the client certificate authentication workflow with Keycloak/Wildfly (Keycloak container).

Unfortunately I can't understand how to generate a valid and trusted x509 certificate with user data (info, roles ecc.) in order to get an access token from the IdP.
Have a look a this article to generate a certificate How to create a self-signed certificate with OpenSSL
How can IdP check and validate this client certificate?
Keycloak documentation is a good starting point, check "Adding X.509 Client Certificate Authentication to a Browser Flow" and "Adding X.509 Client Certificate Authentication to a Direct Grant Flow"
if you need the whole DN for user key, you can use this RegEx on the config X509 :
set "A regular expression to extract user identity" : (.*)
add a user attribute called "usercertificate" for example and copy DN in it.
Is it necessary a Server certificate counterpart somewhere installed on Keycloak?
Not all the certificate, you can add only the DN in a user user attribute called "usercertificate".
What's the correct form (ex with CURL) to pass the client certificate to keycloak?
URL : https://localhost:9445/auth/realms//protocol/openid-connect/token
Example of code to open Keycloak TLS session :
public String openSession(
File p12File,
String passphrase,
String clientId)
throws IOException, GeneralSecurityException {
try (FileInputStream fis = new FileInputStream(p12File);) {
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream(p12File), passphrase.toCharArray());
HttpClient httpClient = HttpClients
.custom()
.setSSLContext(new SSLContextBuilder()
.loadTrustMaterial(null, TrustAllStrategy.INSTANCE)
.loadKeyMaterial(keyStore, passphrase.toCharArray())
.build())
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.build();
HttpPost httpPost = new HttpPost(tokenEndpoint);
httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded");
String data = "grant_type=password" + "&client_id="+ clientId;
StringEntity input = new StringEntity(data);
httpPost.setEntity(input);
HttpResponse response = httpClient.execute(httpPost);
return IOUtils.toString(response.getEntity().getContent(), "UTF-8");
}
}
Is it neccessary to pass also the private key and why?
no

Related

How do Azure Function Apps handle Client Certificate Auth?

Hopefully I can make this clear enough.
Goal:
Client Certificate-Authenticated Azure Function
Scenario:
Azure Function App with:
HTTPS Only: set to Yes
Client certificate mode: set to Require
HTTP-triggered Azure Function (Python) which:
Loads client certificate from X-ARR-ClientCert header
Pulls a pre-shared client cert from a database and compares:
Issuer
CommonName
Not Valid Before/After
Hits the listed OCSP endpoint to see if cert is revoked
If properties from each cert match and the certificate has not been revoked, the Function will generate a SAS token for the requestor and send it in the response.
Question:
How is the cryptographic part of client cert auth handled in this scenario?
According to this (great) blog post, there is a CertificateVerify step where...
"The client is authenticated by using its private key to sign a
hash of all the messages up to this point. The recipient verifies
the signature using the public key of the signer, thus ensuring it
was signed with the client’s private key."
I don't see a way to access ...all the messages up to this point. to validate this has occured using the Function (Python) code.
Is this something Microsoft handles automagically (similar to how they forward client certs via the X-ARR-ClientCert header)? Or is this not possible?
From what I implemented in a similar case:
Your app received the certificate via the header and must:
load the certificate (using the library cryptography in python for example)
verify the signature of the certificate with you certificate authority
verify the date of validity
verify that it has not been revoked
Using web app (but the same would apply to functions), the Azure frontend seems to just launch authentication protocol to verify that the client that send the certificate has the private key associated (and launch the mutual auth protocol as described in the blog post). But it does not verify the validity or signature of the certificate.
The CertificateVerify step you're mentionning seems to be handled by the Azure Frontend, I don't think your need to worry about this process.
Hopes this helps !

use SSL Client Certificate for further server side authentification

If Tomcat is set up for SSL mutual authentication you can get the client javax.servlet.request.X509Certificate from the servlet request.
In the server app I need a key to encrypt a file.
Is it a good idea to use a part of the Client X509Certificate, e.g. the SubjectPublicKeyInfo as encryption key?
The client Certificate should be as secret as any password, shouldn't it?
(this question has Java API example, but is not Java specific)

ADFS Client Certificate Authentication with CN and Subject Alternate Name different from UPN

I am trying to implement client authentication for a SharePoint application using client certificate authentication.
The certificate for the users are issued by an external certificate authority and we map the certificate to users in the Active Firectory by name mapping the certificate value for CN. However, the CN of the certificate does not match the UPN in Active Directory and I have no control for how the CN is created (external CA).
When users are trying to log in by the client certificate(we enable the external authentication withe certificate + add all root CA to the Trusted store so the client certificate can be trusted), the user gets prompted to choose the certificate and after that, they receive the the following error:
The Federation Service encountered an error while processing the WS-Trust request.
Request type: schemas.microsoft.com/idfx/requesttype/issue
Additional Data
Exception details:
System.ComponentModel.Win32Exception (0x80004005): The user name or password is incorrect at Microsoft.IdentityModel.Tokens.X509SecurityTokenHandler.KerberosCertificateLogon(X509Certificate2 certificate) at Microsoft.IdentityModel.Claims.WindowsClaimsIdentity.CertificateLogon(X509Certificate2 x509Certificate) at Microsoft.IdentityModel.Claims.WindowsClaimsIdentity.CreateFromCertificate(X509Certificate2 certificate, Boolean useWindowsTokenService, String issuerName) atMicrosoft.IdentityModel.Tokens.X509SecurityTokenHandler.ValidateToken(SecurityToken token) at Microsoft.IdentityServer.Service.Tokens.MSISX509SecurityTokenHandler.ValidateToken(SecurityToken token) at Microsoft.IdentityServer.Web.WSTrust.SecurityTokenServiceManager.GetEffectivePrincipal(SecurityTokenElement securityTokenElement, SecurityTokenHandlerCollection securityTokenHandlerCollection) at Microsoft.IdentityServer.Web.WSTrust.SecurityTokenServiceManager.Issue(RequestSecurityToken request, IList1& identityClaimSet, List1 additionalClaims)
Ensure that the Alternate ID match is done with the thumbprint of the certificate.
Based on your error message some possible scenarios are:
Your ADFS service account cannot read the pwdlastset value from users
in your child domain - check effective permissions.
The users in the child domain have never set a password, or the value for pwdlastset is set to a very large or very small value that cannot be proceed by
file time -this might happen if the users are provisioned with an
Identity Management tool that is writing to the AD database in a
specific way.
Manually create a user in the child domain and see if the user can login. If it cannot, disable inheritance on the object and assign read all properties permission to the service account - remove any Deny permissions from the user.

How can I validate LDAP SSL Certificates Against the local truststore for .NET

I am trying to implement secure LDAP using SSL and I want to validate the servers certificate against the local keystore for which I have imported the certificate.
I realize I can do this:
ldapConnection.SessionOptions.VerifyServerCertificate =
new VerifyServerCertificateCallback((con, cer) => true);
But that provides no authentication and will accept any cert. When I use SSL with WCF connections, it will automatically use my keystore by default without me having to supply a delegate at all, and that works perfect.
How can can direct the cert validation for an LDAP connection to my trust store? Can I implement the delegate, and then pass the X509Certificate arg to something else that will validate it against my store?
I have to use .NET 4.0

validate x509 client certificate

I am working on a login page using spring security. The page need to provide an option for user to use their certificate instead of username and password. However I am stuck in following scenarios :
Say you have a certificate signed by XYZ company installed in your browser. Now server (trusted XYZ) wanted to validate the certificate... but questions are :
Q1. How can server 'request' browser to provide "the right certificate" (assuming you have more than one certificate installed in your browser)?
Q2. Is it possible to have a button on the login page for user to send his certificate only when he click on the button?
Q3. Say the server received your certificate, can the server say "yes, you have proof who you said you are" simply by looking into the certificate chain (signed by XYZ company)?
Thanks,
From a security newbie :)
This is possible. All you'd have to do would be to setup an ssl site with client certificates required. Browsers support this out of the box, most present an internal cert store, ie shows a user cert store from the os. You should consult your server framework docs on how to turn on the client cert requirement on the ssl connection.
As for q2, you could have two websites, your app and your auth provider. The app shows the button and this redirects to your auth provider which requires the client certificate. Then, the auth provider uses any sso protocol (oauth2, saml) to return the user identity to the application.
As for cert validation, you could either validate the chain or have a mapping between usernames and cert thumbprints at the server side.