X

Security Token Service and Identity Delegation with Metro

Guest Author

by Jiandong Guo

Metro is a high performance, extensible, easy-to-use
web services stack. It combines the JAX-WS reference implementation with Web Services Interoperability Technology (WSIT),
an implementation of numerous WS-\* standards to enable interoperability with other implementations and to provide
Quality of Service (QOS) features such as security, reliability, and transaction support. Metro is available in the open source,
enterprise-ready, modular
GlassFish v3 application server as well
as in the open source, enterprise-ready,
GlassFish v2 application server.
Metro also runs in the
Tomcat web container.
In addition, it has been successfully used in
other application servers.

WSIT implements the following web services security specifications published by the Organization for the Advancement
of Structured Information Standards (OASIS) consortium: WS-Security, WS-SecurityPolicy, WS-SecureConversation, and WS-Trust.
An earlier tech tip, Using WS-Trust Support in Metro to Secure Web Services,
focused on the support in Metro for WS-Trust. It described the basics
of WS-Trust and its Security Token Service (STS) framework and showed
how to take advantage of Metro's support of WS-Trust and STS to secure
a web service.

The latest release of Metro, Metro 2.0, provides
many enhancements and new features, which are described in
Metro 2.0 One Pagers.
Among those enhancements is support for WS-Trust 1.4 and WS-SecureConversation 1.4.
The following tip describes how you can use the enhanced support for WS-Trust and WS-SecureConversation in
Metro 2.0 to access a back-end resource through a chain of services.
You'll also learn how identity delegation in STS is used to access the back-end resource in a secure way.

A sample application package accompanies the tip. The package includes a sample application
that demonstrates the concepts and techniques described in this tip. The code examples shown in the tip are taken from
source code in the sample application.

Identity Delegation

To understand identity delegation, let's briefly review some basic concepts related to WS-Trust and STS.
WS-Trust is a WS-\* specification that provides extensions to the WS-Security specification. WS-Security provides the basic
framework for message level security in web services. WS-Trust builds on that base to specify a framework for broker trust
across different security domains. It specifically deals with the issuing, renewing, and validating of security tokens,
as well as with ways to establish, assess the presence of, and broker trust relationships between participants in
a secure message exchange.

For a web service and its client to communicate securely there needs to be a trust relationship established between the service
and the client. If the service and client are in the same security domain they can have a direct trust relationship.
In this type of relationship the service and client can authenticate each other directly.

However, if the client and the service are in different security domains they have no direct trust relationship. In that case,
you can use an STS to authenticate the client. The STS is an authority trusted by the client and the service. You can also use
an STS to issue a security token, that is, a collection of claims such as name, role, and authorization code, for the client
to access the service. A request for a security token is made by sending a Request Security Token (RST) message to the STS
using an <wst:RequestSecurityToken> element.

The STS approach works well if a client needs to securely access a
service in another domain. But what if the called
service needs to securely access another service on behalf of the
original client? For example, what if the client
needs to securely access a back-end resource through the second
service? In previous versions of WS-Trust, there was no way to pass
along
the authenticated identity of the client through this chain of
services. That obstacle was resolved in
the current version of the WS-Trust specification,
WS-Trust 1.4.

In particular, WS-Trust 1.4 defines extensions to the <wst:RequestSecurityToken> element for indicating
delegation and forwarding requirements on the requested security token. One of those extensions is the
<wst:ActAs> element. The specification defines the <wst:ActAs> element as follows:

This OPTIONAL element indicates that the requested token is expected to contain information about the identity represented
by the content of this element and the token requestor intends to use the returned token to act as this identity.
The identity that the requestor wants to act-as is specified by placing a security token or <wsse:SecurityTokenReference>
element within the <wst:ActAs> element.

In other words, by specifying a token in the <wst:ActAs> element of an RST — let's call
the <wst:ActAs> element the "ActAs" element — you can request
an STS to issue a security token that contains information about the identity
specified in the ActAs element. The identity in the ActAs element can be that of the original caller.
By specifying a token in the ActAs element — let's call the token the "ActAs token" — that identifies a client,
you can enable one service to call another service in a secure way on behalf of a client.

Figure 1 illustrates the control flow in a typical identity delegation scenario. Here a client, Client, wants
to access a back-end resource (not shown) across security domains. To do that, the client calls a service, Service, which in
turn calls a second service, Service 1, to access the resource.

