Enterprise Java

Securing WebSocket using wss and HTTPS/TLS

50th tip on this blog, yaay!

Tech Tip #49 explained how to secure WebSockets using username/password and Servlet Security mechanisms. This Tech Tip will explain how to secure WebSockets using HTTPS/TLS on WildFly.

Lets get started!
 
 
 
 

  1. Create a new keystore:
    keytool -genkey -alias websocket -keyalg RSA -keystore websocket.keystore -validity 10950
    Enter keystore password:
    Re-enter new password:
    What is your first and last name?
      [Unknown]:  Arun Gupta
    What is the name of your organizational unit?
      [Unknown]:  JBoss Middleware
    What is the name of your organization?
      [Unknown]:  Red Hat
    What is the name of your City or Locality?
      [Unknown]:  San Jose
    What is the name of your State or Province?
      [Unknown]:  CA
    What is the two-letter country code for this unit?
      [Unknown]:  US
    Is CN=Arun Gupta, OU=JBoss Middleware, O=Red Hat, L=San Jose, ST=CA, C=US correct?
      [no]:  yes
    
    Enter key password for <websocket>
    	(RETURN if same as keystore password):
    Re-enter new password:

    Used “websocket” as the convenience password.

  2. Download WildFly 8.1, unzip, and copy “websocket.keystore” file in standalone/configuration directory.
  3. Start WildFly as:
    ./bin/standalone.sh
  4. Connect to it using jboss-cli as:
    ./bin/jboss-cli.sh -c
  5. Add a new security realm as:
    [standalone@localhost:9990 /] /core-service=management/security-realm=WebSocketRealm:add()
    {"outcome" => "success"}

    And configure it:

    [standalone@localhost:9990 /] /core-service=management/security-realm=WebSocketRealm/server-identity=ssl:add(keystore-path=websocket.keystore, keystore-relative-to=jboss.server.config.dir, keystore-password=websocket)
    {
        "outcome" => "success",
        "response-headers" => {
            "operation-requires-reload" => true,
            "process-state" => "reload-required"
        }
    }
  6. Add a new HTTPS listener as:
    [standalone@localhost:9990 /] /subsystem=undertow/server=default-server/https-listener=https:add(socket-binding=https, security-realm=WebSocketRealm)
    {
        "outcome" => "success",
        "response-headers" => {"process-state" => "reload-required"}
    }
  7. A simple sample to show TLS-based security for WebSocket is available at github.com/javaee-samples/javaee7-samples/tree/master/websocket/endpoint-wss. Clone the workspace and change directory to “websocket/endpoint-wss”. The sample’s deployment descriptor has:
    <security-constraint>
      <web-resource-collection>
        <web-resource-name>Secure WebSocket</web-resource-name>
        <url-pattern>/*</url-pattern>
      </web-resource-collection>
      <user-data-constraint>
        <transport-guarantee>CONFIDENTIAL</transport-guarantee>
      </user-data-constraint>
    </security-constraint>

    This ensures that any request coming to this application will be auto-directed to an HTTPS URL.

  8. Deploy the sample by giving the command:
    mvn wildfly:deploy

Now accessing http://localhost:8080/endpoint-wss redirects to https://localhost:8080/endpoint-wss. The browsers may complain about self-signed certificate. For example, Chrome shows the following warning:

techtip50-certificate-chrome

And Safari shows the following warning:

techtip50-certificate

In either case, click on “Proceed to localhost” or “Continue” to proceed further. And then a secure WebSocket connection is established.

Another relevant point to understand is that a non-secure WebSocket connection cannot be made from an https-protected page. For example the following code in our sample:

new WebSocket("ws://localhost:8080/endpoint-wss/websocket");

will throw the following exception in Chrome Developer Tools:

[blocked] The page at 'https://localhost:8443/endpoint-wss/index.jsp' was loaded over HTTPS, but ran insecure content from 'ws://localhost:8080/endpoint-wss/websocket': this content should also be loaded over HTTPS.
Uncaught SecurityError: Failed to construct 'WebSocket': An insecure WebSocket connection may not be initiated from a page loaded over HTTPS.

Enjoy!

Arun Gupta

Arun is a technology enthusiast, avid runner, author of a best-selling book, globe trotter, a community guy, Java Champion, JavaOne Rockstar, JUG Leader, Minecraft Modder, Devoxx4Kids-er, and a Red Hatter.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button