<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<body link="#355491" alink="#4262a1" vlink="#355491" style="background: #e2e2e2; margin: 0; padding: 20px;">
<div>
<table cellpadding="0" bgcolor="#FFFFFF" border="0" cellspacing="0" style="border: 1px solid #dadada; margin-bottom: 30px; width: 100%; -moz-border-radius: 6px; -webkit-border-radius: 6px;">
<tbody>
<tr>
<td>
<table border="0" cellpadding="0" cellspacing="0" bgcolor="#FFFFFF" style="border: solid 2px #ccc; background: #dadada; width: 100%; -moz-border-radius: 6px; -webkit-border-radius: 6px;">
<tbody>
<tr>
<td bgcolor="#000000" valign="middle" height="58px" style="border-bottom: 1px solid #ccc; padding: 20px; -moz-border-radius-topleft: 3px; -moz-border-radius-topright: 3px; -webkit-border-top-right-radius: 5px; -webkit-border-top-left-radius: 5px;">
<h1 style="color: #333333; font: bold 22px Arial, Helvetica, sans-serif; margin: 0; display: block !important;">
<!-- To have a header image/logo replace the name below with your img tag -->
<!-- Email clients will render the images when the message is read so any image -->
<!-- must be made available on a public server, so that all recipients can load the image. -->
<a href="http://community.jboss.org/index.jspa" style="text-decoration: none; color: #E1E1E1">JBoss Community</a></h1>
</td>
</tr>
<tr>
<td bgcolor="#FFFFFF" style="font: normal 12px Arial, Helvetica, sans-serif; color:#333333; padding: 20px; -moz-border-radius-bottomleft: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 5px; -webkit-border-bottom-left-radius: 5px;"><h3 style="margin: 10px 0 5px; font-size: 17px; font-weight: normal;">
CLIENT-CERT enabled EJB3 in JBoss5.1
</h3>
<span style="margin-bottom: 10px;">
modified by <a href="http://community.jboss.org/people/admin">Administrator Administrator</a> in <i>EJB3</i> - <a href="http://community.jboss.org/docs/DOC-15734">View the full document</a>
</span>
<hr style="margin: 20px 0; border: none; background-color: #dadada; height: 1px;">
<div class="jive-rendered-content"><p style="text-align: justify;"><span style="font-size: 10pt;">After have struggled a bit to setup this stuff, learning a lot of interesting things, so here I am writing a  clean, pure description of how set up a CLIENT-CERT enable EJB3 application in JBoss5.1 which uses a DatabaseCertLoginModule. The goal of this document is more a cookbook, than a reference one so please forgive lacks of explaination.<br/></span></p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><h4>The EJB class</h4><p>Skipping the details of the implementaiton lets see only the top part of the class</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><pre ___default_attr="java" jivemacro="code"><pre class="jive-pre"><code class="jive-code jive-java"><font color="navy"><b>import</b></font> org.jboss.security.annotation.SecurityDomain;
<font color="navy"><b>import</b></font> org.jboss.wsf.spi.annotation.WebContext;
<font color="navy"><b>import</b></font> javax.annotation.security.RolesAllowed;
<font color="navy"><b>import</b></font> javax.ejb.Stateless;
<font color="navy"><b>import</b></font> javax.jws.WebService;
 
