Announcement Announcement Module
Collapse
No announcement yet.
How to write a x509 custom trust manager for validating the client Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • How to write a x509 custom trust manager for validating the client

    I have a web application in which I am using Spring APIs to get the principal information in the certificate to check for valid user.

    Assumption is that app server in which this is deployed contains the trust store that contains the CA's certificate and would validate the authenticity of the incoming request based on the requesting client's certificate and only then send it to the application.

    And hence I was not validating the contents of the certificate and was just validating the Common Name (Principal) part in the certificate. Now if I want to write my own trust manager in the application that would validate the certificate against the CA's certificate, How do I acheive the same in Spring?

    I know that I need to write custom truststore manager and override checkClientTrusted method, but dont know how to do it and how Spring should be configured to use this custom Trustmanager.. Do anybody know how to do this?

    thanks

    Nohsib

  • #2
    Hi

    I don't understand one thing - if client makes HTTPS requests to your web application deployed on application server, then your application, and hence Spring, is invoked after all the processing related to SSL validation using TrustStore.

    I can give you a solution where Spring (particularily Spring-WS client) makes calls to external, SSL-protected web service and must do server certificate validation using TrustStore, but that's not what you want.

    On the opposite site, If you configure app server (what: Tomcat?, WebSphere?, other?) to not reject client connection on the basis of app server's trust establishment, then you can configure Spring-Security to properly perform X.509 validation:

    Code:
       <http auto-config="false" ...>
          <!-- custom X.509 filter  -->
          <custom-filter position="X509_FILTER" ref="myX509AuthenticationFilter" />
       </http>
    
       <beans:bean id="myX509AuthenticationFilter" class="org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter">
          <beans:property name="authenticationManager" ref="authenticationManager" />
          <beans:property name="principalExtractor">
             <beans:bean class="com.example.MyX509PrincipalExtractor" />
          </beans:property>
       </beans:bean>
    com.example.MyX509PrincipalExtractor could look like this (it returns serialNumber as principal name):

    Code:
    public class MyX509PrincipalExtractor implements X509PrincipalExtractor
    {
       private static Pattern serialNumber = Pattern.compile("serialNumber=([^=,]*)", Pattern.CASE_INSENSITIVE);
    
       public Object extractPrincipal(X509Certificate cert)
       {
          String name = cert.getSubjectDN().getName();
          Matcher m = serialNumber.matcher(name);
    
          if (!m.find())
             throw new BadCredentialsException("Haven't found serialNumber in certificate.");
    
          return m.group(1);
       }
    }
    regards
    Grzegorz Grzybek

    Comment


    • #3
      Thankyou Grzegorz Grzybek. Yes I am talking about the use case where the app server's trust management is set to false (that is, it will accept any certificate presented and not validate it. In that case I want it to be handled by the application using the spring components).
      So in the above solution , only the Principal is authenticated. But the requirement is that the client's certificate signed by a CA be validated in the application.
      I would have the trust store file which contains the CA's certificate, so when the request comes in from the client,I want to use client's certificate (its CA part) and validate it against the trust store file's - CA contents. So I was thinking of having a custom trust store manager that would do it, but dont know how?

      Comment


      • #4
        Hi

        MyX509PrincipalExtractor.extractPrincipal(X509Cert ificate cert) may be the method you want to override.

        If you decide not to trust client's certificate (passed as method argument), just throw BadCredentialsException. To check if you trust client's certificate just try the following code in the form of JUnit tests:

        Code:
           @Test
           public void testTrust() throws Exception
           {
              TrustManagerFactory factory = TrustManagerFactory.getInstance("X509");
              KeyStore ks = KeyStore.getInstance("JKS");
              ks.load(getClass().getResourceAsStream("ca.keystore"), "123456".toCharArray());
              factory.init(ks);
              
              Certificate cert = CertificateFactory.getInstance("X509").generateCertificate(getClass().getResourceAsStream("localhost.cer"));
              for (TrustManager tm: factory.getTrustManagers())
                 ((X509TrustManager)tm).checkClientTrusted(new X509Certificate[] { (X509Certificate)cert }, "RSA");
           }
        
           @Test(expected = CertificateException.class)
           public void testDontTrust() throws Exception
           {
              TrustManagerFactory factory = TrustManagerFactory.getInstance("X509");
              factory.init((KeyStore)null);
              
              Certificate cert = CertificateFactory.getInstance("X509").generateCertificate(getClass().getResourceAsStream("localhost.cer"));
              for (TrustManager tm: factory.getTrustManagers())
                 ((X509TrustManager)tm).checkClientTrusted(new X509Certificate[] { (X509Certificate)cert }, "RSA");
           }
        First method check's localhost.cer against keystore which contains my own ca.cer. The second test fails (as expected), because factory is initialized with null keystore - which means - Java's default truststore containing default CA certificates.

        I hope this will help you write proper MyX509PrincipalExtractor.extractPrincipal(X509Cert ificate cert) method.

        regards
        Grzegorz Grzybek

        Comment

        Working...
        X