prompt for (any) client certificate only from a specific servlet - java

Is there a way to force client certificate authentication only on a particular part of a web application, i.e. some servlet that handles client certificate authentication?
The clientAuth parameter on server.xml set to 'true' or 'want' works for me, but is inconvenient because it prompts the user to choose a certificate in any part of the application.
On the other hand, I tried setting clientAuth to 'false', and using web.xml to enforce security only on a specific servlet. It worked, but this is limited to the users specified in the tomcat-users.xml file, hence other users' certificates are not authorized to the servlet by tomcat.
I need to be able to restrict client certificate authentication to a particular url of my application, while accepting any certificate (trusted, or even not), for authentication and provisioning purposes (the servlet basically reads the information from any certificate, the application decides what to do).
I know there are similar questions like [1], but I did not find the answer that suits these particular needs. Thanks a lot.
[1] Using CLIENT-CERT for Tomcat without specifying a username

ssl is a network layer works below https. So you cannot control it in a serlvet.
The only way is to deploy your webapp in a non-ssl web server. When a servlet (or other resources) need SSL client auth, just redirect to an https url (the same site with https port, or another site).

Related

mutual authentication using certificate

I have been developing a web application using java and I wanted to use implement mutual certificate authentication.
I used a self-signed certificate, I put it on my browser(chrome) and to my glassfish trust store(cacerts.jks) and configure my web.xml and sun-web.xml and works fine.
When I run the application it asked me to choose a certificate and after the proper authentication the page I requested is displayed.
However I need to make different certificate(actually three) and based on the role I want to authorize the user.
But even if I created other two certificates and added to the browser certificate list, the browser didn't list them on the certificate selection prompt except for the first certificate.
It seems that I am adding the certificate to the wrong version of glassfish trust store(cacerts.jks) now everything is working fine. The browser lists all certificate I added and authorize correctly according to the role.

Configure Tomcat to prefer one signer over another OR use different certs per endpoint?