@WebService
@Stateless(name=<font color="red">"dpws"</font>)
@SecurityDomain(<font color="red">"discoveryDomain"</font>)
@RolesAllowed(<font color="red">"OPERATOR"</font>)
@WebContext(contextRoot=<font color="red">"/discovery"</font>, urlPattern=<font color="red">"/dpws"</font> ,authMethod=<font color="red">"CLIENT-CERT"</font>, transportGuarantee=<font color="red">"CONFIDENTIAL"</font>, secureWSDLAccess=<font color="navy"><b>false</b></font>)
<font color="navy"><b>public</b></font> <font color="navy"><b>class</b></font> MyDiscovery <font color="navy"><b>implements</b></font> MyDiscoveryRemote, MyDiscoveryLocal<font color="navy">{</font>
    
     @WebMethod(operationName=<font color="red">"getNames"</font>)
     <font color="navy"><b>public</b></font> String[] getNames() <font color="navy">{</font>
        <font color="navy"><b>return</b></font> <font color="navy">{</font><font color="red">"Fabio"</font>, <font color="red">"Marco"</font><font color="navy">}</font>;
    <font color="navy">}</font>
<font color="navy">}</font>
</code></pre>
<br/></pre><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>Few notes:</p><ul><ul><li>the authMethod (CLIENT-CERT) requires the client to send a certificate for the authentication</li><li>the transportGuarantee (CONFIDENTIAL) requires JBoss to open an SSL connection</li><li>the secureWSDLAccess (false) allow anyone to see the WSDL</li></ul></ul><p>For other options see the annotations documentation</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><ul><li>When packaging the EJB do not forget to add to the META-INF directory the jboss.xml file</li></ul><pre class="jive-pre"><code class="jive-code jive-xml"><span class="jive-xml-tag"><?xml version="1.0" encoding="UTF-8"?></span>
<!DOCTYPE jboss PUBLIC <span class="jive-xml-quote">-//JBoss//DTD JBOSS 3.2//EN</span> <span class="jive-xml-quote"><a class="jive-link-external-small" href="http://www.jboss.org/j2ee/dtd/jboss_3_2.dtd" target="_blank">http://www.jboss.org/j2ee/dtd/jboss_3_2.dtd</a></span>>
<span class="jive-xml-tag"><jboss></span>
    <span class="jive-xml-tag"><security-domain></span>java:/jaas/discoveryDomain<span class="jive-xml-tag"></security-domain></span>
<span class="jive-xml-tag"></jboss></span>
</code></pre><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>Note that the <em>security-domain<strong> </strong></em>defers to the previous EJB's @SecurityDomains.</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><h4>Client's and Server's Certificates</h4><p style="text-align: justify;">Open a terminal windows, create a temporary folder, say "Certificates", and executes the following commands</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p style="text-align: justify;">Create the server keystore</p><pre jivemacro="wiki"><pre jivemacro="wiki"><p style="text-align: justify;"> keytool -genkey -alias serverkeys -keyalg RSA -keystore server.keystore -storepass psw1 -keypass psw2</p></pre>
<br/><br/></pre><p style="text-align: justify;">Export the server certificate</p><pre jivemacro="wiki"> keytool -export -alias serverkeys -keystore server.keystore -storepass psw1 -file server.cer<br/></pre><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p style="text-align: justify;">Create the client keystore</p><pre jivemacro="wiki"> keytool -genkey -alias clientkeys -keyalg RSA -keystore client.keystore -storepass pswA -keypass pswB<br/></pre><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p style="text-align: justify;">Export the client certificate</p><pre ___default_attr="plain" jivemacro="code"> keytool -export -alias clientkeys -keystore client.keystore -storepass pswA -file client.cer<br/></pre><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p style="text-align: justify;">Import the client certificate in the server.truststore</p><pre ___default_attr="plain" jivemacro="code"> keytool -import -v -keystore server.truststore  -storepass psw1 -file client.cer<br/></pre><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p style="text-align: justify;">Import the serevr certificate in the server.truststore</p><pre ___default_attr="plain" jivemacro="code"> keytool -import -v -keystore client.truststore  -storepass pswA -file server.cer</pre><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>Anyway in a real world you just need only two steps:</p><ol><li>a certify signed by a trusted Certification Authority (CA) for your client</li><li>import the CA certificate into your server.truststore</li><li>import the server certificate in your client.truststore</li></ol><h4></h4><h4>JBoss setup</h4><p>As should be known, ${jboss.server.home.dir} indicates the $JBOSS_HOME/server/YourInstance directory.</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><ul><li>Copy the <strong>server.keystore</strong> and <strong>server.truststore</strong> files in ${jboss.server.home.dir}/conf</li></ul><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><ul><li>Enable the JBoss's SSL connector editing the ${jboss.server.home.dir}/deploy/jbossweb.sar/server.xml and adding the following configuration</li></ul><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><pre class="jive-pre"><code class="jive-code jive-xml"><span class="jive-xml-comment"><!-- SSL/TLS Connector configuration using the admin devl guide keystore--></span>
      <span class="jive-xml-tag"><Connector protocol="HTTP/1.1" SSLEnabled="true"
           port="8443" address="${jboss.bind.address}"
           scheme="https" secure="true" clientAuth="false"
           keystoreFile="${jboss.server.home.dir}/conf/server.keystore"
                keystorePass="psw1"
           truststoreFile="${jboss.server.home.dir}/conf/server.truststore"
                truststorePass="psw2"
           sslProtocol = "TLS" /></span>
