Currently, I've been successful implementing Mutual Authentication security so long as the client accesses the website using a web browser, because browsers take care of all the certificate exchange for you. Now I need to create a secure interface with which users can access web services over HTTPS, using the mutual authentication required by the server.
First off, are there any resources anyone knows of that can help me with this? I've looked for quite some time and found nothing. Any other tips anyone can give me on how to go about this?
Secondly, I think my biggest roadblock is my lack of understanding of how to handle certificates. How do I negotiate accepting the server's key and presenting my own key to the server? This is in Java.
Similarly, mutual authentication verifies both parties in a digital communications channel. For example, a client and a server using mutual authentication take steps to independently verify each other's identity, instead of only the client authenticating the server.
Mutual authentication in general (without any mentioning of a specific type of authenticated identity) means that: The API (service) must authenticate itself to the client application (service must present its identity to the client).
You can enable mutual TLS authentication for all the protocols supported by AWS App Mesh. They are TCP, HTTP/1.1, HTTP/2, gRPC. Using App Mesh, you can configure mutual TLS authentication for communications between Envoy proxies from your services.
Mutual authentication, also called two-way authentication, is a process or technology in which both entities in a communications link authenticate each other. In a network environment, the client authenticates the server and the server verifies the client before data can be exchanged.
I spent a long time on this but I finally found an example that actually works. It's Glassfish and Netbeans-based but I guess you could get it working in other environments (e.g. Eclipse and Tomcat) if you played around with it.
http://java.sun.com/webservices/reference/tutorials/wsit/doc/WSIT_Security9.html#wp162511
The problem I've found though is when you want to use your own certificates, not the ones that come pre-installed with glassfish.
Note: I am not a security expert. Don't deploy this to a production environment!
To do this I'm using NetBeans 6.9, JDK 1.6, GlassFish 3.0.1 and OpenSSL v1.0 (I'm using the unofficial Win32 binaries)
# Create the CA mkdir ca server client cd ca openssl req -new -x509 -days 3650 -extensions v3_ca -keyout ca.key -out ca.pem echo 02 > serial.txt cd .. # Creating the Server Keystore openssl req -days 3650 -newkey rsa:1024 -keyout server/server.key -out server/server.req openssl x509 -extensions usr_cert -extfile C:\testbed\OpenSSL-Win32\bin\openssl.cfg -CA ca/ca.pem -CAkey ca/ca.key -CAserial ca/serial.txt -req -in server/server.req -out server/server.crt openssl pkcs12 -export -inkey server/server.key -in server/server.crt -out server/server.p12 -name server keytool -importkeystore -destkeystore server/server.jks -deststoretype jks -srckeystore server/server.p12 -srcstoretype pkcs12 keytool -exportcert -alias server -keystore server/server.jks -file server/server.cer # Create the Client Keystore openssl req -days 3650 -newkey rsa:1024 -keyout client/client1.key -out client/client1.req openssl x509 -extensions usr_cert -extfile C:\testbed\OpenSSL-Win32\bin\openssl.cfg -CA ca/ca.pem -CAkey ca/ca.key -CAserial ca/serial.txt -req -in client/client1.req -out client/client1.crt openssl pkcs12 -export -inkey client/client1.key -in client/client1.crt -out client/client1.p12 -name client1 keytool -importkeystore -destkeystore client/client1.jks -deststoretype jks -srckeystore client/client1.p12 -srcstoretype pkcs12 keytool -exportcert -alias client1 -keystore client/client1.jks -file client/client1.cer # Import public keys and certificates into each others keystores keytool -import -noprompt -trustcacerts -alias client1 -file client/client1.cer -keystore server/server.jks keytool -import -noprompt -trustcacerts -alias server -file server/server.cer -keystore client/client1.jks keytool -import -noprompt -trustcacerts -alias my_ca -file ca/ca.pem -keystore server/server.jks keytool -import -noprompt -trustcacerts -alias my_ca -file ca/ca.pem -keystore client/client1.jks keytool -import -noprompt -trustcacerts -alias my_ca -file ca/ca.pem -keystore "C:\Program Files\glassfish-3.0.1\glassfish\domains\domain1\config\cacerts.jks" keytool -import -noprompt -trustcacerts -alias my_ca -file ca/ca.pem -keystore "C:\Program Files\Java\jdk1.6\jre\lib\security\cacerts" move "C:\Program Files\glassfish-3.0.1\glassfish\domains\domain1\config\keystore.jks" "C:\Program Files\glassfish-3.0.1\glassfish\domains\domain1\config\keystore.jks.backup" copy server\server.jks "C:\Program Files\glassfish-3.0.1\glassfish\domains\domain1\config\keystore.jks"
In the GlassFish admin console, enable Security on your http-listener, tick the SSL3, TLS and Client Authentication boxes, set the Certificate NickName to server, the Key Store to config\keystore.jks, the Trust Store to config\keystore.jks, the Trust Algorithm to PKIX and leave the Max Certificate Length at 5.
In NetBeans, create a new Web Application project. Within that, create a new Web Service.
My Web Service code looked like this:
@WebService() public class ListProducts { @Resource WebServiceContext context; @WebMethod(operationName = "listProducts") public String listProducts() { return context.getUserPrincipal().toString(); } }
Right click on the Web Service and select Edit Web Service Attributes. Tick the Secure Service box and select Mutual Certificates Security as the Security Mechanism. Click on the Configure... button and tick the Encrypt Signature box. Now untick the Use Development Defaults box and then click the Keystore button. Set the location of your server.jks keystore and select the server
alias. Do the same for the Truststore configuration (although you don't have to select an alias here).
Import the client1.p12 client certificate into your browser. Deploy your Web Service to Glassfish. Open up your web service in a browser and browse to the deployed WSDL via HTTPS. Download the WSDL and any other schemas. Rename any referenced schemas to local copies so that when you use WSDL2Java NetBeans won't use any remote resources. (This paragraph is because you've restricted your WSDL to clients with an approved certificate but NetBeans can't fetch it remotely because it doesn't have access to the certificate in question).
Create a new Java Project. Create a new Web Service Client. When prompted, point NetBeans to your saved WSDL file. Import the METRO2.0 library files (C:\Program Files\Netbeans 6.9\enterprise\modules\ext\metr\webservices-*.jar
). My code looked like this:
public static void main(String[] args) { System.getProperties().put("javax.net.ssl.keyStore", "C:\\NetBeansProjects\\security-04\\ssl\\client\\client1.jks"); System.getProperties().put("javax.net.ssl.keyStorePassword", "changeit"); System.getProperties().put("javax.net.ssl.trustStore", "C:\\NetBeansProjects\\security-04\\ssl\\client\\client1.jks"); System.getProperties().put("javax.net.ssl.trustStorePassword", "changeit"); System.out.println(new ListProductsService().getListProductsPort().listProducts()); }
Copy webservices-api.jar into your Java\jdk1.6\jre\lib\endorsed directory. Right-click on the Web Service reference and select Edit Web Service Attributes. Set the keystore location to client1.jks and set the alias to client1
. Set the truststore location to client1.jks and set the alias to server
.
Hopefully you can now run your client and you should see output like so: [email protected], CN=Bob Smith, OU=Something, O=SomethingElse, L=AnyTown, ST=AnyState, C=US
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With