I have a Spring Boot (v1.3) web service running Tomcat 8 with endpoints that hit multiple downstream services. Each downstream service requires information in the user's certificate that was signed by that downstream service's CA.
A user will have all of the certs they need (a cert for each of the necessary CAs), but the service needs to obtain a different cert for each endpoint. Is there a way to do that (get a specific or all certs from a user's browser)?
(Maybe something along the lines of grabbing the tomcat SSLSessionManager (org.apache.tomcat.util.net.SSLSessionManager) in the appropriate controller and invalidating the session/ca...and asking for a different one..)
It is not clear to me what you want : have multiple tomcat endpoints the user can connect to, or call multiple endpoints from your tomcat.
If this is the first one, then you can either:
declare multiple tomcat connectors, each with its own keystore
or add a front server (like Apache, Nginx, HAProxy, etc.) that will handle the SSL part given a requested DNS
If this is the second solution you need, you can have one keystore with all certificates.This keystore can be registered to the JVM through the javax.ssl properties. See java SSL and cert keystore for more information

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.

How Digital certificates provides extra security on top of SSL [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 8 years ago.
Improve this question
My legacy Application is on https(SSL). On top of that i can see some users are configured to use
digital certificates which are created by my own CA using OpenSSL? With this i have got CAcert.pem and CAkey.pem which
are used to create digital certificates for user who requests for it(thru CSR).
My understanding with this
is that whenever user(using digital certificates) tries to connect to server , browser sends the installed Digital
certificate to server automatically(Question is how browser knows this is digital enabled user and it needs to send the certificate? )
and server validates (Who is responsible to validate the certicate information on server side?)
My last question is How Digital certificates provides extra security on top of SSL?
UPDATE :-
As you said Digital certificates are essential part of ssl not different from it(where digital certificates are sent from server
to client containing the publick key and information about the CA whom browser trusts). Now browser will send the data encrypted
with public key which will be decrypted at server side with private key. Similarly when server send the response it will be
reverse i.e encrypted with public key and decrypted with public key at browser side Right?
Bruno, You are right i actually wanted to get the information about client certificates.
I also got the with client certificate, extra security is provided becoz client is subjected to the same strength of authentication from the server. So even if the password is stolen, but hacker does not have client certificate. he can not proceed.
But i am not sure how it works. I have got some
idea with your answer but still questions i asked in OP still puzzles me. I will tell you my configuration. I am sure you can help me then.
I am using Tomcat webserver. Here is the snippet in server.xml i added
Step1 :-
<Connector
SSLEnabled="true"
acceptCount="100"
connectionTimeout="20000"
executor="tomcatThreadPool"
keystoreFile="c/.keystore"
keystorePass="changeme"
maxKeepAliveRequests="15"
port="443"
protocol="HTTP/1.1"
redirectPort="443"
scheme="https"
secure="true"
/>
Step 2
Added below snippet in tomcat-users.xml file
<role rolename="certrole"/>
<user username="ignoreAndCheckInWebApp" password="nopass" roles="certrole"/>
Step 3
Added below sniipet in web.xml
<security-constraint>
<web-resource-collection>
<web-resource-name>Client Certificate Auth</web-resource-name>
<url-pattern>/MyClientAuthenticator.jsp</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>certrole</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>CLIENT-CERT</auth-method>
</login-config>
placed a jar file conatining MySSlAuthentication.java into the lib folder of Tomcat.
Step 4
Then added below valve element under tomcat\conf\context.xml
<Valve className="MySSlAuthentication"/>
So its more or less th eprocedure mentioned at http://twoguysarguing.wordpress.com/2009/11/03/mutual-authentication-with-client-cert-tomcat-6-and-httpclient/ but i am unable to understand the steps(why and when they are required) and how they are linked to each other ?
Now my question is:-
I am not able to relate steps 2,3 and 4. I want to understand what happens when browser tries to connect to MyClientAuthenticator.jsp? My understanding when browser tries to call the MyClientAuthenticator.jsp, server asks the client certificate from browser. But then how/when step 2 and step 4 comes in to picture?
How Digital certificates provides extra security on top of SSL?
In general, I wouldn't say digital certificates provide "extra" security on top of SSL/TLS. Rather, they're an essential part of it. Although the PKI details and how to verify the certificates isn't part of the TLS specification (RFC 5246) (there are a couple of additional specifications for this, such as RFC 5280 and RFC 6125), the specification itself clearly references quite heavily certificates and how they should be used.
You seem to be talking about client certificates, but you probably already know about server certificates, which are far more common.
In both cases, the purpose of certificates in SSL/TLS is to authenticate the communicating parties, so that each party can be sure it's talking with the remote party it expects.
You should always at least have a server certificate (otherwise the connection would be vulnerable to MITM attacks). This proves the identity of the server to the client.
In addition to this, some configurations expect the client to provide a certificate. Since you're talking about users using their certificates from their browser, you seem to be in this situation.
In this case, the extra security is that the client is subjected to the same strength of authentication from the server, as the server is from the client. In particular, since the private key never leaves the remote party in this process, this helps prevents impersonation by password theft (since no password is transmitted). There are more details in this question on Security.SE.
Requesting a client certificate is something that can only be done by the server. If your server is configured to do so, it will send a message to the client (your browser) during the SSL/TLS handshake, and this message will normally contain a list of CA certificates it trusts, to give an indication of which client certificates it is willing to accept. (In this particular case, your server will most likely have been configured to request client certificates issued by your CA.)
Your server will have been coded and configured to do so (I'm not sure from your question whether you're using a Java Servlet container or a bespoke Java server).
The validation of the certificate is done by the trust manager in Java. This is often initialised transparently by providing the application with a trust store and relying on the default behaviour of the default SSLContext (then used by the default SSLSocket or SSLEngine depending on how your application is coded). Assuming your server uses the default trust manager and is configured with a trust store containing your CA certificate (and is also set up to request a certificate), it will send the name of that CA to the browsers than connect to it, and it will also use that CA to verify the certificate then sent by the browser.
(Some applications may also have a customised trust manager, but then its behaviour depends entirely on what it was written to do.)
Java provides two way of requesting a certificate: "need" or "want" (see SSLSocket.setNeedClientAuth(...)). The difference is that with "need", the connection will stop if the client didn't present a user certificate, whereas it will continue in this case with "want".
After this, the server application can check the authentication status of the user by checking the peer certificate from the SSLSession. (It won't get any peer certificate if the client didn't send one and the server used the "want" mode. This may be fine for anonymous access.)
At this stage (provided the server application was coded with the correct trust manager, i.e. not a dummy one), the server code will be ensured that the remote user is indeed the holder of the private key matching that certificate. The Subject Distinguished Name of the certificate can then be used as the identity of the remote party. (Some servers allow you to match this to a different set of user names if necessary. This will depend on which exact server you're using and how it's configured.)
As you said Digital certificates are essential part of ssl not different from it(where digital certificates are sent from server to client containing the publick key and information about the CA whom browser trusts). Now browser will send the data encrypted with public key which will be decrypted at server side with private key. Similarly when server send the response it will be reverse i.e encrypted with public key and decrypted with public key at browser side Right?
No, whether you use client certificates or not, the connection will be encrypted in both directions anyway, using a symmetric key negotiated during the handshake. Client certificate have nothing to do with it. The client certificate is only used to sign the handshake at the end, to prove to the server that the client has the private key for this certificate.
The details in your edit seem to indicate you're using a configuration that's probably a bit more complex than usual.
Firstly, your Connector doesn't have a clientAuth attribute (so its default value is false). This implies that the client certificate will not happen during the initial handshake, but will be triggered by a second handshake when you try to access the protected resource (according to your security-constraint configuration). This is called re-negotiation, and it's not unusual.
(I've also noticed that it doesn't have truststore-related settings, which implies it's using the default JRE truststore, which also implies that your custom CA certificate must have been imported explicitly into that truststore (cacerts in general). Keep this in mind if you upgrade your JRE, since you're probably have to import that cert there manually again.)
Your tomcat-users.xml configuration is what I was talking about earlier (about matching Subject DNs to user names or roles). This, combined with your custom valve is what's unusual in your settings.
My guess would be that this valve maps any valid certificate to a pseudo-user called ignoreAndCheckInWebApp, just to be able to pass that security constraint, although your application would be expected to look at the certificate itself.
In a more traditional case, the usernames in tomcat-users.xml would be the Subject DNs of your certificates, and you would map them to roles this way. Here, it seems your deployment doesn't care about this mapping at that point, but is meant to check this within your application later. This probably means that your application should directly rely on HttpServletRequest.getRemoteUser() (unless it's also set up by a filter later), but should read the certificate using the "javax.servlet.request.X509Certificate" attribute from the request.
This can make sense if the application does all of this correctly. What I'm saying here is really a guess, since it depends entirely on how the Tomcat valve is implemented. This will certainly affect the remote user name and user principals that you get.
Regarding your comments about ActiveX and IE, client-certificate authentication should also work fine with Firefox or Chrome. Two things come to mind:
That ActiveX code may simply have nothing to do with client certificates, but may be part of the what the application is meant to do.
That ActiveX code is part of your own CA, as a means to let your users apply for certificates from within their browsers (when they don't already have one). Perhaps this was only implemented for IE, although it could be done for Firefox or other browsers too.
Question is how browser knows this is digital enabled user and it needs to send the certificate? )
The browser sends it because the server asked for it, because the server is configured to do so.
Who is responsible to validate the certicate information on server side?
The SSL implementation is responsible.
How Digital certificates provides extra security on top of SSL?
As part of SSL, you mean. They securely identify the owner, which gives the application a chance to decide whether that user is authorised to use this part of the application.
Re your UPDATE:
Now browser will send the data encrypted with public key which will be decrypted at server side with private key. Similarly when server send the response it will be reverse i.e encrypted with public key and decrypted with public key at browser side Right?
Wrong. The encryption and decryption processes aren't different just because the client provided a certificate. What really happens is that the client and server negotiate a symmetric session key. Public-private key encryption isn't used.
1)How browser knows when it has to send the client certificate(AS EJP pointed out server asks for it but i am not sure where it is asking it in above configuration).
It is asking for it because of this:
<auth-method>CLIENT-CERT</auth-method>
2)Whoz is validating client certificate at server side ? Is it MySSlAuthentication?
The SSL implementation associated with the Connector validates the client certificate. You haven't told us what MySSlAuthentication is, so I can't tell you what it does.

