PicketLink STS - SAML Profile

Introduction

This article presents the PicketLink STS SAML Profile implementation.

General Notes

Even though SAML profile says support for both SAML 1.1 and SAML 2 tokens (assertions) is required, our current implementation of the SAML assertion provider is capable of issuing SAML2 assertions only. We may add support for SAML 1.1 tokens later.

 

When the STS has been configured with a keystore (that is, the STS public and private keys are available), the issued assertion is signed using the STS private key. The resulting assertion looks like the following:

 

<wst:RequestSecurityTokenResponse Context="context" xmlns:wst=".." xmlns:wsu="..">
   <wst:TokenType>
      http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0
  
</wst:TokenType>
   ...
   <wst:RequestedSecurityToken>
      <saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"
                 xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
                 xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
                 ID="ID-f054188a-f79e-4740-8a8e-938e14e49cf5"
                 IssueInstant="2009-05-30T00:13:29.595Z">
         <saml2:Issuer>PicketLinkSTS</saml2:Issuer>
         <saml2:Subject>
            <saml2:NameID NameQualifier="urn:picketlink:identity-federation">sguilhen</saml2:NameID>
     
      <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"/>
         </saml2:Subject>
         <saml2:Conditions NotBefore="2009-05-30T00:13:29.595Z" NotOnOrAfter="2009-05-30T02:13:29.595Z"/>
         <ds:Signature>
            <ds:SignedInfo>
               <ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/>
               <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
               <ds:Reference URI="#ID-f054188a-f79e-4740-8a8e-938e14e49cf5">
                  <ds:Transforms>
                     <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
                  </ds:Transforms>
                  <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
                  <ds:DigestValue>7ayQgGyQ9+SyHBw9F8wu2QSTw7w=</ds:DigestValue>
               </ds:Reference>
            </ds:SignedInfo>
            <ds:SignatureValue>TcNs8JSVcHACOqxn9fH7CQpTJ7ds++o1tYyFnbuRvIH6oZANkb156/5MzF/myFt1F8b/Vz8r86rf
      PNGDnGUWtzNoUg66zadDmSR8aKdMp1gGtLl4D3x9O/1gYpMfrLgn2wHJxF2ZFMIt1AgNehxzWA56
      mZThBaELVw33O+oBbeA=</ds:SignatureValue>
            <ds:KeyInfo>
               <ds:KeyValue>
                  <ds:RSAKeyValue>
                     <ds:Modulus>suGIyhVTbFvDwZdx8Av62zmP+aGOlsBN8WUE3eEEcDtOIZgO78SImMQGwB2C0eIVMhiLRzVPqoW1
      dCPAveTm653zHOmubaps1fY0lLJDSZbTbhjeYhoQmmaBro/tDpVw5lKJns2qVnMuRK19ju2dxpKw
      lYGGtrP5VQv00dfNPbs=</ds:Modulus>
                     <ds:Exponent>AQAB</ds:Exponent>
                  </ds:RSAKeyValue>
               </ds:KeyValue>
            </ds:KeyInfo>
         </ds:Signature>
      </saml2:Assertion>
   </wst:RequestedSecurityToken>
   ...
</RequestSecurityTokenResponse>

 

Configuring the SAML20TokenProvider

The SAML20TokenProvider is enabled in the picketlink-sts.xml configuration file. All one needs to do is to add a new TokenProvider configuration that specifies that SAMLV2.0 token types must be handled by this provider:

 

<PicketLinkSTS xmlns="urn:picketlink:identity-federation:config:1.0"
     STSName="PicketLinkSTS" TokenTimeout="7200" EncryptToken="false">
     <KeyProvider ClassName="org.picketlink.identity.federation.bindings.tomcat.KeyStoreKeyManager">
          <Auth Key="KeyStoreURL" Value="keystore/sts_keystore.jks"/> 
            <Auth Key="KeyStorePass" Value="testpass"/>
            <Auth Key="SigningKeyAlias" Value="sts"/>
            <Auth Key="SigningKeyPass" Value="keypass"/>
     </KeyProvider>
     <TokenProviders>
          <!-- Custom token provider -->
          <TokenProvider ProviderClass="org.picketlink.test.identity.federation.bindings.wstrust.SpecialTokenProvider"
               TokenType="http://www.tokens.org/SpecialToken"/>
          <!-- Standard SAMLV2.0 token provider -->
          <TokenProvider ProviderClass="org.picketlink.identity.federation.api.wstrust.plugins.saml.SAML20TokenProvider"
               TokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0"/>
     </TokenProviders>
</PicketLinkSTS>

 

It is important to note that the issued SAMLV2.0 assertion will be signed only when a keystore has been configured, like in the example shown above. The keystore URL must either be the full path to a keystore in the file system or a path that is relative to the WEB-INF/classes directory of the PicketLink STS war file. In the previous example, the keystore should be located in WEB-INF/classes/keystore/.

SAML Token Validation

The SAML20TokenProvider is capable of validating the SAML assertions it issues. This is accomplished  by sending a WS-Trust validate message to the STS. The validate request must include the assertion that is to be validated and looks like the following:

