Skip to main content

Adding Timestamps and Username Tokens

This topic discusses timestamps and user tokens.

Overview

A timestamp is the <Timestamp> security element in the WS-Security header. A timestamp is not strictly a security element. You can use it, however, to avoid replay attacks. Timestamps can also be useful for custom logging.

A username token is the <UsernameToken> security element in the WS-Security header; it carries a username. It can also carry the corresponding password (optionally in digest form). You typically use it for authentication, that is, to enable an InterSystems IRIS web client to use a web service that requires a password.

Caution:

The WS-Security header element is sent in clear text by default. To protect the password in a <UsernameToken>, you should use SSL/TLS, encrypt the <UsernameToken> (as described elsewhere), or use some combination of these techniques.

Adding a Timestamp

To add a timestamp to the WS-Security header element, do the following in your web client or web service:

  1. Call the Create() class method of %SOAP.Security.TimestampOpens in a new tab. This method takes one optional argument (the expiration interval in seconds). The default expiration interval is 300 seconds. For example:

     set ts=##class(%SOAP.Security.Timestamp).Create()
    

    This method creates an instance of %SOAP.Security.TimestampOpens in a new tab, sets the values for its Created, Expires, and TimestampAtEnd properties, and returns the instance. This instance represents the <Timestamp> header element.

  2. Call the AddSecurityElement() method of the SecurityOut property of your web client or web service. For the method argument, use the %SOAP.Security.TimestampOpens in a new tab instance you created. For example:

     do client.SecurityOut.AddSecurityElement(ts)
  3. Send the SOAP message. See the general comments in Adding Security Header Elements.

If you include a <Timestamp> element, InterSystems IRIS forces it to be first within <Security>.

Adding a Username Token

To add a username token, do the following in your web client:

  1. Optionally include the %soap.inc include file, which defines macros you might need to use.

  2. Call the Create() class method of %SOAP.Security.UsernameTokenOpens in a new tab. For example:

     set user="SYSTEM"
     set pwd="_SYS" 
     set utoken=##class(%SOAP.Security.UsernameToken).Create(user,pwd)

    The method has an optional third argument (type), which specifies how to include the password in the username token. This must be one of the following:

    • $$$SOAPWSPasswordText — Include the password in plain text. This is the default.

    • $$$SOAPWSPasswordDigest — Do not include the password but instead include its digest. The digest, Nonce, and Created timestamp are derived as specified by WS-Security 1.1.

      Important:

      This option is available only for SOAP clients interacting with third-party servers that support it. PasswordDigest authentication requires the server to store the plain-text password, which is not acceptable in a modern security environment. The PasswordDigest algorithm should be considered a legacy feature. To protect the password in a <UsernameToken>, you should use SSL/TLS, encrypt the <UsernameToken>, or use some combination of these techniques.

    • $$$SOAPWSPasswordNone — Do not include the password.

    This method creates an instance of %SOAP.Security.UsernameTokenOpens in a new tab, sets its Username and Password properties, and returns the instance. This object represents the <UsernameToken> header element.

    Note:

    If you are using this procedure to create a <UsernameToken> needed by a policy created by the Studio wizard, you must use the default type, $$$SOAPWSPasswordText, because the wizard does not generate policies that use other token types. You can, however, manually create a policy that uses the HashPassword assertion (which would use the type $$$SOAPWSPasswordDigest).

  3. Call the AddSecurityElement() method of the SecurityOut property of your web client or web service. For the method argument, use the %SOAP.Security.UsernameTokenOpens in a new tab instance you created. For example:

     do client.SecurityOut.AddSecurityElement(utoken)
  4. Send the SOAP message. See the general comments in Adding Security Header Elements.

Timestamp and Username Token Example

This example shows a web service that requires password authentication, and a web client that sends a timestamp and username token in its request messages.

Caution:

This example sends the username and password in clear text.

To make this example work in your own environment, first do the following:

  • For the web application to which the web service belongs, configure that application to support only password authentication:

    1. From the Management Portal home page, select System Administration > Security > Applications > Web Applications.

    2. Select the web application.

    3. Select only the Password option and then select Save.

  • Edit the client to use an appropriate InterSystems IRIS username and password, if you are not using the defaults.

The web service is as follows:

Class Tokens.DivideWS Extends %SOAP.WebService
{

Parameter SECURITYIN = "REQUIRE";

///  Name of the Web service.
Parameter SERVICENAME = "TokensDemo";

///  SOAP namespace for the Web service
Parameter NAMESPACE = "http://www.myapp.org";

///  Divide arg1 by arg2 and return the result. In case of error, call ApplicationError.
Method Divide(arg1 As %Numeric = 2, arg2 As %Numeric = 8) As %Numeric [ WebMethod ]
{
  Try {
      Set ans=arg1 / arg2
      }Catch{
      Do ..ApplicationError("division error")
      }
  Quit ans
}

///  Create our own method to produce application specific SOAP faults.
Method ApplicationError(detail As %String)
{
    //details not shown here
}

}

The following client-side class invokes the proxy client (not shown here) and adds a username token:

Include %systemInclude

Class TokensClient.UseClient
{

ClassMethod Test() As %Numeric
{
  Set client=##class(TokensClient.TokensDemoSoap).%New()
  
  Do ..AddSecElements(.client)
  Set ans=client.Divide(1,2)
  
  Quit ans
}

ClassMethod AddSecElements(ByRef client As %SOAP.WebClient)
{
   Set utoken=##class(%SOAP.Security.UsernameToken).Create("_SYSTEM","SYS")
   Do client.SecurityOut.AddSecurityElement(utoken)

   Set ts=##class(%SOAP.Security.Timestamp).Create()
   Do client.SecurityOut.AddSecurityElement(ts) 
   Quit
}

}

A sample message from this client is as follows:

<?xml version="1.0" encoding="UTF-8" ?>
<SOAP-ENV:Envelope [parts omitted]>
  <SOAP-ENV:Header>
   <Security xmlns="[parts omitted]oasis-200401-wss-wssecurity-secext-1.0.xsd">
      <Timestamp xmlns="[parts omitted]oasis-200401-wss-wssecurity-utility-1.0.xsd">
         <Created>2010-03-12T20:18:03Z</Created>
         <Expires>2010-03-12T20:23:03Z</Expires>
      </Timestamp>
      <UsernameToken>
         <Username>_SYSTEM</Username>
         <Password 
          Type="[parts omitted]#PasswordText">
            SYS
         </Password>
      </UsernameToken>
      </Security>
   </SOAP-ENV:Header>
   <SOAP-ENV:Body>
      [omitted]
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>
FeedbackOpens in a new tab