Access Keys:
Skip to content (Access Key - 0)
WELCOME TO KAAZING.ORG LOGIN | REGISTER
Kaazing.com | FAQ | Jobs | Forum | Wiki
 

This document is also packaged with the Kaazing Gateway demo bundle, which is available here

Security Overview

Kaazing Gateway 8.12 (Battlestar) Release

February 2009

At Kaazing we do not subscribe to a “leave-the-key-under-the-mat” security philosophy. Instead, we take security very seriously. This document provides an in-depth look at how Kaazing security works under the covers by taking a look at a few sample scenarios that leverage all possible aspects of security. This document covers the following security areas:

  • Credential Caching Strategies
  • PlaintextKeyring API
  • EncryptedKeyring API
  • Wire Traffic Encryption
  • HTTP Authentication and Authorization
  • Encrypted Session Cookies
  • Cookies and Domain Limitations
  • Single Sign-On
  • Kaazing Keyring Service
  • Kaazing Protocol Validation and Credential Injection
  • Cross-Origin Resource Sharing
Prerequisites

This document assumes that you are familiar with the Kaazing Gateway. Refer to the Architectural Overview for more information.

What this document does not cover

Although this document contains example configuration file snippets and JavaScript code examples, it does not cover how to build the example chat and stock applications end-to-end; refer to the Kaazing Tutorials for more information about that. This document also does not describe how Kaazing Gateway security is configured; refer to the section titled Securing the Kaazing Gateway Server in the Kaazing Administrator's Guide for more information on how to configure different aspects of gateway security.

About the example scenarios

To illustrate the different aspects of security, we will use a few example scenarios in which a Web application accesses backend services through the Kaazing Gateway by using the Kaazing Protocol JavaScript Libraries. The Kaazing Gateway provides the full-duplex socket connections required to access the backend services directly. This document covers the following scenarios:

Scenario 1—Plaintext Credentials

Let’s take a look at the first scenario—a Web application with chat and a stock components that interact with backend services through the Kaazing Gateway. A plaintext keyring is used to cache the credentials and because the credentials are stored in plaintext, a secure WebSocket connection is used to protect the credentials.

Scenario 1

In this example the main Web application page is loaded from www.server.com on port 80. The page contains chat and a stock components, which communicate directly with the backend chat and stock services using encrypted wire traffic. To log in to either the stock or the chat application, users provide their name and password in the user interface. The credentials are sent transparently through the gateway as part of the protocol wire traffic. The Kaazing Gateway listens on port 9090 for secure WebSocket XMPP and Stomp traffic and proxies it to the backend XMPP (chat) and Stomp (stock) servers. The stock and chat clients use the same credentials key, allowing the credentials to be shared.

Note: the default ports for WebSocket (ws) is 81 and the default port for secure WebSocket (wss) is 815.

To avoid having to log in every time you return to the page (for example, when you close and reopen a browser tab), the application developer must come up with a strategy to cache the user’s credentials on the client side. Since the credentials are part of the protocol wire traffic, you must use TLS (Transport Layer Security, a.k.a SSL) to encrypt the wire traffic from the browser to the gateway.

Although it is not recommended, it it possible to store plain-text credentials locally or as part of session storage. Extra care must be taken not to compromise the credentials while they are stored, because the passwords will be valid until the users change their passwords; not just for the duration of the session. In many cases, developers rely on the browser’s “Remember Password” feature for this, but that requires a form submit, which is incompatible with WebSocket connectivity.

To address this problem, the Kaazing Gateway offers an easy-to-use keyring API for handling the caching of credentials. The open source Kaazing Gateway ships with the plaintext keyring. The keyring implementation uses the HTML 5 Storage API to cache credentials. HTML 5 defines two implementations of storage:

  1. document.localStorage
  2. document.sessionStorage

The Kaazing Gateway provides an emulation of these implementations if they are not available in the browser.

Using the plaintext keyring, users of the Web application won’t have to log in every time they return to the page, a key enhancement to usability. The Kaazing Gateway Keyring API allows you to reuse cached credentials for backend services that share the same LDAP directory server. In this scenario, the chat and the stock service are using the same LDAP server.

To leverage the Plaintext Keyring requires programming and configuration on both the client side as well as the server side.

Client Side

This section describes the client-side programming required to leverage the plaintext keyring.

Create a Keyring, a Key, and a Callback Function

To leverage the credential caching benefits of the Kaazing Gateway, you first create an instance of a PlaintextKeyring object to store credentials in. Next, you a create a key, called, for example, credentialsKey.