Control Flow in an Identity Delegation Scenario

Figure 1. Control Flow in an Identity Delegation Scenario

  1. Client calls the STS using an RST to authenticate itself. Client obtains a token from the STS.
  2. Client forwards the STS-issued token to Service.
  3. Service calls the STS to authenticate itself using its credential. It also specifies an ActAs token in the RST that identifies
    Client. In response, the STS issues a security token whose subject is Client, but that also contains an "actas" attribute
    identifying Service. Let's call that token the Service token.
  4. Service calls Service1, passing it the Service token. By examining the Service token, Service1 recognizes
    that Service is acting on behalf of the initial requester, Client.
  5. Service1 accesses the back-end resource and sends a response to Service.
  6. Service forwards the response to Client.

Implementing Identity Delegation

In order to implement identity delegation, you need to add an ActAs token to the RST submitted by the pertinent service.
For example, in the identity delegation scenario illustrated in Figure 1, you need to add an ActAs token in the RST
issued by Service, and that ActAs token needs to identify Client.

To do this, you can take advantage of a new feature in Metro 2.0
that allows you to programmatically inject
STS information and token requirements into a web service client at run
time. The following code snippet shows the code you can add
to the web service client. You can find the code in the FSImpl class in the sample application.
This class implements a web service named IFinancialService. In the sample application, the IFinancialService
web service calls another web service, IPingService, to access a resource.

   import com.sun.xml.ws.api.security.trust.client.STSIssuedTokenConfiguration;
import com.sun.xml.ws.security.Token;
import com.sun.xml.ws.security.trust.impl.client.DefaultSTSIssuedTokenConfiguration;
import com.sun.xml.ws.security.trust.STSIssuedTokenFeature;
import javax.xml.ws.WebServiceFeature;
STSIssuedTokenConfiguration config = new DefaultSTSIssuedTokenConfiguration();
...
Token actAsToken = getActAsToken();
config.getOtherOptions().put(STSIssuedTokenConfiguration.ACT_AS, actAsToken);
STSIssuedTokenFeature feature = new STSIssuedTokenFeature(config);
IPingService stub = service.getCustomBindingIPingService(new WebServiceFeature[]{feature});

The DefaultSTSIssuedTokenConfiguration, STSIssuedTokenConfiguration, Token, and
STSIssuedTokenFeature classes are part of Metro's WS-Trust implementation. The WebServiceFeature
class is a JAX-WS class implemented in Metro.

In this approach you:

  • Create an STSIssuedTokenConfiguration object to hold the run-time configuration information.
  • Get the ActAs token as a Token object and add it to the configuration object.
  • Inject the configuration as a WebServiceFeature object.

Note that in the STS, both the subject for the requestor and the subject for the act-as user are
available in the STSAttributeProvider. The STSAttributeProvider class is a part of Metro's
WS-Trust implementation. The class exposes an extension to WS-Trust that enables details about the requestor to be included
in the token to be issued by the STS. If this extension is implemented, the provider implementation returns an
attribute that is included in a SAML assertion created by the STS.

The following code snippet is from an STSAttributeProvider implementation,
SampleSTSAttributeProvider, that is in the sample application.

   import com.sun.xml.ws.api.security.trust.\*;
