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!
- Create a new keystore:010203040506070809101112131415161718192021
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.
- Download WildFly 8.1, unzip, and copy “websocket.keystore” file in
standalone/configuration
directory. - Start WildFly as:1
./bin/standalone.sh
- Connect to it using jboss-cli as:1
./bin/jboss-cli.sh -c
- Add a new security realm as:12
[standalone
@localhost
:
9990
/] /core-service=management/security-realm=WebSocketRealm:add()
{
"outcome"
=>
"success"
}
And configure it:
12345678[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"
}
}
- Add a new HTTPS listener as:12345
[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"
}
}
- 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:123456789
<
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.
- Deploy the sample by giving the command:1
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:
And Safari shows the following warning:
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:
1 | new WebSocket( "ws://localhost:8080/endpoint-wss/websocket" ); |
will throw the following exception in Chrome Developer Tools:
1 2 | [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!
Reference: | Securing WebSocket using wss and HTTPS/TLS from our JCG partner Arun Gupta at the Miles to go 2.0 … blog. |