When the key is asked to resolve the credentials, it first checks the keyring's storage object (document.sessionStorage, in the example below). If the credentials are not present there, the authenticate function is called to prompt the user to enter them. The credentials are then stored and subsequent attempts to resolve the key will be able to retrieve the cached value of the credentials from storage.

// Create a PlaintextKeyring using sessionStorage
// as its storage facility
var keyring = new PlaintextKeyring(document.sessionStorage);

// The authenticate() callback will be called by the keyring
// when a protocol needs to authenticate.
// When you are done gathering credentials, call the passed
// in continuation() function to resume with the protocol.

function authenticate(continuation) {
  // Gather and set credentials, using something like a
  // popup dialog to obtain username and password
  // Once the credentials have been gathered, set them on a
  // credentials Javascript object and pass it back to the protocol
  var credentials = {'username':..., 'password':...};
  
  // Once the credentials are set, resume with the protocol
  continuation(credentials);
}

var credentialsKey = keyring.createKey("shared", authenticate);

Credentials stored in the PlaintextKeyring are stored in, you guessed it, plain text. As described in scenario three, Kaazing Enterprise Gateway allows you to use an encrypted keyring that stores credentials in encrypted form. Next, you create the two backend-service clients: the stock client and the chat client.

Create the Backend-Service Clients

To communicate with the stock service, you create a Stomp protocol stock client that can communicate directly with the backend stock service. The stock client uses the authenticate function, passing in the credentialsKey that was created earlier to authenticate to the backend stock server.

When the credentials are successfully processed by the stock server, the onopen callback function is invoked, allowing the stock user interface  to proceed. If authentication is unsuccessful, the onerror callback function is invoked, allowing the user interface to respond.

var stockClient = new StompClient();
stockClient.connect("wss://stock.server.com/", credentialsKey);

stockClient.onopen = function() {
  // stock server login successful, proceed with fetching stock data...
}

stockClient.onerror = function() {
  // stock server login unsuccessful (or other stock server error)
}

To communicate with the chat service, you create an XMPP protocol chat client that can communicate directly with the backend chat service. The chat client uses the authenticate function, passing in the credentialsKey that was created earlier to authenticate to the backend chat server.

When the credentials are successfully processed by the chat server, the onauthenticated callback function is invoked, allowing the chat user interface to proceed. If authentication is unsuccessful, the onerror callback function is invoked, allowing the user interface to respond.

// The Chat server is configured for "[username]@chat.com" accounts

var chatClient = new XmppClient();
chatClient.connect("wss://chat.server.com/", "chat.com");

chatClient.onopen = function() {
  chatClient.authenticate(credentialsKey);
}

chatClient.onauthenticated = function() {
  // chat server login successful
}

chatClient.onerror = function() {
  // chat server login unsuccessful (or other chat server error)
}

Note: The XMPP protocol supports anonymous connections. Therefore, it requires a second authentication step after the connection is established.

Since the credentials In this scenario are stored and passed along to the backend service in plaintext, the connections from the browser to the gateway must use secure WebSocket (wss). For example, wss://chat.server.com. This has the unfortunate side effect that all communication to the Kaazing Gateway has to be encrypted; not just the credential-related wire traffic. While this is secure, the use of TLS comes with additional overhead, which can affect performance and may be undesired.

Notice that the stock and chat clients use the same credentials key (credentialsKey). The first client to resolve the key will trigger the authenticated callback function allowing the credentials to be shared between the two clients.

Server Side

This section describes the server-side configuration required to leverage the plaintext keyring.

Configuring Network Address Mapping

When a firewall or load-balancing router front-ends a Kaazing Gateway Server, DNS will resolve to the public IP address of that device. The device is configured to forward requests to the Kaazing Gateway Server on the internal network.

In  this scenario, a firewall connected directly to the Internet has the IP address 65.43.2.1 and the public DNS name www.server.com.The Kaazing Gateway Server is running on gateway.dmz.net with IP address 10.0.0.1. The firewall forwards network traffic to the Kaazing Gateway Server, which has to serve HTTP requests for www.server.com on port 80. These requests must be routed through the firewall to the gateway’s internal IP address (10.0.0.1) on port 8080.

By default, the Kaazing Gateway Server resolves the local interface address (10.0.0.1) by looking up the DNS name www.server.com, but in this case that would resolve to 65.43.2.1, which does not represent any local network interface, resulting in a failure to serve requests for www.server.com.