public Map<QName, List<String>> getClaimedAttributes(Subject subject, String appliesTo, String tokenType, Claims claims){
// find the id of the requestor
String name = null;
Set<Principal> principals = subject.getPrincipals();
if (principals != null){
final Iterator iterator = principals.iterator();
while (iterator.hasNext()){
String cnName = principals.iterator().next().getName();
int pos = cnName.indexOf("=");
name = cnName.substring(pos+1);
break;
}
}
// Check if it is the ActAs case
if ("true".equals(claims.getOtherAttributes().get(new QName("ActAs")))){
// Get the ActAs token
Element token = null;
for (Object obj : claims.getSupportingProperties()){
if (obj instanceof Subject){
token = (Element)((Subject)obj).getPublicCredentials().iterator().next();
break;
}
}
// get the attributes to be included in the SAML assertion accordingly
...

Securing the Back-End Service

You can secure the back-end service in a chain of services, such as Service1 in the scenario illustrated in Figure 1,
with the token issued by the STS. You can also secure the back-end service with its own credential, such as an X509
certificate, or with both a token issued by the STS and a certificate. The back-end service must trust the STS, but
not necessarily have a direct trust relationship with the intermediate service. Unlike the Sender-Vouches case, the back-end
service should not ask for the intermediate service to provide any of its credentials to sign the issued token and the message.
Instead, it trusts the STS for the validity of the service token.

The NetBeans IDE offers an easy way to enable secure conversations
in Metro for a web service.
For details on using the NetBeans IDE to enable secure conversations
in Metro for a web service, see the tip
Using WS-Trust Support in Metro
to Secure Web Services.

The NetBeans IDE provides a set of security profiles that specify the mechanism
to be used in securing conversations. Four of these profiles secure web services with STS-issued tokens. Here are the four
profiles and the STS-issued token-based mechanisms they implement:

  • STS Issued Token. Symmetric binding with a symmetric keyed-issued token as a protection token.
  • STS Issued Token with Service Certificate. Asymmetric binding.
  • STS Issued Endorsing Token. Asymmetric binding with keyed-issued token as endorsing supporting token.
  • STS Issued Supporting Token. Symmetric binding with bearer-issued token as encrypted signed supporting token.

You can choose any of the four STS-issued token based mechanisms to secure the back-end service.

Securing the STS

In an identity delegation scenario involving a chain of services, as illustrated in Figure 1, messages exchanged between the
intermediate service and the STS are secured with service credentials and STS credentials. However, the only thing changed
in each request is the addition of an ActAs token to the message payload. In this situation, it makes sense
to enable a secure conversation for the STS through WS-SecureConversation. The WS-SecureConversation standard introduces
secure sessions on top of WS-Security. It enhances overall security through key derivations and improves performance by
avoiding repeated key exchanges in multi-message exchange scenarios. So by enabling a secure conversation for the STS, you
not only enhance overall security, but you can also improve performance.

You can enable a secure conversation for the STS in the same way as for a regular web service.
To take advantage of the secure conversation session with the STS, you must share a common STSIssuedTokenConfiguration
object with different calls from the intermediate service to the back-end service.

See the Tech Tip Secure Conversations
for Web Services With Metro
to learn the basics of WS-SecureConversation and see examples of using the WS-SecureConversation
support in Metro.

Token Propagation

Although this tip focuses on identity delegation as a technique for
securely accessing the back-end resource through a chain
of services, there is an alternative approach. The intermediate
service, such as Service in Figure 1, can propagate the end user's
identity
by calling the back-end service with the token it receives from the
client. This approach is called token propagation.
Figure 2 illustrates the control flow in a typical token propagation scenario.

Figure 2: Control Flow in a Token Propagation


  1. Client sends a request to the STS. The request message carries the username/password of the
    user and is secured with the STS certificate. The STS issues a SAML assertion containing the username
    as the subject ID, and the role attribute. The STS then sends a response message with the issued token to Client.
  2. Client sends a request to Service. The message carries the SAML assertion from the
    previous step for authentication, and is secured, that is, signed and encrypted, with the service certificate.
  3. Service sends a request to Service 1. The message carries the SAML assertion from the
    previous step and is secured, that is, signed and encrypted, with the Service 1 certificate. Service 1
    checks the SAML assertion.
  4. Service 1 sends a response to Service.
  5. Service forwards the response to Client.

Token propagation is more efficient than identity delegation with an
ActAs token. However, it is less secure than identity delegation
for the following reasons:

  • The back-end service won't be able to apply the AudiencesRestrictionCondition check on the SAML assertion.
    The AudiencesRestrictionCondition is used to restrict the validity of a SAML assertion to a specific audience.
  • The assertion has to be used as a unkeyed assertion from the intermediate requestor to the back-end service.

For these reasons, token propagation is a better choice for service chains in the same security domain. In any case, you
can configure the back-end service for token propagation using either of the following security mechanisms:

  • SAML Authorization with SSL. Transport binding using a SAML token as a SignedSupportingToken.
  • Symmetric binding using a SAML token as a SignedEncryptedSupportingToken.

The following code shows how to obtain the user SAML assertion in the intermediate service:

   Element samlAssertion = null;
Subject subj = SubjectAccessor.getRequesterSubject(context);
Set<Object> set = subj.getPublicCredentials();
for (Object obj : set) {
if (obj instanceof XMLStreamReader) {
XMLStreamReader reader = (XMLStreamReader) obj;
//To create a DOM Element representing the Assertion :
samlAssertion = SAMLUtil.createSAMLAssertion(reader);
break;
} else if (obj instanceof Element) {
samlAssertion = (Element) obj;
break;
}
}

Here is how to inject to the context for the proxy to the back-end service:

   ((BindingProvider)stub).getRequestContext().put("userSAMLAssertion", getSAMLAssertion());

You can find a complete code sample for token propagation
here.

The Sample Application

A sample application package that accompanies the tip. The package includes a sample
application that demonstrates identity delegation using ActAs. The STS in the sample application contains two
endpoints. One endpoint is for end users who require username/password for authentication. The other endpoint
is for the intermediate requestor that has secure conversation enabled and requires an X509 certificate for
authentication.

The intermediate service is configured to use the STS Issued Token mechanism, where an
issued token with a symmetric proof is used as the protection token.

The back-end service is configured to use an STS-issued endorsing
token, where the X509 certificate of the back-end service is used
as the protection token and an issued token with a public proof key is
as an endorsing supporting token.

To build, deploy, and run the sample, do the following:

  1. If you haven't already done so, download and install
    GlassFish v3
    or GlassFish v2 .
  2. (GlassFish v2 only.) If you haven't already done so, download and install Metro 2.0
    into GlassFish.
  3. If you use JDK 1.6, copy the webservices-api.jar file from the
    METRO_HOME/lib directory to the JAVA_HOME/jre/lib/endorsed directory, where METRO_HOME
    is the directory where you installed Metro 2.0, and JAVA_HOME is the directory where you installed JDK 6.
  4. Download the sample application package and extract its contents. You should now see a newly extracted directory named
    delegate.
  5. Copy the delegate/certs/xws-security directory to one of the following locations:



    • (GlassFish v3): GF_LOC/glassfish
    • (GlassFish v2): GF_LOC/glassfish

    where GF_LOC is the directory where you installed GlassFish.

    The delegate/certs/xws-security directory contains key stores for the sample.

  6. Edit the /delegate/src/fs/build.properties file to properly set glassfish.home to the location of GlassFish
    in your environment.
  7. In the following files, replace $WSIT_HOME with the GlassFish location:



    • /delegate/src/fs/etc/service/PingService.wsdl
    • /delegate/src/fs/etc/service1/PingService.wsdl
    • /delegate/src/fs/etc/client/wsit-client.xml
    • /delegate/src/fs/etc/service/client/wsit-client.xml
    • /delegate/src/fs/etc/sts/sts.wsdl
  8. Start GlassFish.
  9. Change the directory to /delegate/src/fs and enter the following commend from the command line:
       ant run-sample

    You will be prompted to enter a username and password. Enter the username alice and the password alice, or
    the username bob and the password bob. These two username-password pairs are preconfigured for use with the sample
    application.

    If the sample application runs successfully, you should see balance=100000.

About the Author

Jiandong Guo has lead the development of implementations and solutions based on WS-SecureConversation and WS-Trust in the
Metro project in Sun . He is currently a security architect in Oracle security and Identity management platform security group.

Join the discussion

Comments ( 9 )
  • antonio Sunday, May 30, 2010

    very good


  • guest Sunday, May 30, 2010

    very good


  • Ashish Monday, May 31, 2010

    I want Feedback


  • N Monday, May 31, 2010

    good


  • kuldeep sharma Wednesday, June 2, 2010

    good


  • guest Friday, June 4, 2010

    good


  • nayan Friday, June 4, 2010

    I downloaded the sample application package and followed instructions to run sample. It did not work with glassfish 3, JDK 6.

    Ant stopped with error:

    [ERROR] http://localhost:8080/jaxws-fs/simple?wsdl is unreachable

    On checking the autodeploy folder, I found that deployment of jaxws-fs-sts.war and jaxws-far.war failed. There were no messages in server.log, so I tried to manually deploy these 2 war files through glassfish console and got WSSTUBE0028: Error in creating new instance of SecurityServerTube

    The Netbeans project configuration included in the download does not seem to be complete. It does not contain list of files/folders that need to be on classpath. Not a big issue but quite a hassle to fix broken projects.


  • guest Friday, June 4, 2010

    great!


  • Raghav Friday, September 10, 2010

    Very good tutorial. Any idea of how to create a STS using CXF?


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.Captcha