I have just started writing a web application for Glassfish 4.1 and I've started of with the security stuff.
Users accessing the application will identify them self with a client certificate. I created a self-signed root CA. Added this root CA to domain-dir/config/cacerts.jks. Created a client certificate, signed it with root CA and added it to my web browser.
web.xml:
<web-app>
<!-- other stuff -->
<security-constraint>
<web-resource-collection>
<web-resource-name>foo</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>operator</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<login-config>
<auth-method>CLIENT-CERT</auth-method>
</login-config>
<security-role>
<role-name>operator</role-name>
</security-role>
</web-app>
glassfish-web.xml:
<glassfish-web-app>
<context-root>/foo</context-root>
<security-role-mapping>
<role-name>operator</role-name>
<principal-name>CN=user</principal-name>
</security-role-mapping>
</glassfish-web-app>
This works, but I don't want to have to add a principal-name in glassfish-web.xml for each new user. I would like to fetch that information from a database together with group information for each user.
I have looked into and tried to write my own realm extending com.sun.appserv.security.AppservRealm.I have added the realm in the proper way, but it can only be used if I set auth-method in web.xml to BASIC. Using CLIENT-CERT will ignore the realm-name element:
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>my-realm</realm-name>
</login-config>
<login-config>
<auth-method>CLIENT-CERT</auth-method>
<realm-name>my-realm</realm-name>
</login-config>
In the second case, the pre-defined realm 'certificate' will be used. And using BASIC will obviously not use a client certificate.
There is another way and that is to modify domain-dir/config/domain.xml and replace
...
<config name="server-config">
...
<security-service>
...
<auth-realm classname="com.sun.enterprise.security.auth.realm.certificate.CertificateRealm" name="certificate"></auth-realm>
with
...
<config name="server-config">
...
<security-service>
...
<auth-realm classname="org.foo.MyCertificateRealm" name="certificate"></auth-realm>
But that doesn't help either. I get the following warning in the log: "Certificate authentication requires certificate realm." Googling told me that the used realm must be an instance of CertificateRealm and I take it it means com.sun.enterprise.security.auth.realm.certificate.CertificateRealm, but that class is final, so I can't extend it.
Is there no way to have your principals and their groups defined somewhere else than in glassfish-web.xml? Should I ditch Glassfish and use something else, like JBoss?
EDIT 2015-03-31:
Soon after asking this question I tried out Jetty and there I managed to do what I wanted to do. I was even able to combine CLIENT-CERT authentication with FORM authentication in a way that if the client doesn't provide a valid certificate, the user is re-directed to a form based log-in page and can authenticate herself with a user name and password.
Roles are then added to the user at the time of authentication so that Jetty can control access to resources.
If control of role-assignment to a user in Glassfish in CLIENT-CERT mode can be accomplished without having to add each user to glassfish-web.xml, but to be able to pull this information from e.g. a data base, and allowing Glassfish to control access to resources is still a valid question. But I'm in no hurry to receive an answer.
I got the same problem and resolve it whith this link: here
Just use the property assign-groups in the domain.xml file like that:
<auth-realm classname="com.sun.enterprise.security.auth.realm.certificate.CertificateRealm" name="certificate"> <property name="assign-groups" value="allusers"></property> </auth-realm>
allusers will be the group dynamically created for all users who successfully log in with a valid certificate.
Replace the principal tag and value, by the group-name tag and value as allusers. So you will have to just modify your glassfish-web.xml like that:
No need to add Principals in the web.xml. You can after check in a Servlet which certificate is connected by retrieving it with:
and check the DN part with something like:
Hope it helps.Thanks!