You use the network configuration address-mapping element to override the Kaazing Gateway's default behavior. In this example scenario, you map the internal address gateway.dmz.net:8080 to the external address of the firewall, which is www.server.com:80 as follows:

<network>
  <address-mapping>
    <external-address>www.server.com:80</external-address>
    <internal-address>gateway.dmz.net:8080</internal-address>
  </address-mapping>
  <address-mapping>
    <external-address>stock.server.com:443</external-address>
    <external-address>chat.server.com:443</external-address>
    <internal-address>gateway.dmz.net:9090</internal-address>
  </address-mapping>
</network>

This signals the Kaazing Gateway Server to listen on the internal address gateway.dmz.net:8080 to serve requests originally sent to the external address www.server.com:80.

Configure TLS

As mentioned previously, it is important that TLS (Transport Layer Security) is used to encrypt the wire traffic between the browser and the Kaazing Gateway so that the credentials, which are passed in plaintext in this scenario, are not subject to eavesdropping and wire traffic sniffing attacks. This is done by using a secure WebSocket connection. For example, wss://chat.server.com.

You configure TLS by creating and signing a private and public key pair that can be used by the Kaazing Gateway. See the section titled Configuring Wire Traffic Encryption in the Kaazing Administrator’s Guide for more information.

If desired, you can further lock down the network topology described in this scenario. For example, depending on how secure you need the wire traffic to be, you can configure TLS on the internal network. Traffic would then use different ports, but the configuration steps would remain the same.

Alternatively, you can configure some firewalls and load-balancing routers to handle the TLS encryption for your topology. In that case, traffic initially sent to the device at https://www.server.com can be decrypted by the firewall or load-balancing router and clear HTTP traffic can be sent to the Kaazing Gateway.

If the internal network represents a multi-level secure system, then you can choose to encrypt traffic between the different internal nodes of that network to prevent eavesdropping of potentially sensitive information. Traffic to and from the identity management directory server is shown to be using wire encryption already, as that is a common requirement in most scenarios.

Whether you need to fully lockdown your network topology depends on the type of data that is sent over the wire. For example, if the data is just an aggregation of non-sensitive, personalized data then you may not need to encrypt the all wire traffic, but if you are passing around sensitive information, that's a different story.

Important: Do not use the plaintext keyring in enterprise deployments of any kind. Instead, use the encrypted keyring and the Kaazing Keyring Service as described in scenario three.

Configure the Service Proxy Elements

To configure the gateway to communicate with the chat and the stock service, you must add two service elements to the gateway-config.xml configuration file.

For the stock service, you add a proxy element that accepts connections wss://stock.server.com (on port 443) and proxies TCP traffic to the stock server at tcp://stock.internal.net (on the default Stomp port 61613).

<!-- Proxy to STOMP server -->
<service>
  <!-- wss:// scheme refers to WebSocket (secure) -->
  <accept>wss://stock.server.com:443</accept>

  <type>proxy</type>
  <properties>
    <connect>tcp://stock.internal.net:61613</connect>
  </properties>

  <cross-site-constraint>
    <allow-origin>http://www.server.com</allow-origin>
  </cross-site-constraint>
</service>

The addition of the cross-site-constraint protects the service, only allowing access to the backend service from the site http://www.server.com. Access to backend services is denied by default and cross-site-constraints allow you to "white-list" cross-origin sites. The Kaazing Gateway provides support for the W3C Cross-Origin Resource Sharing specification, providing an emulation if it is not available in the browser. Using Cross-Origin Resource Sharing provides a way to explicitly and securely allow cross-origin sites access to the backend services.

For the chat service, you add a proxy service element that accepts connections at wss://chat.server.com (on port 443), proxies TCP traffic to the chat server at tcp://chat.internal.net (on port 5222), and allows access to the backend service from the site http://www.server.com.

<!-- Proxy to XMPP server -->
<service>
  <!-- wss:// scheme refers to WebSocket (secure) -->
  <accept>wss://chat.server.com:443</accept>

  <type>proxy</type>
  <properties>
    <connect>tcp://chat.internal.net:5222</connect>
  </properties>

  <cross-site-constraint>
    <allow-origin>http://www.server.com</allow-origin>
  </cross-site-constraint>
</service>

Summary

Using a secure WebSocket connection as shown in this scenario, protects the credentials that are sent in plaintext, but it has the unfortunate side effect that all communication to the Kaazing Gateway has to be encrypted; not just the login-related wire traffic. While this is secure, the use of TLS comes with additional overhead, which can affect performance and may be undesired.

