Securing Web Services
Adding Timestamps and Username Tokens
|
|
This chapter discusses timestamps and user tokens. It discusses the following topics:
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.
To add a timestamp to the WS-Security header element, do the following in your web client or web service:
-
set ts=##class(%SOAP.Security.Timestamp).Create()
-
do client.SecurityOut.AddSecurityElement(ts)
-
To add a username token, do the following in your web client:
-
Optionally include the
%soap.inc include file, which defines macros you might need to use.
-
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:
-
-
$$$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.
-
-
do client.SecurityOut.AddSecurityElement(utoken)
-
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:
-
-
Select the web application.
-
-
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>
Content Date/Time: 2019-02-22 00:52:40