</code></pre><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><ul><li>In the ${jboss.server.home.dir}/deploy folder create a <strong>discovery-service.xml</strong> file (or eventually edit one *-service.xml file you already use) and add</li></ul><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><pre class="jive-pre"><code class="jive-code jive-xml"><span class="jive-xml-comment"><!-- Configures the Discovery SecurityDomain --></span>
<span class="jive-xml-tag"><mbean code="org.jboss.security.plugins.JaasSecurityDomain" name="jboss.security:service=SecurityDomain"></span>
     <span class="jive-xml-tag"><constructor></span>
          <span class="jive-xml-tag"><arg type="java.lang.String" value="discoveryDomain" /></span>
     <span class="jive-xml-tag"></constructor></span>
     <span class="jive-xml-tag"><attribute name="KeyStoreURL"></span>file:${jboss.server.home.dir}/conf/server.keystore<span class="jive-xml-tag"></attribute></span>
     <span class="jive-xml-tag"><attribute name="KeyStorePass"></span>pws1<span class="jive-xml-tag"></attribute></span>
     <span class="jive-xml-tag"><attribute name="TrustStoreURL"></span>file:${jboss.server.home.dir}/conf/server.truststore<span class="jive-xml-tag"></attribute></span>
     <span class="jive-xml-tag"><attribute name="TrustStorePass"></span>pws2<span class="jive-xml-tag"></attribute></span>
     <span class="jive-xml-tag"><depends></span>jboss.security:service=JaasSecurityManager<span class="jive-xml-tag"></depends></span>
<span class="jive-xml-tag"></mbean></span>
<span class="jive-xml-tag"><mbean code="org.jboss.security.auth.login.DynamicLoginConfig" name="jboss:service=DynamicLoginConfig"></span>
     <span class="jive-xml-tag"><attribute name="AuthConfig"></span>
          file:${jboss.server.home.dir}/deploy/discovery-security-config.xml
     <span class="jive-xml-tag"></attribute></span>
     <span class="jive-xml-tag"><depends optional-attribute-name="LoginConfigService"></span>
          jboss.security:service=XMLLoginConfig
     <span class="jive-xml-tag"></depends></span>
     <span class="jive-xml-tag"><depends optional-attribute-name="SecurityManagerService"></span>          jboss.security:service=JaasSecurityManager
     <span class="jive-xml-tag"></depends></span>
