Keycloak x509 client authentication configuration

12,653

Solution 1

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).

Solution 2

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

Share:
12,653

Related videos on Youtube

HK15
Author by

HK15

Updated on June 04, 2022

Comments

  • HK15
    HK15 almost 2 years

    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?

    • coyote
      coyote over 3 years
      Is Keycloak running in the same K8s cluster with the Spring Boot application?
    • shxpark
      shxpark over 2 years
      Hey did you ever get this working? Having trouble with implementing the same use case.
  • HK15
    HK15 about 4 years
    I've read the documentation but It's not completely clear for me how to make it works. Is it supposed to: 1) generate a private / public key pair 2) extract the public certificate from the keypair 3) store the key pair in the truststore 4) store the public certificate on the client application 5) In order to authenticate send the public certificate from the client side then Keycloack check the public / private matching of the keys ... is it correct?
  • cdan
    cdan about 4 years
    Indeed, first you have to set up the keystores/truststores by yourself: 1) for the server (Keycloak) and each of your clients, you need to generate a private/public keypair (keystore), and a Certificate Signing Request (CSR) from that keypair, all that you can do with Java keytool or other PKI tool...
  • cdan
    cdan about 4 years
    ... 2) Submit the CSR to your CA (Certificate Authority) with EKU (Extended Key Usage) extension set to TLS Server (resp. Client) Authentication for the server (resp. clients), in order to get back a proper signed TLS server (resp. client) certificate (signed by the CA). If you don't own a CA, you may create one with keytool and use keytool again to sign the certificate. 3) Import back that CA-signed certificate into the server (resp. client) keystores...
  • cdan
    cdan about 4 years
    ... 4) Import the CA certificate into the server/client's truststores. In a more complex setup, you could use different CAs for the server and clients, in which case you import the server CA into client truststores, and the clients CA into the server's truststore. More info