Although the use of the plaintext keyring provides an easy-to-use API to handle the caching of credentials, they are still stored in plaintext on the client, which is vulnerable to a cross-site scripting attacks. If a cross-site script manages to inject code, to steal the user name and password, these credentials will be valid until the users change their password.

Scenario two provides more security by integrating with HTTP authentication.

Scenario 2—Plaintext Credentials Single Sign-On

Let’s take a look at a second scenario—a Web application with chat and stock components that interact with backend services through the Kaazing Enterprise Gateway. The plaintext keyring is used to cache the credentials, but this time a separate login component is added that is integrated with HTTP authentication to provide single sign-on. The stock and chat clients use the same credentials key, allowing the credentials to be shared. An encrypted session cookie protects the credentials, providing more security. Protocol awareness in the Kaazing Enterprise Gateway allows for the injection of credentials directly in the protocol communication.

Scenario 2

To log in to the chat application, users provide their name and password by clicking a login link on the Web page that directs them to a separate login user interface. Because the credentials are passed in plaintext form, login communication with the Gateway has to be configured to use TLS. However, since the login wire traffic is now routed separately, the remaining chat and stock communication does not have to be encrypted anymore (although it may be desired to use wire traffic encryption in some cases). The Kaazing Enterprise Gateway listens for regular WebSocket traffic (for example, ws://stock.server.com on port 80) and proxies it to the backend servers.

To leverage the plaintext keyring and integrate it with HTTP authentication to create a single sign-on environment requires programming and configuration on both the client side as well as the server side.

Client Side

This section describes the client-side programming required to leverage the plaintext keyring.

Create a Keyring and a Key

To leverage the credential caching and single sign-on benefits of the Kaazing Enterprise Gateway, you first create an instance of a PlaintextKeyring object to store the credentials in. Along with the type of storage, you pass the location of the gateway's session service (https://www.server.com/session), which is used to create the encrypted session cookie. This is required to integrate with HTTP authentication and will be covered in detail in the next section.

Next, you a create a key, called, for example, credentialsKey. To integrate with HTTP authentication, you do not specify a callback function this time (in scenario 1, you attached callback function authenticate to the creation of the key.) This automatically triggers HTTP authentication to kick in and the login request is directed to the session service, which will return an encrypted session cookie. The value of this encrypted session cookie contains an expiration timestamp.

var keyring = new PlaintextKeyring(document.sessionStorage,               "https://www.server.com/session");

var credentialsKey = keyring.createKey("sso"); // integrate HTTP authentication

keyring.onlogin = function(successful) {
  // Callback indicating that the HTTP login completed, successfully or not
}

// initiate login to session service
// heartbeat pings server to renew session at half session timeout interval
keyring.login({'username':..., 'password':...});

When the key is asked to resolve the credentials, it first checks the keyring's storage object (document.sessionStorage, in this example). If the credentials are not present there, the authenticate function is called to prompt the user to enter them. The credentials are then stored and subsequent attempts to resolve the key will be able to retrieve the cached value of the credentials from storage.

The login method also starts the “heartbeat” communication to keep the session alive by sending a heartbeat message from the browser to the server at an interval of half the session timeout value.

Create the Backend-Service Clients

To communicate with the stock service, you create a Stomp protocol stock client that can communicate directly with the backend stock service. The value of the connection URL is now using regular WebSocket (not secure WebSocket): ws://stock.server.com/.

var stockClient = new StompClient();
stockClient.connect("ws://stock.server.com/", credentialsKey);

stockClient.onopen = function() {
  // Callback indicating that the stock server login was successful
}

stockClient.onerror = function() {
  // Callback indicating that the stock server login unsuccessful (or other stock server error)
}

To communicate with the chat service, you create an XMPP protocol chat client that can communicate directly with the backend chat service. The value of the connection URL also uses WebSocket (not secure WebSocket): ws://chat.server.com/.

// The Chat server is configured for "[username]@chat.com" accounts

var chatClient = new XmppClient();
chatClient.connect("wss://chat.server.com/", "chat.com");

chatClient.onopen = function() {
  chatClient.authenticate(credentialsKey);
}

chatClient.onauthenticated = function() {
  // Callback indicating that the chat server login successful
}

chatClient.onerror = function() {
  // Callback indicating that the chat server login unsuccessful
}

The stock and chat clients use the same credentials key (credentialsKey). The services now rely on the login functionality and the HTTP authentication integration to return valid credentials that can be shared between the two clients.

Server side

This section describes the server-side configuration required to leverage the plaintext keyring.

Configuring Network Address Mapping

To configure the DMZ correctly, and to prevent the Kaazing Gateway Server from being unable to resolve the DNS name www.server.com, you use the network configuration address-mapping element to override the Kaazing Gateway's default behavior. In this example scenario, you map the internal address gateway.dmz.net:8080 to the external address of the firewall, which is www.server.com:80 as follows:

<network>
  <address-mapping>
    <external-address>www.server.com:443</external-address>
    <internal-address>gateway.dmz.net:9090</internal-address>
  </address-mapping>
  <address-mapping>
    <external-address>www.server.com:80</external-address>
    <external-address>stock.server.com:80</external-address>
    <external-address>chat.server.com:80</external-address>
    <internal-address>gateway.dmz.net:8080</internal-address>
  </address-mapping>
</network>

This signals the Kaazing Gateway Server to listen on the internal address gateway.dmz.net:8080 to serve requests originally sent to the external address www.server.com:80.

Configure TLS

It is important that TLS is used to encrypt the login wire traffic between the browser and the session service running on the Kaazing Gateway so that the credentials, which are passed in plaintext, are not subject to eavesdropping and wire traffic sniffing attacks. This is done by using an HTTPS connection. For example, https://www.server.com/session.

If desired, you can further lock down the network topology described in this scenario. For example, depending on how secure you need the wire traffic to be, you can configure TLS inside the DMZ (Demilitarized Zone) and even on the internal network. Traffic would then use different ports, but the configuration steps would remain the same. For example, you could use stomp+ssl://stock.internal.net:61614 instead of the regular stomp scheme.

Configure the session Service Element

To configure the session service on the Kaazing Enterprise Gateway, you must add a service element of type session to the gateway-config.xml configuration file. You configure the session service element so that it accepts connections at https://www.server.com/session and configure it to have an auth-constraint for the role AUTHENTICATED.

<!-- Export the session service -->
<service>
  <accept>https://www.server.com/session</accept>

  <type>session</type>

  <auth-constraint>
    <require-role>AUTHENTICATED</require-role>
  </auth-constraint>
</service>

When a request is made to the gateway's session service, the gateway finds the auth-constraint applied to it and tries to identify the end user so that it can enforce the constraint. The gateway then checks if either an authorization header or a session cookie was sent with the request. Neither one will be present in the first request from the browser.

The server then parses the host header from the request and extracts the host name. In this case, that is www.server.com. The server consults the configuration parameters that were supplied at server startup and looks for a session element that contains the www.server.com service domain to look up the authentication scheme.

Configure the Session Element

To associate a session with one or more services by matching the domain of each service's accept URL, you must add a session element to the gateway-config.xml configuration file and configure it to have the correct service domain.

<session>
    <!-- associate service realms automatically -->
    <service-domain>.server.com</service-domain>
    
    <!-- HTTP authentication configuration -->
    <authentication-scheme>Basic</authentication-scheme>
    <realm-name>demo</realm-name>
    
    <!-- Session cookie configuration -->
    <encryption-key-alias>session</encryption-key-alias>
    <inactivity-timeout>1800</inactivity-timeout>
</session>

In this case, the service domain is set to .server.com and not www.server.com (using a wider scope). This is done on purpose to allow the cookie to span the peer domains www.chat.server.com and www.stock.server.com so that the cookie, which contains the encrypted credentials, will be sent to those when accessing the stock and chat services.

The gateway sends a response, challenging the user to supply login credentials. The server uses the authentication scheme specified in the session element (authentication-scheme, in this example). The browser responds by providing the requested authentication information in the authorization header information of the request.

The server now finds the authorization header and decodes it to extract the supplied login credentials. The server reads the value of the host and port from the Host header. In this case, it contains www.server.com, and it looks for a session element that contains the .server.com service domain to look up the realm name, in this case demo.

<realm-name>demo</realm-name>

Configure the Security Element

Next, you must add and configure the security element in the gateway-config.xml file.

The realm-name value is used to look up the realm information for the request. The realm element is part of the security element in the gateway-config.xml file. The server checks the realm information to see which login modules are associated with it and passes the encoded user's login credential values to it.

<security>
  <keystore>
   <type>JCEKS</type>
   <file>keystore.db</file>
    <password-file>keystore.pw</password-file>
  </keystore>
    
  <realm>
    <name>demo</name>
    <description>Kaazing Gateway Demo</description>
    <login-module>
      <type>ldap</type>
      <success>required</success>
      <options>
        <userProvider>
          ldaps://directory/ou=people, dc=internal,dc=net
        </userProvider>
        <userFilter>
          <![CDATA[(&(uid={USERNAME})(objectClass=inetOrgPerson))]]>
        </userFilter>
        <authzIdentity>{EMPLOYEENUMBER}</authzIdentity>
      </options>
    </login-module>
  </realm>
</security>

The realm login modules are used to authenticate the end user's login credentials and establish the list of authorized roles that the user has. For example, AUTHENTICATED. Since this realm uses an LDAP-based login module, the server will consult the LDAP directory server. Communication with the directory server is configured to use TLS (ldaps).

If the user is successfully authenticated, the server proceeds to construct a cookie to send along with the HTTP response. Inactivity timeout information, as well as domain, name, user name and password information is stored in the cookie and to protect this information, the cookie is encrypted using a secret key stored in the keystore under the encryption key alias (session, in this example).

The server verifies that the user has been granted all the roles required by the auth-constraint for this request and continues to service the request, sending back the data and the cookie in the response. If the user had not been fully authorized, an additional challenge would have been sent to the browser.

When the cookie is present, subsequent requests follow the steps above and behave as if the authentication header was present, but instead the session cookie contains an encrypted version of the authorization header plus session expiration information.

Configure the Service Proxy Elements

To configure the gateway to communicate with the chat and the stock service, you must add the two service elements to the gateway-config.xml configuration file.

For the stock service, you add a proxy service element that accepts connections at ws://stock.server.com:80 and proxies Stomp traffic to the stock server at stomp://stock.internal.net. Since this scenario leverages single sign-on, you must guarantee that authentication with the gateway has completed before attempting to access the backend services. To do that, you must specify an auth-constraint with at least one required role (AUTHENTICATED in this case).

<!-- Proxy to STOMP server -->
<service>
  <accept>ws://stock.server.com:80</accept>

  <type>proxy</type>
  <properties>
    <connect>stomp://stock.internal.net</connect>
  </properties>

  <cross-site-constraint>
    <allow-origin>http://www.server.com</allow-origin>
  </cross-site-constraint>

  <auth-constraint>
    <require-role>AUTHENTICATED</require-role>
  </auth-constraint>
</service>

For the chat service, you add a proxy service element that accepts connections at ws://chat.server.com, proxies XMPP traffic to the chat server at xmpp://chat.internal.net, and allows access to the backend service from the site http://www.server.com.

<!-- Proxy to XMPP server -->
<service>
  <accept>ws://chat.server.com:80</accept>

  <type>proxy</type>
  <properties>
    <connect>xmpp://chat.internal.net</connect>
  </properties>

  <cross-site-constraint>
    <allow-origin>http://www.server.com</allow-origin>
  </cross-site-constraint>
</service>

In this scenario, you are using the Kaazing Enterprise Gateway, which is protocol aware and therefore the connect URLs can now use stomp (or xmpp) instead of tcp) and it can inject the single sign-on credentials automatically into the protocol to authenticate with the backend system.