<span class="jive-xml-tag"></mbean></span>
</code></pre><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>     Notice that</p><ul><ul><li>the first MBean defines the domain name (discoveryDomain) and the location of the key/truststore</li><li>the second MBean defines the location of a specific policy configuraration file (so do not have to touch the ${jboss.server.home.dir}/conf/login-config.xml)</li></ul></ul><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><ul><li>creates ${jboss.server.home.dir}/deploy/discovery-security-config.xml file</li></ul><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><pre class="jive-pre"><code class="jive-code jive-xml"><span class="jive-xml-tag"><?xml version="1.0" encoding="UTF-8"?></span>
<span class="jive-xml-tag"><policy></span>
     <span class="jive-xml-tag"><application-policy name="discoveryDomain"></span>
          <span class="jive-xml-tag"><authentication></span>
               <span class="jive-xml-tag"><login-module code="org.jboss.security.auth.spi.DatabaseCertLoginModule" flag = "required"></span>
                    <span class="jive-xml-tag"><module-option name="password-stacking"></span>useFirstPass<span class="jive-xml-tag"></module-option></span>
                    <span class="jive-xml-tag"><module-option name="securityDomain"></span>java:/jaas/discoveryDomain<span class="jive-xml-tag"></module-option></span>
                    <span class="jive-xml-tag"><module-option name="dsJndiName"></span>jdbc/securityDS<span class="jive-xml-tag"></module-option></span>
                    <span class="jive-xml-tag"><module-option name="rolesQuery"></span>select role, role_group from roles where principal_id=?<span class="jive-xml-tag"></module-option></span>
                    <span class="jive-xml-tag"><module-option name="verifier"></span>ndg.common.jboss.security.CertVerifier<span class="jive-xml-tag"></module-option></span>
               <span class="jive-xml-tag"></login-module></span>
          <span class="jive-xml-tag"></authentication></span>
     <span class="jive-xml-tag"></application-policy></span>
<span class="jive-xml-tag"></policy></span>
</code></pre><p>Notice that the policy defines a custom verifier, CertVerifier, which allow the application to customize the authenticationl; an empty, always trusting implementation, looks like</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><pre class="jive-pre"><code class="jive-code jive-java"><font color="navy"><b>import</b></font> java.security.KeyStore;
<font color="navy"><b>import</b></font> java.security.cert.X509Certificate;
<font color="navy"><b>import</b></font> org.jboss.security.auth.certs.X509CertificateVerifier;
 
<font color="navy"><b>public</b></font> <font color="navy"><b>class</b></font> CertVerifier <font color="navy"><b>implements</b></font> X509CertificateVerifier <font color="navy">{</font>
    <font color="navy"><b>public</b></font> <font color="navy"><b>boolean</b></font> verify(X509Certificate arg0, String arg1, KeyStore arg2, KeyStore arg3) <font color="navy">{</font>
        System.out.println(<font color="red">"CIAO!!!!!"</font>);
        <font color="navy"><b>return</b></font> <font color="navy"><b>true</b></font>;
    <font color="navy">}</font>
<font color="navy">}</font>
</code></pre><p>Notes that this clas should be packed in a separate jar file and deployed possibly in creates ${jboss.server.home.dir}/lib</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><ul><li>As should be clear the policy uses a DatabaseCertLoginModule class so we have to define a table in a given database using the roleTable.sql script</li></ul><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><pre class="jive-pre"><code class="jive-code jive-sql"><span class="jive-sql-keyword">CREATE</span> <span class="jive-sql-keyword">TABLE</span> roles( role_group <span class="jive-sql-object">character</span> <span class="jive-sql-keyword">varying</span> <span class="jive-sql-keyword">NOT</span> <span class="jive-sql-keyword">NULL</span> <span class="jive-sql-keyword">DEFAULT</span> 'Roles'::<span class="jive-sql-object">character</span> <span class="jive-sql-keyword">varying</span>,
"<span class="jive-sql-quote">role</span>" <span class="jive-sql-object">character</span> <span class="jive-sql-keyword">varying</span> <span class="jive-sql-keyword">NOT</span> <span class="jive-sql-keyword">NULL</span>,
principal_id <span class="jive-sql-object">character</span> <span class="jive-sql-keyword">varying</span> <span class="jive-sql-keyword">NOT</span> <span class="jive-sql-keyword">NULL</span>)
</code></pre><p>Notice that:</p><ul><ul><li>The role_group column has 'Roles' as DEFAULT. This value MUST NOT be changed nor overrided.</li><li>You need to insert <span style="text-decoration: underline;"><strong>by hand</strong></span> a row with your client role/PrincipalID. Such row will look like</li></ul></ul><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><pre class="jive-pre"><code class="jive-code">"Roles";"OPERATOR";"CN=Maurizio Nagni, OU=BADC, O=STFC, L=Harwell, ST=Oxfordshire, C=UK"
</code></pre><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><ul><li>At the end you need a configuration file for the datasource similar to a <strong>discovery-ds.xml</strong></li></ul><pre class="jive-pre"><code class="jive-code jive-xml"><span class="jive-xml-tag"><?xml version="1.0" encoding="UTF-8"?></span>
<span class="jive-xml-tag"><datasources></span>
     <span class="jive-xml-tag"><local-tx-datasource></span>
     <span class="jive-xml-tag"><jndi-name></span>jdbc/securityDS<span class="jive-xml-tag"></jndi-name></span>
     [.......]
     <span class="jive-xml-tag"><local-tx-datasource></span>
