I have a web application running on Tomcat 7 and it is configured with a custom JNDIRealm and my login-config auth-method in my web.xml is set to "FORM".
I am trying to find a way to add the ability to authenticate users through the same LDAP with a smart card, if presented.
I have changed my server.xml to have clientAuth=want, but want to know if there is a way to authenticate the user when a certificate is presented via the LDAP and then re-direct them past the login form. Is this possible?
EDIT: Michael-O below was marked as the right answer because I was able to achieve this by creating a custom class that extends FormAuthenticator and then registering that in Tomcat's authenticator.properties. This allowed me to check for a x509cert from the client in the request. If the cert is present and valid, authenticate and forward the user to the secured resources page. If not present or invalid, forward the user to the form login.
You obviously do not now what you want or what technologies you are actually using. Smartcard authentication is mutual SSL authentication. So you first need to configure Tomcat to accept SSL-based authentication. Your realm will receive the X509 certs and will try find your DN in your data store. The store can be anything, database, files, directory, etc.
Related
I am trying to create a java servlet application that requires client certificate authentication, but only on specific pages. I would like to have a landing page that doesn't require any sort of authentication which will have a link/button to go to a page that does require authentication. Is there a way to do this?
I am using OpenLiberty as the servlet container. I am familiar with using ClientAuthenticationSupported="true" (in server.xml), but I do not want the user prompted to select a certificate until they reach a certain page. I have also looked at HttpServletRequest, but don't see a way to force a specific type of authentication with the available methods.
I want the user to be prompted like they would be visiting prod.idrix.eu/secure. Is there a way to set a servlet's authentication type programmatically to accomplish this? Any help would be appreciated. I think this can be done using two different applications (one that does not require authentication and one that does), but I would like to keep it all as one.
Thanks.
In web.xml you can specify security-constraints that will include URL patterns for the pages that should be protected. You can also configure <login-config> to use CLIENT-CERT authentication method.
In the server.xml then you configure your user registry and mapping between cert and user. More details here - https://www.ibm.com/docs/en/was-liberty/base?topic=liberty-ldap-certificate-map-mode
I am trying to develop an authentication module using servlets as targets for different methods of authentication. For a username/password combination it is relatively simple since I can pull the parameters and call request.login(, ), but for a client-certificate-type login I am unsure how to proceed after getting the user's certificate (via calling request.getAttribute("javax.servlet.request.X509Certificate").
How can I go about passing the certificate back to the authentication logic (which is most likely going to be JAAS configured in Wildfly) so I can authenticate the user through the container?
I have a web application which is hosted on apache web server. And i have external java application which runs on tomcat integrated in this web application.
The apache is kerberized and I get the username of the person accessing it in the intranet. I want to use the same username and pass it on tomcat to check against ldap and authorize the user.
I was looking into JNDI realm which supports LDAP module. But the problem is I do not have access to the user's password. But I'm able to get the groups the user belongs to and based on that I want to authenticate the user.
So my question is will i be able to authenticate a user against Tomcat server via LDAP with just the username and not the password?
PS: Sorry there is no code or configuration that I can post at this point. The only resources i found implemented both username and password. I cannot kerberize the tomcat server because I have other issues in the network.
"I was looking into JNDI realm which supports LDAP module. But the problem is I do not have
access to the user's password. But I'm able to get the groups the user belongs to and based
on that I want to authenticate the user."
Once I was asked to write some code to do the very same thing. I found a way to make it work. However, although it seemed to work well enough with Internet Explorer which would automatically detect the Windows username (because my code was parsing some NTLM information that only Internet Explorer passes in as a header), in Firefox or any other browser the user would be presented with an authentication box and any username they typed in would be accepted! Its very insecure.
(Well, its not really true that only IE passes the header in. Only IE passes it in automatically; but Firefox also passes it in after someone gets the authentication box and types in any name they want. That's the problem.)
What I would suggest is writing a C#.NET service to do the authentication for real on a webserver that is IIS and has Integrated Authentication on. Then, redirect to the C# service when someone hits the Java site and the username session variable is null. Have the C# service save the info in a trusted/secure database including ip address and browser and redirect to the Java app which reads the db to validate IP address and browser and that the record was just created.
Edit: I just noticed you said your Apache is kerberized and already gets the Windows username, which may render the problem above about the unreliability of parsing the NTLM header null and void. In this case, if you can get the AD groups via LDAP you can authenticate the user in your webapp with your own code, but probably not using the official Tomcat authentication scheme. What is described above is just because my Tomcat is not paired with an Apache server but with a IIS server. So basically, its the same thing, except you won't need C#.
Since I'm running Java with Tomcat6 as servlet container I found it appropriate to use the Tomcat JNDIRealm feature so that LDAP users can log into my site without any additional efforts. The LDAP server I'm using is OpenLDAP on Ubuntu.
On top of this I have the login page using form-based authentication over an https connection.
I found two very good examples of authentication users via LDAP, here and here, that both achieve what I feel I almost achieved. Why almost achieved?
When I attempt to login with the wrong credentials I'm appropriately sent to the <form-error-page>, login-failed.html in my case.
When my credentials are good and I authenticate successfully I start getting a 403 for all urls in the site. And I cannot remove the 403 error (not even for the login page!) unless I restart Tomcat.
I suspect the reason is because I don't have roles in the realm or other config files set up correctly. For the sake of brevity I put the relevant config files excerpts on pastebin:
Realm in Tomcat server.xml
Relevant tomcat-users.xml part
Relevant web.xml part
Basic LDAP structure, dashes indicate tree structure
Note that Tomcat-based auth works perfectly since the role is easily attached to the user in the tomcat-users.xml. Therefore I believe it's a problem in getting the role for an authenticated user from LDAP once it has been successfully been authenticated.
TL/DR
I have a config issue in connecting Tomcat to LDAP auth. User data fetched properly, but not the user's role. LDAP log messages available on request ;)
UPDATE: I pasted the LDAP data here.
That is correct. Your LDAP roles aren't being found by the JNDIRealm. You need to test your role search string outside Tomcat to ensure it yields what you think it should yield. As you haven't provided any LDAP details it isn't possible to comment further.
Putting a security-permission on the entire site with /* is a mistake. You need to exclude the login page and probably also the front page and the forgot-password page, maybe more, from requiring a role.
http://support.microsoft.com/kb/892424
When the "Smart card is required for interactive logon" is set on Active Directory, it generates a random password. How do I utilize a smart card to authenticate a user over LDAP from a web application?
How do I know who the user is? Is there a way to access the cert? Can I get it from the session?
HTTPS and SSL mutual authentication should be used for this, because client already has at least corporate CA-signed certificate on its smart card stored.
When mutual SSL authentication is used instead just server authentication, the client certificate is also verified by server, not only the server's certificate by client (which is more common set-up for e.g. HTTPS enabled e-commerce sites). And you still get encrypted connection as a bonus.
See e.g. Tomcat 6.0 SSL Configuration HOW-TO. The key point is to have the CA certificate in the trust-store and clientAuth attribute set to true.
The login auth-method should be also specified to CLIENT-CERT in web.xml of the respective web-application:
...
<login-config>
<auth-method>CLIENT-CERT</auth-method>
<realm-name>Foo * Bar * Realm</realm-name>
</login-config>
...
SubjectDN attribute from the client certificate is used to identify the user. LDAP (or ActiveDirectory) can be still used for authorization - e.g. by checking if user belongs to a group.
It can be difficult to set it all on the first time. To get familiar with all the concepts I recommend following approach:
Use BASIC auth-method with user-names and passwords stored in a file
Use simple role-based authorization
Enable CLIENT-CERT auth-method + simple role-based authorization
Incorporate LDAP for checking roles