Uploaded image for project: 'Keycloak'
  1. Keycloak
  2. KEYCLOAK-9554

Certificate subject DN is provider dependent

    XMLWordPrintable

Details

    • Bug
    • Status: Closed
    • Minor
    • Resolution: Done
    • 4.8.3.Final
    • 6.0.1
    • Authentication
    • None
    • Hide

      public class DnTest
      {

      private static String CERT = "MIIDQzCCAqygAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwTjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFDASBgNVBAoMC2V4YW1wbGUuY29tMRQwEgYDVQQDDAtleGFtcGxlLmNvbTAeFw0xMTEwMjIwNjI0MzFaFw0xMjEwMDQwNjI0MzFaMH8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRQwEgYDVQQKDAtleGFtcGxlLmNvbTEhMB8GA1UEAwwYTXMuIEJhcmJhcmEgSiBKZW5zZW4gSUlJMSIwIAYJKoZIhvcNAQkBFhNiamVuc2VuQGV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7Kr+Dcds/JQ5GwejJFcBIP682X3xpjis56AK02bc1FLgzdLI8auoR+cC9/Vrh5t66HkQIOdA4unHh0AaZ4xL5PhVbXIPMB5vAPKpzz5iPSi8xO8SL7I7SDhcBVJhqVqr3HgllEG6UClDdHO7nkLuwXq8HcISKkbT5WFTVfFZzidPl8HZ7DhXkZIRtJwBweq4bvm3hM1Os7UQH05ZS6cVDgweKNwdLLrT51ikSQG3DYrl+ft781UQRIqxgwqCfXEuDiinPh0kkvIi5jivVu1Z9QiwlYEdRbLJ4zJQBmDrSGTMYn4lRc2HgHO4DqB/bnMVorHB0CC6AV1QoFK4GPe1LwIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQU8pD0U0vsZIsaA16lL8En8bx0F/gwHwYDVR0jBBgwFoAUdGeKitcaF7gnzsNwDx708kqaVt0wDQYJKoZIhvcNAQEFBQADgYEAA81SsFnOdYJtNg5Tcq+/ByEDrBgnusx0jloUhByPMEVkoMZ3J7j1ZgI8rAbOkNngX8+pKfTiDz1RC4+dx8oU6Za+4NJXUjlL5CvV6BEYb1+QAEJwitTVvxB/A67g42/vzgAtoRUeDov1+GFiBZ+GNF/cAYKcMtGcrs2i97ZkJMo=";

      @Test
      public void test() throws Exception

      { X509Certificate cert = PemUtils.decodeCertificate(CERT); System.out.println("BouncyCastle: " + cert.getSubjectDN().getName()); System.out.println("BouncyCastle: " + cert.getSubjectX500Principal().getName(X500Principal.RFC1779)); System.out.println("BouncyCastle: " + cert.getSubjectX500Principal().getName(X500Principal.RFC2253)); System.out.println("BouncyCastle: " + cert.getSubjectX500Principal().getName(X500Principal.CANONICAL)); CertificateFactory cf = CertificateFactory.getInstance("X.509"); cert = (X509Certificate)cf.generateCertificate(new Base64DecoderStream(new ByteArrayInputStream(CERT.getBytes()))); System.out.println("SUN : " + cert.getSubjectDN().getName()); System.out.println("SUN : " + cert.getSubjectX500Principal().getName(X500Principal.RFC1779)); System.out.println("SUN : " + cert.getSubjectX500Principal().getName(X500Principal.RFC2253)); System.out.println("SUN : " + cert.getSubjectX500Principal().getName(X500Principal.CANONICAL)); }

      }

      Show
      public class DnTest { private static String CERT = "MIIDQzCCAqygAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwTjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFDASBgNVBAoMC2V4YW1wbGUuY29tMRQwEgYDVQQDDAtleGFtcGxlLmNvbTAeFw0xMTEwMjIwNjI0MzFaFw0xMjEwMDQwNjI0MzFaMH8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRQwEgYDVQQKDAtleGFtcGxlLmNvbTEhMB8GA1UEAwwYTXMuIEJhcmJhcmEgSiBKZW5zZW4gSUlJMSIwIAYJKoZIhvcNAQkBFhNiamVuc2VuQGV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7Kr+Dcds/JQ5GwejJFcBIP682X3xpjis56AK02bc1FLgzdLI8auoR+cC9/Vrh5t66HkQIOdA4unHh0AaZ4xL5PhVbXIPMB5vAPKpzz5iPSi8xO8SL7I7SDhcBVJhqVqr3HgllEG6UClDdHO7nkLuwXq8HcISKkbT5WFTVfFZzidPl8HZ7DhXkZIRtJwBweq4bvm3hM1Os7UQH05ZS6cVDgweKNwdLLrT51ikSQG3DYrl+ft781UQRIqxgwqCfXEuDiinPh0kkvIi5jivVu1Z9QiwlYEdRbLJ4zJQBmDrSGTMYn4lRc2HgHO4DqB/bnMVorHB0CC6AV1QoFK4GPe1LwIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQU8pD0U0vsZIsaA16lL8En8bx0F/gwHwYDVR0jBBgwFoAUdGeKitcaF7gnzsNwDx708kqaVt0wDQYJKoZIhvcNAQEFBQADgYEAA81SsFnOdYJtNg5Tcq+/ByEDrBgnusx0jloUhByPMEVkoMZ3J7j1ZgI8rAbOkNngX8+pKfTiDz1RC4+dx8oU6Za+4NJXUjlL5CvV6BEYb1+QAEJwitTVvxB/A67g42/vzgAtoRUeDov1+GFiBZ+GNF/cAYKcMtGcrs2i97ZkJMo="; @Test public void test() throws Exception { X509Certificate cert = PemUtils.decodeCertificate(CERT); System.out.println("BouncyCastle: " + cert.getSubjectDN().getName()); System.out.println("BouncyCastle: " + cert.getSubjectX500Principal().getName(X500Principal.RFC1779)); System.out.println("BouncyCastle: " + cert.getSubjectX500Principal().getName(X500Principal.RFC2253)); System.out.println("BouncyCastle: " + cert.getSubjectX500Principal().getName(X500Principal.CANONICAL)); CertificateFactory cf = CertificateFactory.getInstance("X.509"); cert = (X509Certificate)cf.generateCertificate(new Base64DecoderStream(new ByteArrayInputStream(CERT.getBytes()))); System.out.println("SUN : " + cert.getSubjectDN().getName()); System.out.println("SUN : " + cert.getSubjectX500Principal().getName(X500Principal.RFC1779)); System.out.println("SUN : " + cert.getSubjectX500Principal().getName(X500Principal.RFC2253)); System.out.println("SUN : " + cert.getSubjectX500Principal().getName(X500Principal.CANONICAL)); } }
    • NEW
    • NEW

    Description

      I am currently working on configuring keycloak for X.509 certificate login.
      We store the whole user certificate's subject DN as user attribute. During the login we match the authentication certificate's subjectDN against the value stored in the user attributes.
      The subject DN is determined executing:

      cert.getSubjectDN().getName()
      

      Here we have a problem regarding the subject DN order. We realized that the subject DN order is security provider specific:

      • Using SUN security provider we get a subject DN like:
        "EMAILADDRESS=bjensen@example.com, CN=Ms. Barbara J Jensen III, O=example.com, ST=California, C=US"
      • Using BouncyCastle security provider we get a subject DN like:
        "C=US,ST=California,O=example.com,CN=Ms. Barbara J Jensen III,E=bjensen@example.com"
        This is obviously a problem.
        Does anybody else ran into the same problem?

      In my opinion it would be better to use:

      cert.getSubjectX500Principal().getName(X500Principal.CANONICAL)
      

      to determine the subject DN, as the result is provider independent.
      But this would be an backward incompatible change in Method

      org.keycloak.authentication.authenticators.x509.AbstractX509ClientCertificateAuthenticator.UserIdentityExtractorBuilder.fromConfig()
      

      Attachments

        Activity

          People

            Unassigned Unassigned
            gov.slo Sebastian Löscht (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: