CAC authentication in a Java WebApp - java

I saw that there were a few other Java and CAC posts on stackoverflow. I am a beginner with all of this stuff and I am still trying to a framework of what to do and where to go in my mind.
I am doing work for a big org that is using CACs with Windows 7 boxes to authenticate users who want to get into their PCs. They stick the CAC in their keyboard and type in a PIN.
My boss would like to alter our Java Webap such that it will not make the users authenticate if they have their CAC in their computer. If not, they will go through the traditional LDAP login.
We are using WebLogic 11g and Java 6.
From Googling around it seems like there are two approaches:
Implement an applet to read the user's CAC and send an SSL certificate to the webapp.
Implement "mutually SSL authentication" in the web server, which will cause the browser to send the SSL certificate on the CAC to the webapp
Do I have a correct appraisal of my options?
Which solution is easier?
Which will be less hassle, more robust in the long run?
I know next to nothing about SSL, which seems to be common in both solutions. I've found a few SSL tutorials that go on at length about abstract concepts. Can anyone recommend a good tutorial for what I want to do?
Thanks much in advance for any information or tips
Steve

Implement an applet to read the user's CAC and send an SSL certificate to the webapp.
Implement "mutually SSL authentication" in the web server, which will cause the browser to send the SSL certificate on the CAC to the webapp
You will want to do #2. You don't really want to have to mess with smart card hardware / software. Let the OS do all that work.
I've done this on IIS, but generically, to implement this, you will need to configure your web server to require client certificates and to trust the DoD CAs. You may need to configure your web server to advertise to clients which CAs it trusts. If the Win7 clients have a client cert that is signed by a CA you trust, the client will attempt to use it. If it's a smartcard certificate, Windows will automatically prompt the user for the pin; you don't have to worry about that. If the user types the correct pin, the cert will be sent to your web server which should then be able to validate the certificate with the CA. If it's a valid certificate, your software can then parse the fields in the certificate and use the values to help authenticate the user (ie whether, despite having a valid certificate, the user is actually allowed to login based on their name / email address/ etc). It's up to you how to handle it from there.
You will have a much easier time figuring this out and finding information if you forget that the users are using a smartcard or a CAC, and just start with the idea that you're going to use client certificates for authentication. Start by creating a self-signed CA test cert. Then create a server cert for your webserver and a client-certificate signed by your test CA. Add the test CA cert as trusted root cert on the client and the server. Then attempt to write a small test app that uses the client cert to authenticate to your webserver. Once you have that working, you can add the DoD CA and try to pull the info out of a CaC certificate.
good luck!

Related

Best Practices Java Trust Store

I have a client/server application that sends data over SSLSockets, so I generated a cert and loaded it with a trust store and keystore. The client is going to be public, so in order to work I need the client to have the javaTrustStore.jts file with it. Is it ok to bundle it in the resources directory? Or should I have the client generate a new key every time and add it to the server's keystore?
There are two ways that you can approach this.
The first is to have a certificate just on the server, and no certificate on the client.
The is the usual way that websites work - when the SSL connection is negotiated, the server sends it's certificate to the client, and the client verifies that the server cert is signed by a Certificate Authority that the client trusts. Most (all?) web browsers are pre-loaded with a number of certificate authoritys' "master certificates",
So, a Java application operating in this mode would need the "master CA certificate", and any "intermediate" signing certificates in it's trust store.
You can also be your own CA, which was done often in years past, when you had to pay for a server cert. These days, if you want a free cert, you can just use Let's Encrypt, or one of several other providers of free certificates.
If you need to validate the client when negotiating the SSL connection, then you would also put a certificate on the client. But, you can't just have the client generate it's own certificate. You'll need to have your CA generate and sign the certificate, and then give that to the client, who would need to add it to their keystore.
Again, in this case, you can act as your own CA, and generate "self-signed" certificates.
If you'd like to see an example of this, I wrote a blog post for my employer's web site about nine or ten years ago about doing this with an Android app.

Handling security when deploying Java application

I have a Java app (deployed as a JAR file) that allows file sharing through SLLSockets. If all users use the same certificate, file transfers are not secure, since it violates the core concept of asymmetric encrypted communication. Therefore, I understand that each user needs to have its own certificate. This brings up my first question:
How can you generate a certificate programmatically, and where would you store it ? I don't want users to have to generate their own certificate with keytool, then have to tell the app where it is located.
Now, let's say my first question is answered and each user has its own certificate. Prior to opening the SSL connection between two hosts, you need to add each other's certificate to the trustStore. The only way I know to achieve this is by exchanging them through Sockets (note that I am using JGroups to exchange Socket connection info). This brings up my next two questions:
How do you guarantee authentication and integrity when exchanging the certificates ?
How do you programmatically add the received certificate to the trustStore ?
Finally, this whole post brings up my fourth question:
Are the steps described above the correct way to send data securely between two hosts, using SSLSocket asymmetric encrypted communication ?
You don't need client certificates necessarily.
Could you not use username/password authentication?
You can still secure the transfer just by using a server certificate.
Client certs are also kind of a pain, and not entirely secure. They tie you to a machine, and evil processes can read them. Smart cards mitigate this, but aren't free.

How to avoid web browser warning when my site use HTTPS protocol, and it's pages include images from sites without HTTPS?

I have java web application which is running on several tomcats behind apache. Application use HTTPS protocol. Some pages from the app include images from sites which use only HTTP protocol. On pages with this images the client's web browser shows message (warning) that despite service is certified correctly some contents are not secure.
What should I do to avoid this message? Should I use some proxy for this images? Can I do something in java code?
Thanks in advance.
You can't do anything nor should you.
The browser is correct in warning the user even though there are no bad intentions here.
Using a proxy could be useful if you're really worried. In that case, the unencrypted connection is between your server and the hosts of the images instead of between the hosts and the user's browser.
Nothing you can do in java.
You need to register your certificate at some official certification authority, you can do that through the registration authorities.
A registration authority (RA) is an authority in a network that
verifies user requests for a digital certificate and tells the
certificate authority (CA) to issue it.
Google it. Of course you'll pay for that.
Also, you can avoid that browser message if manually add your certificate into Trusted Certificate on client machine.

Can a signed certificate be used without importing explicitly?

I've read a lot of articles regarding the import of a cert, but I am still unclear on a couple things.
When connecting to an SSL site from a Java application [in this case, a JBOSS web app], does the client cert need to be explicitly installed on the application server prior?
I can install a client cert manually, but there is an expiration date. So I'll need to manage the expiration dates of all client installed certs on our application server, and take an outage to update each one.
It feels like there should be a better way.
Shouldn't the application automatically accept a valid signed cert? [In this case, it is signed by VeriSign]
We are getting an exception currently when trying to access an https url from the application without explicitly installing the cert.
The API proxy library is swallowing the internal exception, so I dont know the details.
If the cert should be accepted automatically, then there may be a different issue here...
Can a signed certificate be used without importing explicitly?
Yes, it does not need to be installed prior to use. In fact, if you know in advance of what to expect, then you can include that information into the application. That has an added benefit of improving the application's security posture.
To avoid importing the certificate, use a custom X509TrustManager and override checkServerTrusted. In checkServerTrusted, ensure the server's public key is expected (i.e., pin the server's certificate or public key); or verify the server's certificate is valid (i.e., is within validity and forms a chain to your trusted root).
When connecting to an SSL site from a Java application [in this case, a JBOSS web app], does the client cert need to be explicitly installed on the application server prior?
In the case of client certificates, the server advertises the issuer whom it relies upon to issue client certificates. So the server will need to know the trust point for issuing client certifcates for authenticating clients.
In this case, it is signed by VeriSign
This could be really bad. In this case, you will trust all of your clients signed under the Verisign PKI, and all of Verisign's other clients signed under the Verisign PKI.
In this case, it would probably be better to avoid public CAs and run your own PKI (i.e., be your own CA). In this case, pick up a copy of Network Security with OpenSSL. The book will show you how to accomplish the customary tasks using both the openssl command and programmatically.

Authentication based on Certificates and IP

Is there a way for a java web app to get information on the security certificates installed on one's machine via a http request and selectively grant access if a particular certifiicate is installed on the machine.
Basically the requirement is, the web application should entertain request only from a company laptop else must deny access with appropriate error text.
(These could be win laptops with certain certifcates installed on their machine or they can be from a certain set of static ips.)
Yes, this is possible using HTTPS client certificates. The exact setup and configuration depends on your application server and specific requirements, but a common scenario woul be that you create a company internal CA (certification authority) to issue the client certificates which may be restricted to specific client IP addresses and configure your application server's HTTPS connector to require a client certificate and to trust certificates issued by your own CA.
After the proper configuration has been done, the client certificate(s) is/are made available to the web application through a servlet request attribute:
X509Certificate[] certificates = (X509Certificate[])
request.getAttribute("javax.servlet.request.X509Certificate");
As jambjo said - you can absolutely get client certificates through HTTPS with client authentication as he described. I'd recommend that over static IPs, a certificate is harder to spoof and allows more flexibilty if you need to reconfigure the network differently in the future.
A couple other thoughts:
Almost any application server will let you set a trusted certificate store - the list of CA certificates your application will accept for HTTPS client auth. Limit this to the CA that is providing client certificates - either an internal company CA or a certificate provider.
The choice of internal CA or CA provider is a corporate one. An internal CA will take manpower to set up and maintain, a CA provider will cost you money per certificate. There reaches a tradeoff point where it's cheaper to make the certificates yourself, but until you hit that point, the CA provider may be cheaper.
If you have an internal CA and your rule is that "any company machine (with a certificate) can access this application", then your work is done at the Trusted CA list in the applicaiton server, since you know the company CA will not be used for anyone but people in the company.
If you have a CA provider, you may need to limit your access control further and use the code jambjo provided to get the certificate and look at information within it. Typically, there is a organization (O) and organizational unit (OU) component within the subject DN (distinguished name) that will tell you what organization produced this certificate. You should be able to check that to be sure you have a company computer.
It's viable to do the O and OU checking if you know that your CA provider will never give out your company's O and OU names to anyone but a member of your company. If that is not the case, you may need to check against a back end data store (like an LDAP directory) to be sure the user or user's machine is known to you.
It's also possible to link the IP address of the machine to the certificate - often SubjectAltName (Subject Alternative Name) is used for this when the certificate is being constructed. I would not recommend it, because you will need a need a new certificate if you ever change the IP address of the machine. It seems unnecessarily complex for your purposes.

Categories