Summary

Using HTTP authentication in conjunction with plaintext keyring and the Kaazing Enterprise Gateway provides several major improvements over scenario one when it comes to security. You no longer have to use wss for all protocol-communication wire traffic and the encrypted session cookie is used for the credentials instead of caching them in plaintext.

This scenario does still have some drawbacks though. Although the session cookie is encrypted, it can still be vulnerable to cross-site scripting attacks and If it is compromised, the credentials can be played back until the session expires, which is usually about of 30 minutes.

Another problem with this solution is that fully cross-site communication with backend services is not possible. The session needs to be domain-scoped to be able to pass the cookie to all the right places. Therefore, the backend services must be located on peer domains (stock.internal.net and chat.internal.net, for example).

Scenario three provides more security and by using the encrypted keyring and the Kaazing Keyring Service.

Scenario 3—Encrypted Credentials Single Sign-On

Let’s take a look at a third scenario—a similar Web application with chat and a stock components that interact with backend services through the Kaazing Enterprise Gateway. In this scenario, the Kaazing Keyring Service is used in conjunction with the encrypted keyring to provide a single sign-on environment.

Scenario 3

To log in to the chat application, users provide their name and password by clicking a login link on the Web page that directs them to a separate login user interface. Because the credentials are passed in plaintext form, login communication with the Gateway has to be configured to use TLS.

