Authentication of web services clients with a UsernameToken

The WebSphere® Application Server Liberty supports the OASIS Web Services Security UsernameToken Profile 1.1 specification. The specification describes how a web services client supplies a UsernameToken as a means of identifying the requestor by using a user name, and optionally by using a password or password-equivalent to the web services provider. The Web Services Security (WS-Security) run time in Liberty that processes the policy for the web services provider can use this identifying information to authenticate the user.

The requirement of a UsernameToken is expressed as one of the supporting tokens in the WS-Security policy. You can add a UsernameToken requirement as a required token in one of supporting token assertions, including SupportingTokens, SignedSupportingTokens, SignedEndorsingSupportingTokens, SignedEncryptedSupportingTokens, and EncryptedSupportingTokens.

The following example shows a sample policy fragment that requires a UsernameToken with password text to be sent in the Security header of a SOAP message to a web services provider:
<sp:SupportingTokens>
  <wsp:Policy>
    <sp:UsernameToken
      sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
      <wsp:Policy>
        <sp:WssUsernameToken11 />
      </wsp:Policy>
    </sp:UsernameToken>
  </wsp:Policy>
</sp:SupportingTokens>

In addition to the requirement of providing a user name or a password, you can configure a policy to include a nonce and created timestamp in a UsernameToken.

The following example shows a sample policy fragment that requires a UsernameToken with password text, nonce, and created timestamp to be sent in the Security header of a SOAP message to a web services provider:
<sp:SupportingTokens>
  <wsp:Policy>
    <sp:UsernameToken
      sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
      <wsp:Policy>
        <sp:WssUsernameToken11 />
        <sp13:Created />
        <sp13:Nonce />
      </wsp:Policy>
    </sp:UsernameToken>
  </wsp:Policy>
</sp:SupportingTokens>
The following example shows a sample policy fragment that requires a UsernameToken with password digest instead of password text:
<sp:SupportingTokens>
  <wsp:Policy>
    <sp:UsernameToken
      sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
      <wsp:Policy>
        <sp:WssUsernameToken11 />
        <sp:HashPassword />
      </wsp:Policy>
    </sp:UsernameToken>
  </wsp:Policy>
</sp:SupportingTokens>

For more information about nonce, created, and different password types, see the OASIS WS-Security policy 1.3 specification.

Providing a user name and password in a web services client

The WS-Security feature in Liberty provides more than one method for indicating the user name and password for a client application when generating a UsernameToken. You can set the user name and password programmatically or in the server.xml file.

A client can generate a UsernameToken with the user name and password provided in the server.xml file. The user name and password that is in the server.xml file is considered the default configuration and is overridden by what is provided on the RequestContext for the client's web service invocation.

The following example shows a sample default configuration:
<wsSecurityClient id="default"
    ws-security.username="alice"
    ws-security.callback-handler="com.acme.PasswordCallback"
</wsSecurityClient>
To generate a UsernameToken with the user name and password determined programmatically, you can set the following CXF properties on the RequestContext for the client's web service invocation:
  • ws-security.username - user name
  • ws-security.password - user password if ws-security.callback-handler is not defined
  • ws-security.callback-handler - the CallbackHandler implementation class used to obtain passwords
The following code sample shows how to provide a user name and password on the request context:
Map<String, Object> requestCtx = ((BindingProvider)port).getRequestContext();
requestCtx.put("ws-security.username", "bob_username");
requestCtx.put("ws-security.password", "bob_password");

Consuming a UsernameToken in a web services provider

When a UsernameToken is received, WS-Security automatically uses Liberty security user registry to validate the user name and password, if the password is required. If the password type in the UsernameToken is PasswordDigest or is using derived keys, you must provide the ws-security.callback-handler implementation of a password callback handler by configuring it in the server.xml file. This callback handler must return valid passwords for all expected user names so that the WS-Security run time can calculate digest values for comparison with the value in the SOAP message. After the digest value comparison completes successfully, the user name and password is validated against the user registry.

The following example illustrates a sample configuration in the server.xml file for password digest:
<wsSecurityProvider id="default"
    ws-security.callback-handler="com.acme.PasswordCallback"
</wsSecurityProvider>

Password CallbackHandler

The password CallbackHandler is used by WS-Security to retrieve a user password. In Liberty, this password CallbackHandler class must be packaged as a Liberty feature. For more information about the password CallbackHandler, see Developing a password callback handler for WS-Security.

For more information on requirements and limitations of a callback handler implementation, refer to the Private key password CallbackHandler section of Protection of web services with an X.509 token.

Protecting a UsernameToken in a SOAP message

When a UsernameToken is specified in a policy, the password type is password text (PasswordText) by default. When a password is sent with password text, it is sent in the message as-is. The following example shows a UsernameToken with a password type of PasswordText:
<UsernameToken>
  <Username>myusername</Username>
  <Password
    Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">
    mypassword
  </Password>
</UsernameToken>

When you want to send a UsernameToken with PasswordText, consider additional protections on the message, such as using HTTPS or encrypting the token using the EncryptedSupportingToken policy assertion. For more information on requiring the use of the HTTPS transport in the policy, see Liberty: Web services security HTTPS transport policy assertions.

UsernameToken key derivation

As stated in the Web Services Security UsernameToken Profile 1.1 specification:

The password associated with a username may be used to derive a shared secret key for the purposes of integrity or confidentiality protecting message contents.

It must be noted that passwords are subject to several kinds of attack, which in turn will lead to the exposure of any derived keys. This key derivation procedure is intended to minimize the risk of attacks on the keys, to the extent possible, but it is ultimately limited by the insecurity of a password that it is possible for a human being to remember and type on a standard keyboard.

Two additional elements are required to enable to derivation of a key from a password. They are <wsse11:Salt> and <wsse11:Iteration>. These values are not secret and must be conveyed in the Username token when key derivation is used. When key derivation is used the password must not be included in the Username token. The receiver will use its knowledge of the password to derive the same key as the sender.

If a UsernameToken is using key derivation, for a provider application, you must provide the ws-security.callback-handler implementation of a password callback handler by configuring it in the server.xml file.

The following example shows a policy fragment for a UsernameToken as a protection token with key derivation:
<sp:SymmetricBinding>
  <wsp:Policy>
    <sp:ProtectionToken>
      <wsp:Policy>
        <sp:UsernameToken
          sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
          <wsp:Policy>
            <sp:WssUsernameToken10 />
            <sp:RequireDerivedKeys />
          </wsp:Policy>
        </sp:UsernameToken>
      <wsp:Policy>
    </sp:ProtectionToken>
  </wsp:Policy>
</sp:SymmetricBinding>
The following example shows a sample UsernameToken in the security header when key derivation is used:
<wsse:UsernameToken wsse:Id="...">
  <wsse:Username>...</wsse:Username>
  <wsse11:Salt>...</wsse11:Salt>
  <wsse11:Iteration>...</wsse11:Iteration>
</wsse:UsernameToken>