Add HTTPS to a custom domain on Google App Engine (and keep HTTP working)

I own a Java application on Google App Engine Java with a custom domain and multiple subdomains.
I'd like to allow one part of my application to be served over https (for example, all the urls of a subdomain or all the urls with /secure/ in path).
The other urls should still be served over http. Our website receive more than 100 req/s and the vast majority of these requests should still work over http.
I fear that by trying to activate https I might block all the http requests which would create a big downtime for our servers.
Is it possible to do what I'd like with App Engine?
What is the best way to do it and avoid any downtime?
Thanks!
If someone is interested, here's what I finally did:
in google apps for my domain, in More controls / Security / SSL for Custom Domains, I activated my app engine app id.
I activated Virtual IP ($39/month) (but it also works with SNI)
As I use VIP, I changed the CNAME to redirect all my subdomains to the special CNAME for SSL with VIP (unnecessary with SNI I think)
I created a key + CSR with OpenSSL. I created a self signed certificate and tested it. It worked but of course, warning message.
I paid a signing authority for a valid certificate (wildcard for all my subdomains, about 100€/year)
I added that certificate + intermediate certificate and key in google apps for my domain.
It now works perfectly in both http and https. There wasn't any service disruption at any time for http.
I'll now add some url filter to my app to automatically redirect some http urls to https.

Categories