<wst:RequestSecurityToken xmlns:wst="..">
   <wst:TokenType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/RSTR/Status</wst:TokenType>
   <wst:RequestType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/Validate</wst:RequestType>
   <wst:ValidateTarget>
      <saml2:Assertion xmlns:saml2=...>
         ...
      </saml2:Assertion>
   </wst:ValidateTarget>
</wst:RequestSecurityToken>

Upon receiving the validation request, the STS finds the provider that can validate the specified token, and delegates the validation to the selected provider. The validation performed by SAML20TokenProvider produces a status that is returned in a WS-Trust response. A successful validation response looks like the following:

<wst:RequestSecurityTokenResponse xmlns:wst="...”>
   <wst:TokenType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/RSTR/Status</wst:TokenType>
   <wst:Status>
      <wst:Code>http://docs.oasis-open.org/ws-sx/ws-trust/200512/status/valid</wst:Code>
      <wst:Reason>SAMLV2.0 Assertion successfuly validated</wst:Reason>
   </wst:Status>
<wst:RequestSecurityTokenResponse>  

 

SAML Subject Confirmation Methods

Bearer

A bearer assertion is a "keyless" assertion that is mainly used as a supporting token. In other words, a bearer assertion is typically used to provide more information about the client while the client has already proved his identity to the service using a different token or mechanism.

 

Any WS-Trust request that doesn't include a key (symmetric or public) and is not made on behalf of another identity will result in a bearer assertion being issued by the STS. So, in a sense, this can be considered the default subject confirmation method.

Holder of Key

A subject confirmation method of type holder-of-key contains information about the key that must be used to verify the client's identity. If the key is a symmetric key, the client proves possession of the token by encrypting part (or all) of the request message that is sent to the service provider. If the key is a public key, the client proves possession of the token by signing part (or all) of the whole request message that is sent to the service provider.

 

The key to be used can be specified in the WS-Trust request message. If a key of type SymmetricKey is used, then the client-provided key is combined with the STS generated key and the resulting key is inserted in the subject confirmation method. They key is also returned to the client as part of the WS-Trust response. If a key of type PublicKey is used, the client's public key or public key certificate is used as the proof of possession token and is inserted in the subject confirmation method.

Sender Vouches

A subject confirmation method of type sender-vouches is used when a message is sent by an entity on behalf of the assertion principal. In other words, the service provider trusts the message sender and will accept requests made by this sender on behalf of other identities.

 

To obtain an assertion with the sender-vouches confirmation method, the trusted entity must request a token from the STS and specify the assertion principal using the OnBehalfOf element. Upon receiving such a request, the STS will issue an assertion for the identity specified by the OnBehalfOf element (instead of issuing the assertion for the trusted entity). The trusted entity uses this assertion to call a service provider on behalf of the assertion principal.

Configuring an attribute provider

The SAML20TokenProvider can be configured with an attribute provider that will be used to obtain the attributes that must be inserted into the SAML assertions.

 

This is accomplished by implementing the SAML20TokenAttributeProvider interface and specifying the implementation class in the AttributeProvider property:

 

     <TokenProvider ProviderClass="org.picketlink.identity.federation.core.wstrust.plugins.saml.SAML20TokenProvider"
            TokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0"
            TokenElement="Assertion"
            TokenElementNS="urn:oasis:names:tc:SAML:2.0:assertion">
         <Property Key="AttributeProvider" Value="org.mycompany.myproject.MyProvider"/>
     </TokenProvider>

 

The SAML20TokenAttributeProvider interface defines two methods: initialize, that receives a properties map (same properties that were set for the SAML20TokenProvider), and getAttributeStatement, that returns an AttributeStatementType containing the attributes:

 

package org.picketlink.identity.federation.core.wstrust.plugins.saml;

import java.util.Map;

import org.picketlink.identity.federation.saml.v2.assertion.AttributeStatementType;

/**
 * <p>
 * An interface used by {@code SAML20TokenProvider} to retrieve an environment specific attribute that will be
 *  inserted into the Assertion.
 * </p>
 * 
 * @author <a href="mailto:Babak@redhat.com">Babak Mozaffari</a>
 */
public interface SAML20TokenAttributeProvider
{
   /**
    * Sets properties on the Attribute Provider that may affect its behavior
    * 
    * @param properties A set of string properties, some or all of which might impact the provider's behavior
    */
   void setProperties( Map<String, String> properties );

   /**
    * Given the security context, environment or other static or non-static criteria, returns an attribute statement
    *  to be included in the SAML v2 Assertion
    * 
    * @return An Attribute Statement to be inserted in the SAML v2 Assertion
    */
   AttributeStatementType getAttributeStatement();
}

 

PicketLink contains an implementation of SAML20TokenAttributeProvider to be used on JBoss Application Server. Its the org.picketlink.identity.federation.bindings.jboss.auth.SAML20TokenRoleAttributeProvider

 

This implementation extracts the roles of the authenticated principal from the Subject and sets them as attributes in the SAML assertion. As it uses internal JBoss AS APIs to get ahold of the Subject, this implementation can only be used if the STS is deployed on JBoss AS.