Similar to scenario two, the remaining chat and stock communication does not have to be encrypted, since the login wire traffic is now routed separately. The Kaazing Enterprise Gateway now listens for unencrypted WebSocket traffic (for example, ws://stock.server.com) and proxies it to the backend servers.

Instead of the encrypted session cookie created by the session service, this example uses the Kaazing Keyring Service to create new encrypted tokens to access the backend services. These encrypted tokens provide additional security, because they have a very short life span (typically less than a minute), which minimizes opportunity for token theft, yet maintains a stateless server implementation for horizontal scalability.

Note: since the encrypted keyring provides storage of encrypted credentials at the browser, single sign-on can also be achieved with the encrypted keyring without integrating directly with the keyring service. However, if any services on the gateway have auth-constraints applied against them, it may be desirable to use HTTP authentication integration for the single sign-on solution.

To leverage the Encrypted Keyring and the Kaazing Keyring Service to create a single sign-on environment requires programming and configuration on both the client side as well as the server side.

Client Side

This section describes the client-side programming required to leverage the encrypted keyring.

Create a Keyring and a Key

To leverage single sign-on benefits of the Kaazing Enterprise Gateway, you first create an instance of a EncryptedKeyring object to store the credentials in. Along with the type of storage, you pass the location of the Kaazing Keyring Service (https://www.keyring.com), which is used to create the encrypted tokens.

Next, you a create a key, called, for example, credentialsKey. To integrate with HTTP authentication, you do not specify a callback function this time. This automatically triggers HTTP authentication to kick in and the login request is directed to the session service, which will return an encrypted session cookie. The value of this encrypted session cookie also contains an expiration timestamp.

var keyring = new EncryptedKeyring(document.sessionStorage,               "https://www.keyring.com/");

var credentialsKey = keyring.createKey("sso"); // integrate HTTP authentication

keyring.onlogin = function(successful) {
// HTTP login completed, whether successful or not
}
// initiate login to Kaazing Keyring Service
// (pings server to renew session at half session timeout interval)
keyring.login({'username':..., 'password':...});

The encrypted Keyring asks the Kaazing Keyring Service to authorize the use and provide an encrypted token that can be used by the Kaazing Gateway. This token consists of the credentials and a timeout value.

Create the Backend-Service Clients

To communicate with the stock service, you create a Stomp protocol stock client that can communicate directly with the backend stock service. The value of the connection URL is now using regular WebSocket (not secure WebSocket): ws://www.stock.com/. Notice that we are no longer bound by the peer-domain restriction of the cookie-based approach from scenario 2; with the Kaazing Keyring Service services can now reside on different domains.

var stockClient = new StompClient();
stockClient.connect("ws://stock.server.com/", credentialsKey);

stockClient.onopen = function() {
  // stock server login successful
}

stockClient.onerror = function() {
  // stock server login unsuccessful (or other stock server error)
}

To communicate with the chat service, you create an XMPP protocol chat client that can communicate directly with the backend chat service. The value of the connection URL is now using regular WebSocket (not secure WebSocket): ws://chat.server.com/.

// The Chat server is configured for "[username]@chat.com" accounts

var chatClient = new XmppClient();
chatClient.connect("wss://www.chat.com/", "chat.com");

chatClient.onopen = function() {
  chatClient.authenticate(credentialsKey);
}

chatClient.onauthenticated = function() {
  // chat server login successful
}

chatClient.onerror = function() {
  // chat server login unsuccessful (or other chat server error)
}

Server side

This section describes the server-side configuration required to leverage the plaintext keyring.

Configuring Network Address Mapping

To configure the DMZ correctly, and to prevent the Kaazing Gateway Server from being unable to resolve the DNS name www.server.com, you use the network configuration address-mapping element to override the Kaazing Gateway's default behavior. In this example scenario, you create the following address-mappings.

<network>
  <address-mapping>
    <external-address>www.keyring.com:443</external-address>
    <internal-address>gateway.dmz.net:9090</internal-address>
  </address-mapping>
  <address-mapping>
    <external-address>www.server.com:80</external-address>
    <external-address>stock.server.com:80</external-address>
    <external-address>chat.server.com:80</external-address>
    <internal-address>gateway.dmz.net:8080</internal-address>
  </address-mapping>
</network>

Configure TLS

It is important that TLS is used to encrypt the login wire traffic between the browser and the session service running on the Kaazing Gateway so that the plaintext credentials, which are passed from the browser to the gateway, are not subject to eavesdropping and wire traffic sniffing attacks. This is done by using an HTTPS connection. For example, https://www.server.com/session.

If desired, you can further lock down the network topology described in this scenario. For example, depending on how secure you need the wire traffic to be, you can configure TLS inside the DMZ (Demilitarized Zone) and even on the internal network. Traffic would then use different ports, but the configuration steps would remain the same. For example, you could use stomp+ssl://stock.internal.net:61614 instead of the regular stomp scheme.

Configure the Keyring Service Element

To configure the keyring service on the Kaazing Enterprise Gateway, you must add a service element of type keyring to the gateway-config.xml configuration file. You configure the keyring service element so that it accepts connections at https://www.keyring.com and configure it to have an auth-constraint for the role AUTHENTICATED.

<!-- Export the keyring service -->
<service>
  <accept>https://www.keyring.com</accept>
  <type>keyring</type>

   <auth-constraint>
    <require-role>AUTHENTICATED</require-role>
  </auth-constraint>
  
  <cross-site-constraint>
    <allow-origin>http://www.server.com</allow-origin>
  </cross-site-constraint>

</service>

Configure the Session Element

To configure the session element on the Kaazing Enterprise Gateway, you must add a session element to the gateway-config.xml configuration file. Configure the session cookie scope to be www.keyring.com.

<session>
    <!-- associate service realms automatically -->
    <service-domain>www.keyring.com</service-domain>
    
    <!-- HTTP authentication configuration -->
    <authentication-scheme>Basic</authentication-scheme>
    <realm-name>demo</realm-name>
    
    <!-- Session cookie configuration -->
    <encryption-key-alias>session</encryption-key-alias>
    <inactivity-timeout>1800</inactivity-timeout>
</session>

Configure the Security Element

Next, you must add and configure the security element in the gateway-config.xml file.

<security>
  <keystore>
   <type>JCEKS</type>
   <file>keystore.db</file>
    <password-file>keystore.pw</password-file>
  </keystore>
    
  <realm>
    <name>demo</name>
    <description>Kaazing Gateway Demo</description>
    <login-module>
      <type>ldap</type>
      <success>required</success>
      <options>
        <userProvider>
          ldaps://directory/ou=people, dc=internal,dc=net
        </userProvider>
        <userFilter>
          (&amp;(uid={USERNAME})(objectClass=inetOrgPerson))
        </userFilter>
        <authzIdentity>{EMPLOYEENUMBER}</authzIdentity>
      </options>
    </login-module>
  </realm>
</security>

Configure the Service Proxy Elements

To configure the gateway to communicate with the chat and the stock service, you must add the two service elements to the gateway-config.xml configuration file. For the stock service, you add a proxy service element that accepts connections at ws://stock.server.com and proxies Stomp traffic to the stock server at stomp://stock.internal.net.

There is not need for auth-constraints here, because there is no longer a requirement for peer-domain scoped session in this Kaazing Keyring Service-based single sign-on solution; encrypted keyring tokens are used ins tread.

<!-- Proxy to STOMP server -->
<service>
  <accept>ws://www.stock.com:80</accept>

  <type>proxy</type>
  <properties>
    <connect>stomp://stock.internal.net</connect>
  </properties>

  <cross-site-constraint>
    <allow-origin>http://www.server.com</allow-origin>
  </cross-site-constraint>
</service>

For the chat service, you add a proxy service element that accepts connections at ws://www.chat.com, proxies TCP traffic to the chat server at xmpp://chat.internal.net, and allows access to the backend service from the site http://www.server.com.

<!-- Proxy to XMPP server -->
<service>
  <accept>ws://www.chat.com:80</accept>

  <type>proxy</type>
  <properties>
    <connect>xmpp://chat.internal.net</connect>
  </properties>

  <cross-site-constraint>
    <allow-origin>http://www.server.com</allow-origin>
  </cross-site-constraint>
</service>

Summary

Scenario three provides all the benefits of scenario two and more. The Kaazing Keyring Service does not rely on cookies and thus provides full cross domain service access. Cookie (or plaintext credentials) are never sent across an unsecured channel and cannot be sniffed; instead an encrypted token is passed around. This encrypted token has a very short life span (typically less than a minute), much smaller than the common session cookie expiration, which is often close to 30 minutes.

 

Adaptavist Theme Builder (3.2.1) Powered by Atlassian Confluence 2.9, the Enterprise Wiki.
Free theme builder license