<span class="jive-xml-tag"><datasources></span>
</code></pre><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><h4>The Client setup</h4><p>Once you deploy all the necessary machinery in JBoss you should verify that your WSDL is visible but none of the services is available. Now you can generate a WebService Client using any tool you like most (I used the Eclipse) to write a quick and dirty test like</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><pre class="jive-pre"><code class="jive-code jive-java"><font color="navy"><b>import</b></font> java.rmi.RemoteException;
<font color="navy"><b>import</b></font> javax.security.auth.login.LoginContext;
<font color="navy"><b>import</b></font> javax.xml.rpc.ServiceException;
 
<font color="navy"><b>public</b></font> <font color="navy"><b>class</b></font> Client <font color="navy">{</font>
 
    <font color="darkgreen">/**
     * @param args
     */</font>
    <font color="navy"><b>public</b></font> <font color="navy"><b>static</b></font> <font color="navy"><b>void</b></font> main(String[] args) <font color="navy">{</font>
        MyDiscoveryService svc = <font color="navy"><b>new</b></font> MyDiscoveryServiceLocator();
        MyDiscovery ws;
        <font color="navy"><b>try</b></font> <font color="navy">{</font>
            ws = svc.getMyDiscoveryPort();
            String[] listNames = ws.getNames(); <font color="darkgreen">//my webService method</font>
            <font color="navy"><b>for</b></font> (String name : listNames)
                System.out.println(name);
        <font color="navy">}</font> <font color="navy"><b>catch</b></font> (ServiceException e) <font color="navy">{</font>
            e.printStackTrace();
        <font color="navy">}</font> <font color="navy"><b>catch</b></font> (RemoteException e) <font color="navy">{</font>
            e.printStackTrace();
        <font color="navy">}</font>
    <font color="navy">}</font>
<font color="navy">}</font>
</code></pre><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>Now you can run the Client class passing to the JVM the appropriate parameters, that is</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><pre class="jive-pre"><code class="jive-code">-Djavax.net.ssl.keyStore=/myPathTo/client.keystore
-Djavax.net.ssl.keyStorePassword=pswA-Djavax.net.ssl.trustStore=/myPathTo/client.truststore
-Djavax.net.ssl.trustStorePassword=pswB</code></pre><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>and verify that the client has been authenticated using its certificate and that the client name has been correctly associated to the role specified in the Roles table.</p></div>
<div style="background-color: #f4f4f4; padding: 10px; margin-top: 20px;">
<p style="margin: 0;">Comment by <a href="http://community.jboss.org/docs/DOC-15734">going to Community</a></p>
<p style="margin: 0;">Create a new document in EJB3 at <a href="http://community.jboss.org/choose-container!input.jspa?contentType=102&containerType=14&container=2029">Community</a></p>
</div></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>