Tuesday, November 22, 2011

Apache CXF STS documentation - part XII

A previous blog post detailed the AbstractOperation class that provides some core functionality for the STS operations, such as parsing the client request into a format that the TokenProviders/TokenValidators/TokenCancellers can consume. In this, the final post of this series of articles on the Apache CXF STS, we will examine an extension of AbstractOperation that is used to cancel tokens. Finally, we will look at the STS sample that ships with the CXF 2.5.x distribution.

1) The TokenCancelOperation

TokenCancelOperation is used to cancel tokens in the STS. It implements the CancelOperation interface in the STS provider framework. In addition to the properties that it inherits from AbstractOperation (detailed previously), it has a single property that can be configured:

  • List<TokenCanceller> tokencancellers - A list of TokenCanceller implementations to use to cancel tokens.

Recall that AbstractOperation uses the RequestParser to parse a client request into TokenRequirements and KeyRequirements objects. TokenCancelOperation first checks that a "CancelTarget" token was received and successfully parsed (if so it will be stored in the TokenRequirements object). If no token was received then an exception is thrown.

TokenCancelOperation then populates a TokenCancellerParameters object with values extracted from the TokenRequirements and KeyRequirements objects. It iterates through the list of defined TokenCanceller implementations to see if any "can handle" the received token. If no TokenCanceller is defined, or if no TokenCanceller can handle the received token, then an exception is thrown. Otherwise, the received token is cancelled. If there is an error in cancelling the token, then an exception is also thrown. A response is constructed with the context attribute (if applicable), and the cancelled token type.

2) The STS sample in Apache CXF

Finally, we'll take a brief look at the STS sample that ships with Apache CXF. Download and extract the Apache CXF 2.5.x distribution. Navigate into "samples/sts" and take a look at the README.txt. The service provider has a policy that requires a SAML 2.0 token issued by an STS. The client authenticates itself to the STS with a UsernameToken over the symmetric binding. The STS issues a SAML 2.0 token to the client, which sends it to the service. The IssuedToken is defined as an InitiatorToken of an Asymmetric binding in the policy of the service, and so the client will use the secret key associated with the Subject of the Assertion to sign various parts of the message.

Build the sample with "mvn install", and then open up three separate command prompts. Start the STS with "mvn -Psts" in one, and start the service with "mvn -Pserver" in another. Finally, start the sample in the other window with "mvn -Pclient". You will see the (encrypted) messages flowing first between the client and the STS, and then between the client and the service provider.

Monday, November 21, 2011

Apache CXF STS documentation - part XI

A previous blog post detailed the AbstractOperation class that provides some core functionality for the STS operations, such as parsing the client request into a format that the TokenProviders/TokenValidators/TokenCancellers can consume. In this post we will examine an extension of AbstractOperation that is used to validate tokens.

1) The TokenValidateOperation

TokenValidateOperation is used to validate tokens in the STS. It implements the ValidateOperation interface in the STS provider framework. In addition to the properties that it inherits from AbstractOperation (detailed previously), it has a single property that can be configured:

  • List<TokenValidator> tokenValidators - A list of TokenValidator implementations to use to validate tokens.

Recall that AbstractOperation uses the RequestParser to parse a client request into TokenRequirements and KeyRequirements objects. TokenValidateOperation first checks that a "ValidateTarget" token was received and successfully parsed (if so it will be stored in the TokenRequirements object). If no token was received then an exception is thrown.

2) Token validation and response

TokenValidateOperation then populates a TokenValidatorParameters object with values extracted from the TokenRequirements and KeyRequirements objects. It iterates through the list of defined TokenValidator implementations to see if any "can handle" the received token. If no TokenValidator is defined, or if no TokenValidator can handle the received token, then an exception is thrown. Otherwise, the received token is validated. The TokenValidateOperation then checks to see whether token transformation is required.

2.1) Token Transformation

If the received token is successfully validated, and if the client supplies a TokenType in the request that does not correspond to the WS-Trust "status" namespace, then the TokenValidateOperation attempts to transform the validated token into a token of the requested type. Token transformation works in a similar way to token issuing, as detailed previously. A TokenProviderParameters object is constructed and the same processing steps (Realm parsing, AppliesTo parsing) are followed as for token issuing.

One additional processing step occurs before the token is transformed. If the TokenValidatorResponse object has a principal that was set by the TokenValidator implementation, then it is set as the principal of the TokenProviderParameters object. However, it is possible that the token is being issued in a different realm to that of the validated token, and the principal might also need to be transformed. Recall that the STSPropertiesMBean configuration object defined on AbstractOperation has an IdentityMapper property. This interface is used to map identities across realms. It has a single method:

  • Principal mapPrincipal(String sourceRealm, Principal sourcePrincipal, String targetRealm) - Map a principal from a source realm to a target realm

If the source realm is not null (the realm of the validated token as returned in TokenValidatorResponse), and if it does not equal the target realm (as set by the RealmParser), then the identity mapper is used to map the principal to the target realm and this is stored in TokenProviderParameters for use in token generation. After the (optional) identity mapping step, TokenValidateOperation iterates through the TokenProvider list to find an implementation that can "handle" the desired token type in the given (target) realm (if applicable). If no TokenProvider is defined, or if no TokenProvider can handle the desired token type, then an exception is thrown.

2.2) Token response

After token validation has been performed, and after any optional token transformation steps, a response object is constructed containing the following items:

  • The context attribute (if any was specified).
  • The received Token Type (if any was specified, or the "status" token type if validation was successful).
  • Whether the received token was valid or not (status code & reason).
  • If the received token was valid, and if token transformation successfully occurred:
    • The transformed token.
    • The lifetime of the transformed token.
    • A number of references to that token (can be disabled by configuration).
3) TokenValidateOperation example

Finally, it's time to look at an example of how to spring-load the STS so that it can validate tokens. This particular example uses a security policy that requires a UsernameToken over the transport binding (client auth is disabled). As the STS is a web service, we first define an endpoint:

<jaxws:endpoint id="transportSTS"
    implementor="#transportSTSProviderBean"
    address="http://.../SecurityTokenService/Transport"
    wsdlLocation=".../ws-trust-1.4-service.wsdl"
    xmlns:ns1="http://docs.oasis-open.org/ws-sx/ws-trust/200512/"
    serviceName="ns1:SecurityTokenService"
    endpointName="ns1:Transport_Port">
    <jaxws:properties>
        <entry key="ws-security.callback-handler" value="..."/>
    </jaxws:properties>
</jaxws:endpoint>

The CallbackHandler JAX-WS property is used to validate the UsernameToken. The "implementor" of the jaxws:endpoint is the SecurityTokenServiceProvider class defined in the STS provider framework:

<bean id="transportSTSProviderBean"
    class="org.apache.cxf.ws.security.sts.provider.SecurityTokenServiceProvider">
    ...
    <property name="validateOperation" ref="transportValidateDelegate"/>
</bean>

This bean supports the Validate Operation via a TokenValidateOperation instance:

<bean id="transportValidateDelegate"
    class="org.apache.cxf.sts.operation.TokenValidateOperation">
    <property name="tokenValidators" ref="transportTokenValidators"/>
    <property name="stsProperties" ref="transportSTSProperties"/>
</bean>

This TokenValidateOperation instance has a number of different TokenValidator instances configured:

<util:list id="transportTokenValidators">
    <ref bean="transportSamlTokenValidator"/>
    <ref bean="transportX509TokenValidator"/>
    <ref bean="transportUsernameTokenValidator"/>
</util:list>

<bean id="transportX509TokenValidator"
    class="org.apache.cxf.sts.token.validator.X509TokenValidator"/>

<bean id="transportUsernameTokenValidator"
    class="org.apache.cxf.sts.token.validator.UsernameTokenValidator"/>

<bean id="transportSamlTokenValidator"
    class="org.apache.cxf.sts.token.validator.SAMLTokenValidator"/>
</bean>

Finally the STSPropertiesMBean object that is used is given as follows:

<bean id="transportSTSProperties"
    class="org.apache.cxf.sts.StaticSTSProperties">
    <property name="signaturePropertiesFile" value="..."/>
    <property name="signatureUsername" value="mystskey"/>
    <property name="callbackHandlerClass" value="..."/>
    <property name="encryptionPropertiesFile" value="..."/>
    <property name="issuer" value="DoubleItSTSIssuer"/>
    <property name="encryptionUsername" value="myservicekey"/>
</bean>

Tuesday, November 15, 2011

Apache CXF STS documentation - part X

The previous blog post introduced the TokenIssueOperation, which is used to issue tokens in the STS. The article covered the various processing steps that the TokenIssueOperation does on the parsed request, before it calls a TokenProvider instance to provide a token that is returned to the client. One step that was not covered was claims handling, as this is a complex topic that merits a deeper discussion. In this post, we will look at how claims are handled in the STS as a whole.

1) Claims Handling in the STS

A typical scenario for WS-Trust is when the client requires a particular security token from an STS to access a service provider. The service provider can let the client know what the requirements are for the security token in an IssuedToken policy embedded in the WSDL of the service. In particular, the service provider can advertise the claims that the security token must contain in the policy (either directly as a child element of IssuedToken, or else as part of the RequestSecurityTokenTemplate). An example is contained in the STS systests:

<sp:RequestSecurityTokenTemplate>
    <t:TokenType>http://...#SAMLV1.1</t:TokenType>
    <t:KeyType>http://.../PublicKey</t:KeyType>
    <t:Claims Dialect="http://.../identity">
        <ic:ClaimType Uri="http://.../claims/role"/>
    </t:Claims>
</sp:RequestSecurityTokenTemplate>

This template specifies that a SAML 1.1 Assertion is required with an embedded X509 Certificate in the subject of the Assertion. The issued Assertion must also contain a "role" claim. The template is sent verbatim by the client to the STS when requesting a security token.

1.1) Parsing claims

The RequestParser object parses the client request into TokenRequirements and KeyRequirements objects. As part of this processing it converts a received Claims element into a RequestClaimCollection object. The RequestClaimCollection is just a list of RequestClaim objects, along with a dialect URI. The RequestClaim object holds the claimType URI as well as a boolean indicating whether the claim is optional or not.

1.2) The ClaimsHandler

The ClaimsHandler is an interface that the user must implement to be able to "handle" a requested claim. It has two methods:

  • List getSupportedClaimTypes() - Return the list of ClaimType URIs that this ClaimHandler object can handle.
  • ClaimCollection retrieveClaimValues(Principal principal, RequestClaimCollection claims) - Return the claim values associated with the requested claims (and client principal).

The ClaimCollection object that is returned is just a list of Claim objects. This object represents a Claim that has been processed by a ClaimsHandler instance. It essentially contains a number of properties that the ClaimsHandler implementation will set, e.g.:

  • URI claimType - The claimtype URI as received from the client.
  • String value - The claim value

Each Claim object in a ClaimCollection corresponds to a RequestClaim object in the RequestClaimCollection, and contains the Claim value corresponding to the requested claim. How the ClaimsHandler is invoked to create the ClaimCollection will be covered later. The STS ships with a single ClaimsHandler implementation, the LDAPClaimsHandler, which can retrieve claims from an LDAP store. A simpler example is available in the unit tests.

1.3) The ClaimsManager

Recall that in the previous post, the TokenIssueOperation has a single additional property that can be configured:

  • ClaimsManager claimsManager - An object that is used to handle claims.

The ClaimsManager holds a list of ClaimsHandler objects. So to support claim handling in the STS, it is necessary to implement one or more ClaimsHandler objects for whatever Claim URIs you wish to support, and register them with a ClaimsManager instance, which will be configured on the TokenIssueOperation object.

As detailed in the previous article, the TokenIssueOperation gets the realm of the current request, and does some processing of the AppliesTo address, after the RequestParser has finished parsing the request. The RequestClaimCollection object that has been constructed by the RequestParser is then processed. For each RequestClaim in the collection, it checks to see whether the ClaimsManager has a ClaimsHandler implementation registered that can "handle" that Claim (by checking the URIs). If it does not, and if the requested claim is not optional, then an exception is thrown.

If a ClaimsHandler implementation is registered with the ClaimsManager that can handle the desired claim, then the claims are passed through to the TokenProvider implementation, which is expected to be able to invoke the relevant ClaimHandler object, and insert the processed Claim into the generated security token. How this is done is entirely up to the user. For example, for the use-case given above of a SAML 1.1 token containing a "role" claim, the user could implement a custom AttributeStatementProvider instance that evaluates the claim values (via a custom ClaimsHandler implementation registered with the ClaimsManager) and constructs a set of Attributes accordingly in an AttributeStatement. An example of how to do this is given in the unit tests.

Thursday, November 10, 2011

Apache CXF STS documentation - part IX

The previous blog post detailed the AbstractOperation class that provides some core functionality for the STS operations, such as parsing the client request into a format that the TokenProviders/TokenValidators/TokenCancellers can consume. In this post we will examine an extension of AbstractOperation that is used to issue tokens.

1) The TokenIssueOperation

TokenIssueOperation is used to issue tokens in the STS. It implements the IssueOperation and IssueSingleOperation interfaces in the STS provider framework. In addition to the properties that it inherits from AbstractOperation (detailed in the previous post), it has a single property that can be configured:

  • ClaimsManager claimsManager - An object that is used to handle claims. This will be covered in a future post.

Recall that AbstractOperation uses the RequestParser to parse a client request into TokenRequirements and KeyRequirements objects. TokenIssueOperation populates a TokenProviderParameters object with values extracted from the TokenRequirements and KeyRequirements objects. A number of different processing steps then occur before a TokenProvider implementation is used to retrieve the desired token, comprising of realm parsing, claims handling, and AppliesTo parsing. Claims handling will be discussed in the next article.

1.1) Realm Parsing

We have discussed how realms are used with TokenProviders to provide tokens, and also how they work with TokenValidators to validate a given token. However, we did not cover how realms are defined in the first place. Recall that the STSPropertiesMBean configuration object defined on AbstractOperation has a RealmParser property. The RealmParser is an interface which defines a pluggable way of defining a realm for the current request. It has a single method:

  • String parseRealm(WebServiceContext context) - Return the realm of the current request given a WebServiceContext object.

Therefore if you wish to issue tokens in multiple realms, it is necessary to create an implementation of the RequestParser which will return a realm String given a context object. For example, different realms could be returned based on the endpoint URL or a HTTP parameter. This realm will then get used to select a TokenProvider implementation to use to issue a token of the desired type. It will also be used for token validation in a similar way.

1.2) AppliesTo parsing

An AppliesTo element contains an address that refers to the recipient of the issued token. If an AppliesTo element was sent as part of the request then the CXF STS requires that it must be explicitly handled. This is done by the list of ServiceMBean objects that can be configured on AbstractOperation. The ServiceMBean interface represents a service, and has the following methods (amongst others):

  • boolean isAddressInEndpoints(String address) - Return true if the supplied address corresponds to a known address for this service.
  • void setEndpoints(List<String> endpoints) - Set the list of endpoint addresses that correspond to this service.

The STS ships with a single implementation of this interface, the StaticService. For the normal use-case of handling an AppliesTo element, the user creates a StaticService object and calls setEndpoints with a set of Strings that correspond to a list of regular expressions that match the allowable set of token recipients (by address). The TokenIssueOperation will extract the URL address from the EndpointReference child of the received AppliesTo element, and then iterate through the list of ServiceMBean objects and ask each one whether the given address is known to that ServiceMBean object. If an AppliesTo address is received, and no ServiceMBean is configured that can deal with that URL, then an exception is thrown.

The ServiceMBean also defines a number of optional configuration options, such as the default KeyType and TokenType Strings to use for that Service, if the client does not supply them. It also allows the user to set a custom EncryptionProperties object, which defines a set of acceptable encryption algorithms to use to encrypt issued tokens for that service.

2) Token creation and response

Once the TokenIssuerOperation has processed the client request, it iterates through the list of defined TokenProvider implementations to see if each "can handle" the desired token type in the configured realm (if any). If no TokenProvider is defined, or if no TokenProvider can handle the desired token type, then an exception is thrown. Otherwise, a token is created, and a response object is constructed containing the following items:

  • The context attribute (if any was specified).
  • The Token Type.
  • The requested token (possibly encrypted, depending on configuration).
  • A number of references to that token (can be disabled by configuration).
  • The received AppliesTo address (if any).
  • The RequestedProofToken (if a Computed Key Algorithm was used).
  • The Entropy generated by the STS (if any, can be encrypted).
  • The lifetime of the generated token.
  • The KeySize that was used (if any).

3) TokenIssueOperation Example

Finally, it's time to look at an example of how to spring-load the STS so that it can issue tokens. This particular example uses a security policy that requires a UsernameToken over the symmetric binding. As the STS is a web service, we first define an endpoint:

<jaxws:endpoint id="UTSTS"
    implementor="#utSTSProviderBean"
    address="http://.../SecurityTokenService/UT"
    wsdlLocation=".../ws-trust-1.4-service.wsdl"
    xmlns:ns1="http://docs.oasis-open.org/ws-sx/ws-trust/200512/"
    serviceName="ns1:SecurityTokenService"
    endpointName="ns1:UT_Port">
    <jaxws:properties>
        <entry key="ws-security.callback-handler" value="..."/>
        <entry key="ws-security.signature.properties" value="stsKeystore.properties"/>
    </jaxws:properties>
</jaxws:endpoint>

The jaxws:properties are required to parse the incoming message. The CallbackHandler is used to validate the UsernameToken and provide the password required to access the private key defined in the signature properties parameter. The "implementor" of the jaxws:endpoint is the SecurityTokenServiceProvider class defined in the STS provider framework:

<bean id="utSTSProviderBean"
    class="org.apache.cxf.ws.security.sts.provider.SecurityTokenServiceProvider">
    <property name="issueOperation" ref="utIssueDelegate"/>
    ...
</bean>

This bean supports the Issue Operation via a TokenIssueOperation instance:

<bean id="utIssueDelegate"
    class="org.apache.cxf.sts.operation.TokenIssueOperation">
    <property name="tokenProviders" ref="utSamlTokenProvider"/>
    <property name="services" ref="utService"/>
    <property name="stsProperties" ref="utSTSProperties"/>
</bean>

This TokenIssueOperation instance has a single TokenProvider configured to issue SAML Tokens (with a default Subject and Attribute statement):

<bean id="utSamlTokenProvider"
    class="org.apache.cxf.sts.token.provider.SAMLTokenProvider">
</bean>

The TokenIssueOperation also refers to a single StaticService implementation, which in turn defines a single URL expression to use to compare any received AppliesTo addresses:

<bean id="utService"
    class="org.apache.cxf.sts.service.StaticService">
    <property name="endpoints" ref="utEndpoints"/>
</bean>
<util:list id="utEndpoints">
    <value>http://localhost:(\d)*/(doubleit|metrowsp)/services/doubleit(UT|.*symmetric.*|.*)</value>
</util:list>

Finally, the TokenIssueOperation is configured with a StaticSTSProperties object. This class contains properties that define what private key to use to sign issued SAML tokens, as well as the Issuer name to use in the generated token.

<bean id="utSTSProperties"
    class="org.apache.cxf.sts.StaticSTSProperties">
    <property name="signaturePropertiesFile" value="stsKeystore.properties"/>
    <property name="signatureUsername" value="mystskey"/>
    <property name="callbackHandlerClass" value="..."/>
    <property name="issuer" value="DoubleItSTSIssuer"/>
    ...
</bean>

Tuesday, November 8, 2011

Apache CXF STS documentation - part VIII

Previous blog posts on the Apache CXF STS have focused on how tokens are provided, validated and canceled in the STS. These operations are (at least in theory) relatively independent of WS-Trust. For example, they could be used as an API to provide/validate/etc tokens. In the next couple of posts we will look at the bigger picture of how this internal token handling functionality works in the context of a client invocation. In this post we will cover some common functionality that is used by all of the WS-Trust operations in the STS implementation.

1) AbstractOperation

In the first post of this series of articles, the STS provider framework in Apache CXF was introduced. A number of interfaces were defined for each of the operations that can be invoked on the STS. Before looking at the implementations of these interfaces that ship with the STS, we will look a base class that all of the operations extend, namely the AbstractOperation class. This class defines a number of properties that are shared with any subclasses, and can be accessed via set/get methods:
  • STSPropertiesMBean stsProperties - A configuration MBean that holds the configuration for the STS as a whole, such as information about the private key to use to sign issued tokens, etc.
  • boolean encryptIssuedToken - Whether to encrypt an issued token or not. The default is false.
  • List<ServiceMBean> services - A list of ServiceMBean objects, which correspond to "known" services. This will be covered later.
  • List<TokenProvider> - A list of TokenProvider implementations to use to issue tokens.
  • boolean returnReferences - Whether to return SecurityTokenReference elements to the client or not, that point to the issued token. The default is true.
  • STSTokenStore tokenStore - A cache used to store/retrieve tokens.
Several of the properties refer to issuing tokens - this is because this functionality is shared between the issuing and validating operations. At least one TokenProvider implementation must be configured, if the STS is to support issuing a token. Some of these properties have been seen in previous posts, for example the STSTokenStore cache was covered in a previous blog post. This cache could be shared across a number of different operations, or else kept separate. AbstractOperation also contains some common functionality to parse requests, encrypt tokens, create references to return to the client, etc.

1.1) STSPropertiesMBean

The AbstractOperation object must be configured with an STSPropertiesMBean object. This is an interface that encapsulates some configuration common to a number of different operations of the STS:
  • void configureProperties() - load and process the properties
  • void setCallbackHandler(CallbackHandler callbackHandler) - Set a CallbackHandler object. This is used in the TokenProviders/TokenValidators to retrieve passwords for various purposes.
  • void setSignatureCrypto(Crypto signatureCrypto) - Set a WSS4J Crypto object to use to sign tokens, or validate signed requests, etc.
  • void setSignatureUsername(String signatureUsername) - Set the default signature username to use (e.g. corresponding to a keystore alias)
  • void setEncryptionCrypto(Crypto encryptionCrypto) - Set a WSS4J Crypto object to use to encrypt issued tokens.
  • void setEncryptionUsername(String encryptionUsername) - Set the default encryption username to use (e.g. corresponding to a keystore alias)
  • void setIssuer(String issuer) - Set the default issuer name of the STS
  • void setSignatureProperties(SignatureProperties signatureProperties) - Set the SignatureProperties object corresponding to the STS.
  • void setRealmParser(RealmParser realmParser) - Set the object used to define what realm a request is in. This will be covered later.
  • void setIdentityMapper(IdentityMapper identityMapper) - Set the object used to map identities across realms. This will be covered later.
The STS ships with a single implementation of the STSPropertiesMBean interface - StaticSTSProperties. This class has two additional methods:
  • void setSignaturePropertiesFile(String signaturePropertiesFile)
  • void setEncryptionPropertiesFile(String encryptionPropertiesFile)
If no Crypto objects are supplied to StaticSTSProperties, then it will try to locate a properties file using these values, and create a WSS4J Crypto object internally from the properties that are parsed.

1.2) SignatureProperties

A SignatureProperties object can be defined on the STSPropertiesMBean. Note that this is unrelated to the signaturePropertiesFile property of StaticSTSProperties. This class provides some configuration relating to the signing of an issued token, as well as symmetric key generation. It has the following properties:
  • boolean useKeyValue - Whether to use a KeyValue or not to refer to a certificate in a signature. The default is false.
  • long keySize - The (default) key size to use when generating a symmetric key. The default is 256 bits.
  • long minimumKeySize - The minimum key size to use when generating a symmetric key. The requestor can specify a KeySize value to use. The default is 128 bits. 
  • long maximumKeySize - The maximum key size to use when generating a symmetric key. The requestor can specify a KeySize value to use. The default is 512 bits.
For example, when the client sends a "KeySize" element to the STS when requesting a SAML Token (and sending a SymmetricKey KeyType URI), the SAMLTokenProvider will check that the requested keysize falls in between the minimum and maximum key sizes defined above. If it does not, then the default key size is used.

2) Request Parsing

The first thing any of the AbstractOperation implementations do on receiving a request is to call some functionality in AbstractOperation to parse the request. This parsing is done by the RequestParser object, which iterates through the objects of the JAXB RequestSecurityTokenType. The request is parsed into two components, TokenRequirements and KeyRequirements, which are available on the RequestParser object and are subsequently passed to the desired TokenProvider/TokenValidator/etc objects.

2.1) TokenRequirements

The TokenRequirements class holds a set of properties that have been extracted and parsed by RequestParser. These properties loosely relate to the token itself, rather than anything to do with keys. The properties that can be set by RequestParser are:
  • String tokenType - The desired TokenType URI. This is required if a token is to be issued.
  • Element appliesTo - The AppliesTo element that was received in the request. This normally holds a URL that indicates who the recipient of the issued token will be.
  • String context - The context attribute of the request.
  • ReceivedToken validateTarget - This object holds the contents of a received "ValidateTarget" element, i.e. a token to validate.
  • ReceivedToken onBehalfOf - This object holds the contents of a received "OnBehalfOf" element.
  • ReceivedToken actAs - This object holds the contents of a received "ActAs" element.
  • ReceivedToken cancelTarget - This object holds the contents of a received "CancelTarget" element, i.e. a token to cancel.
  • Lifetime lifetime - The requested lifetime of the issued token. This just holds created and expires Strings, that are parsed from the request.
  • RequestClaimCollection claims - A collection of requested claims that are parsed from the request. This will be covered later.
The ReceivedToken class mentioned above parses a received token object, which can be a JAXBElement<?> or a DOM Element. If it is a JAXBElement then it must be either a UsernameToken, SecurityTokenReference, or BinarySecurityToken. If it is a reference to a security token in the security header of the request, then this token is retrieved and set as the ReceivedToken instead.

2.2) KeyRequirements

The KeyRequirements class holds a set of properties that have been extracted and parsed by RequestParser. These properties are anything to do with key handling or creation. The properties that can be set by RequestParser are:
  • String authenticationType - An optional authentication type URI. This is currently not used in the STS.
  • String keyType - The desired KeyType URI.
  • long keySize - The requested KeySize to use when generating symmetric keys.
  • String signatureAlgorithm - The requested signature algorithm to use when signing an issued token. This is currently not used in the STS.
  • String encryptionAlgorithm - The requested encryption algorithm to use when encrypting an issued token.
  • String c14nAlgorithm - The requested canonicalization algorithm to use when signing an issued token. This is currently not used in the STS.
  • String computedKeyAlgorithm - The computed key algorithm to use when creating a symmetric key.
  • String keywrapAlgorithm - The requested KeyWrap algorithm to use when encrypting a symmetric key.
  • X509Certificate certificate - A certificate that has been extracted from a "UseKey" element, for use in the SAML case when a PublicKey KeyType URI is specified.
  • Entropy entropy - This object holds entropy information extracted from the client request for use in generating a symmetric key. Only BinarySecret elements are currently supported. 
2.3) SecondaryParameters

RequestParser also supports parsing a "SecondaryParameters" element that might be in the request. This could be extracted from the WSDL of a service provider that specifies an IssuedToken policy by the client and sent to the STS as part of the RequestSecurityToken request. Only KeySize, TokenType, KeyType and Claims child elements are currently parsed.

Monday, November 7, 2011

Apache CXF STS documentation - part VII

Previous blog entries have covered TokenProviders and TokenValidators, used by the STS to provide and validate tokens respectively. The STS does not currently have any support for renewing tokens - although this may change in the future. The other STS operation on tokens that is of interest is the ability to cancel tokens that were issued by the STS. In this post I will detail an interface used to cancel tokens, as well as an implementation that ships with the STS.

1) The TokenCanceller interface

SecurityTokens are cancelled in the STS via the TokenCanceller interface. This interface is very similar to the TokenProvider and TokenValidator interfaces. It contains three methods:
  • void setVerifyProofOfPossession(boolean verifyProofOfPossession) - Whether to enable or disable proof-of-possession verification.
  • boolean canHandleToken(ReceivedToken cancelTarget) - Whether this TokenCanceller implementation can cancel the given token
  • TokenCancellerResponse cancelToken(TokenCancellerParameters tokenParameters) - Cancel a token using the given parameters
A client can cancel a security token via the STS by invoking the "cancel" operation. Assuming that the client request is authenticated and well-formed, the STS will iterate through a list of TokenCanceller implementations to see if they can "handle" the received token. If they can, then the implementation is used to cancel the received security token, and the cancellation result is returned to the client. The STS currently ships with a single TokenCanceller implementation, which can cancel SecurityContextTokens that were issued by the STS. Before we look at this implementation, let's look at the "cancelToken" operation in more detail. This method takes a TokenCancellerParameters instance, and returns a TokenCancellerResponse object.

2) TokenCancellerParameters and TokenCancellerResponse

The TokenCancellerParameters class is nothing more than a collection of configuration properties to use in cancelling the token, which are populated by the STS operations using information collated from the request, or static configuration, etc. The properties of the TokenCancellerParameters are:
  • STSPropertiesMBean stsProperties - A configuration MBean that holds the configuration for the STS as a whole.
  • Principal principal - The current client Principal object
  • WebServiceContext webServiceContext - The current web service context object. This allows access to the client request.
  • KeyRequirements keyRequirements - A set of configuration properties relating to keys. This will be covered later.
  • TokenRequirements tokenRequirements - A set of configuration properties relating to the token. This will be covered later.
  • STSTokenStore tokenStore - A cache used to retrieve tokens.
The "cancelToken" method returns an object of type TokenCancellerResponse. Similar to the TokenCancellerParameters object, this just holds a collection of objects that is parsed by the STS operation to construct a response to the client. It currently only has a single property:
  • boolean tokenCancelled - Whether the token was cancelled or not.
3) The SCTCanceller

The STS ships with a single implementation of the TokenCanceller interface, namely the SCTCanceller. The SCTCanceller is used to cancel a token known as a SecurityContextToken, that is defined in the WS-SecureConversation specification. The SCTProvider and the SCTValidator were covered previously. A SecurityContextToken essentially consists of a String Identifier which is associated with a particular secret key. The SCTCanceller can cancel a SecurityContextToken in either of the following namespaces:
  • http://schemas.xmlsoap.org/ws/2005/02/sc/sct
  • http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512
Recall that the SCTValidator validates a received SecurityContextToken by checking to see whether it is stored in the cache. Therefore it is a requirement to configure a cache for the STS if you want to validate SecurityContextTokens. The same applies for the SCTCanceller. A received SecurityContextToken is successfully cancelled only if it is stored in the cache and is removed from the cache without any errors. This generally implies that the STS must have previously issued the SecurityContextToken and stored it in the cache, unless the STS is sharing a distributed cache with other STS instances.

3.1) Enforcing proof-of-possession

Recall that the TokenCanceller interface has a method "setVerifyProofOfPossession" which defines whether proof-of-possession is required or not to cancel a security token. The default value for the SCTCanceller is "true". This means that for the client to successfully cancel a SecurityContextToken it must prove to the STS that it knows the secret key associated with that SecurityContextToken. The client must do this by signing some portion of the request with the same secret key that the SCTCanceller retrieves from the security token stored in the cache.

Friday, November 4, 2011

Apache CXF STS documentation - part VI

In the previous post, I covered the TokenValidator interface that is used by the CXF STS to validate tokens, and two implementations that ship with the STS to validate SecurityContextTokens and BinarySecurityTokens (X509 Certificates). In this post I will cover the other two TokenValidator implementations that ship with the STS, which can validate UsernameTokens and SAML Tokens (both 1.1 and 2.0).

1) The UsernameTokenValidator

The UsernameTokenValidator is used to validate WS-Security UsernameTokens. Two properties can be set directly on the UsernameTokenValidator:
  • void setValidator(Validator validator) - Set the WSS4J Validator instance to use to validate the received UsernameToken. The default is the UsernameTokenValidator (note that this is in WSS4J and not the same as the UsernameTokenValidator in the STS!).
  • void setUsernameTokenRealmCodec(UsernameTokenRealmCodec usernameTokenRealmCodec) - Set the UsernameTokenRealmCodec instance to use to return a realm from a validated token. This will be explained later.
The UsernameToken is first checked to make sure that it is well-formed. If it has no password element then it is rejected. If a cache is configured, then it sees if the UsernameToken has been previously stored in the cache (searching by wsu:Id). If it is, and if the retrieved SecurityToken has an "associated hash" corresponding to the hashcode of the received UsernameToken, then the received UsernameToken has already been validated, and no further validation is required. It is necessary to check the "associated hash" value, in case two different UsernameTokens are being compared that have the same wsu:Id. Note that the CXF STS does not have a UsernameTokenProvider as of yet, so for this use-case perhaps the cache is shared with a custom TokenProvider.

If the token is not stored in the cache, then the WSS4J Validator instance is used to validate the received UsernameToken. As stated above, the default implementation that is used is the UsernameTokenValidator in WSS4J. This implementation uses a CallbackHandler to supply a password to validate the UsernameToken. This CallbackHandler implementation is supplied by the STSPropertiesMBean object. WSS4J also ships with an implementation that validates a UsernameToken via a JAAS LoginModule, which can be plugged in to the STS UsernameTokenValidator. If validation is successful, then a principal is created from the received UsernameToken and set on the response.

2) Realms in the TokenValidators

Recall that the TokenValidator interface has a method that takes a realm parameter:
  • boolean canHandleToken(ReceivedToken validateTarget, String realm) - Whether this TokenValidator implementation can validate the given token in the given realm
How the STS knows what the desired realm is will be covered in a future post.  
Realms are handled in a slightly different way in TokenValidators compared to TokenProviders. Recall that for TokenProviders, the implementation is essentially asked whether it can provide a token in a given realm. For the SCTProvider, the realm is ignored in this method. However, when creating a token, the SCTProvider will store the given realm as a property associated with that token in the cache. The SAMLTokenProvider checks to see if the given realm is null, and if it is not null then the realmMap *must* contain a key which matches the given realm.

There is a subtle distinction between the realm passed to "canHandleToken" for TokenValidators and the realm returned after a token is validated as part of the TokenValidatorResponse object. The realm passed to "canHandleToken" is the realm to validate the token in. So for example, you could have two TokenValidator instances registered to validate the same token, but in different realms. All of the TokenValidator implementations that ship with the STS ignore the realm as part of this method. However, the method signature gives the user the option to validate tokens in different realms in a more flexible manner.

The realm that is returned as part of the TokenValidatorResponse is the realm that the validated token is in (if any). This can be different to the realm the token was validated in. The X509TokenValidator ignores this parameter altogether. The SCTValidator checks to see whether the SecurityToken that was stored in the cache has a realm property, and if so sets this on the TokenValidatorResonse. The UsernameTokenValidator and SAMLTokenValidator handle realms in a more sophisticated manner. I will cover the UsernameTokenValidator here, and the SAMLTokenValidator later. Recall that the UsernameTokenValidator has the following method:
  • void setUsernameTokenRealmCodec(UsernameTokenRealmCodec usernameTokenRealmCodec) - Set the UsernameTokenRealmCodec instance to use to return a realm from a validated token. 
The UsernameTokenRealmCodec has a single method:
  • String getRealmFromToken(UsernameToken usernameToken) - Get the realm associated with the UsernameToken parameter.
No UsernameTokenRealmCodec implementation is set by default on the UsernameTokenValidator, hence no realm is returned in TokenValidatorResponse. If an implemention is specified, then the UsernameTokenValidator will retrieve a realm from the UsernameTokenRealmCodec implementation corresponding to the validated UsernameToken. If a cache is configured, and the UsernameToken was already stored in the cache, then the realm is compared to the realm of the cached token, stored under the tag "org.apache.cxf.sts.token.realm". If they do not match then validation fails.

3) The SAMLTokenValidator

The SAMLTokenValidator is used to validate SAML (1.1 and 2.0) tokens. The following properties can be set directly on the SAMLTokenValidator:
  • void setValidator(Validator validator) - Set the WSS4J Validator instance to use to validate the received certificate. The default is SignatureTrustValidator.
  • void setSamlRealmCodec(SAMLRealmCodec samlRealmCodec) - Set the SAMLRealmCodec instance to use to return a realm from a validated token.
  • void setSubjectConstraints(List<String> subjectConstraints) - Set a list of Strings corresponding to regular expression constraints on the subject DN of a certificate that was used to sign an Assertion.
These methods are covered in more detail below. The Assertion is first checked to make sure that it is well-formed. If a cache is defined, then the signature value of the received assertion (if it is signed) is hashed and compared against the tokens in the cache (via getTokenByAssociatedHash()). If a match is found in the cache, then the Assertion is taken to be valid. If a match is not found, then the Assertion is validated.
3.1) Validating a received SAML Assertion

If the token is not stored in the cache then it must be validated. Firstly a check is performed to make sure that the Assertion is signed, if it is not then it is rejected. The signature of the Assertion is then validated using the Crypto object retrieved from the STSPropertiesMBean passed in the TokenValidatorParameters. Finally, trust is verified in the certificate/public-key used to sign the Assertion. This is done using the Validator object that can be configured via "setValidator". The default Validator is the WSS4J SignatureTrustValidator, which checks that the received certificate is known (or trusted) by the STS Crypto object.

Recall that a List of Strings can be set on the SAMLTokenValidator via the "setSubjectConstraints" method. These Strings correspond to regular expression constraints on the subject DN of a certificate that was used to sign an Assertion. This provides additional flexibility to validate a received SAML Assertion. For example, the Assertion could be signed by an entity that has a certificate issued by a particular CA, which in turn is trusted by the STS Crypto object. However, one might want to restrict the list of "valid" entities who can sign a SAML Assertion. This can be done by adding a list of regular expressions that match the Subject DN of all acceptable certificates that might be used to sign a valid SAML Assertion. This matching is done by the CertConstraintsParser.

3.2) Realm handling in the SAMLTokenValidator

Recall that the SAMLTokenValidator has the following method:
  • void setSamlRealmCodec(SAMLRealmCodec samlRealmCodec) - Set the SAMLRealmCodec instance to use to return a realm from a validated token.
The SAMLRealmCodec has a single method:
  • String getRealmFromToken(AssertionWrapper assertion) - Get the realm associated with the (SAML Assertion) parameter.
No SAMLRealmCodec implementation is set by default on the SAMLTokenValidator, hence no realm is returned in TokenValidatorResponse. If an implemention is specified, then the SAMLTokenValidator will retrieve a realm from theSAMLRealmCodec  implementation corresponding to the validated Assertion. If a cache is configured, and the Assertion was already stored in the cache, then the realm is compared to the realm of the cached token, stored under the tag "org.apache.cxf.sts.token.realm". If they do not match then validation fails.

Wednesday, November 2, 2011

Apache CXF STS documentation - part V

In the previous couple of posts (here and here) I detailed the TokenProvider interface, which is used to generate tokens in the STS, as well as two implementations that ship with the STS to generate SecurityContextTokens and SAML Tokens. In this post I will describe the interface that is used for validating tokens, as well as two implementations that ship with the STS, which are used to validate SecurityContextTokens, and (X.509) BinarySecurityTokens. In the next post, I will detail implementations which can validate a UsernameToken and a SAML Token. 

1) The TokenValidator interface

SecurityTokens are validated in the STS via the TokenValidator interface. It is very similar to the TokenProvider interface (hence some duplication of documentation from previous blog entries on the TokenProvider). It has three methods:
  • boolean canHandleToken(ReceivedToken validateTarget) - Whether this TokenValidator implementation can validate the given token
  • boolean canHandleToken(ReceivedToken validateTarget, String realm) - Whether this TokenValidator implementation can validate the given token in the given realm
  • TokenValidatorResponse validateToken(TokenValidatorParameters tokenParameters) - Validate a token using the given parameters.
A client can validate a security token via the STS by invoking the "validate" operation. Assuming that the client request is authenticated and well-formed, the STS will iterate through a list of TokenValidator implementations to see if they can "handle" the received token. If they can, then the implementation is used to validate the received security token, and the validation result is returned to the client. The second "canHandleToken" method which also takes a "realm" parameter will be covered in a future post.

So to support the validation of a particular token type in an STS deployment, it is necessary to specify a TokenValidator implementation that can handle that token. The STS currently ships with four TokenValidator  implementations, to validate SecurityContextTokens, SAML Assertions, UsernameTokens, and BinarySecurityTokens. Before we look at these implementations, let's take a look at the "validateToken" operation in more detail. This method takes a TokenValidatorParameters instance.

2) TokenValidatorParameters

The TokenValidatorParameters class is nothing more than a collection of configuration properties to use in validating the token, which are populated by the STS operations using information collated from the request, or static configuration, etc. The properties of the TokenValidatorParameters are:
  • STSPropertiesMBean stsProperties - A configuration MBean that holds the configuration for the STS as a whole.
  • Principal principal - The current client Principal object
  • WebServiceContext webServiceContext - The current web service context object. This allows access to the client request.
  • KeyRequirements keyRequirements - A set of configuration properties relating to keys. This will be covered later.
  • TokenRequirements tokenRequirements - A set of configuration properties relating to the token. This will be covered later.
  • STSTokenStore tokenStore - A cache used to retrieve tokens.
  • String realm - The realm to validate the token in (this should be the same as the realm passed to "canHandleToken"). This will be covered later.
If this looks complicated then remember that the STS will take care of populating all of these properties from the request and some additional configuration. You only need to worry about the TokenValidatorParameters object if you are creating your own TokenValidator implementation.

3) TokenValidatorResponse

The "validateToken" method returns an object of type TokenValidatorResponse. Similar to the TokenValidatorParameters object, this just holds a collection of objects that is parsed by the STS operation to construct a response to the client. The properties are:
  • boolean valid - Whether the token is valid or not.
  • Principal principal - A principal corresponding to the validated token.
  • Map<String, Object> additionalProperties - Any additional properties associated with the validated token.
  • String realm - The realm of the validated token.
4) The SCTValidator

Now that we've covered the TokenValidator interface, let's look at an implementation that is shipped with the STS. The SCTValidator is used to validate a token known as a SecurityContextToken, that is defined in the WS-SecureConversation specification. The SCTProvider was covered in a previous post. A SecurityContextToken essentially consists of a String Identifier which is associated with a particular secret key. If a service provider receives a SOAP message with a digital signature which refers to a SecurityContextToken in the KeyInfo of the signature, then the service provider knows that it must somehow obtain a secret key associated with that particular Identifier to verify the signature.

One way to do this would be if the service provider shares a (secured) distributed cache with an STS instance. An alternative solution would be for the service provider to send the SCT to an STS for validation, and to receive a SAML token in response with the embedded (encrypted) secret key. The SCTValidator can accommodate this latter scenario, albeit indirectly as will be explained shortly.

The SCTValidator can validate a SecurityContextToken in either of the following namespaces:
  • http://schemas.xmlsoap.org/ws/2005/02/sc/sct
  • http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512
The SCTValidator validates a received SecurityContextToken by checking to see whether it is stored in the cache. Therefore it is a requirement to configure a cache for the STS if you want to validate SecurityContextTokens. If the SecurityContextToken is stored in the cache (for example, by the SCTProvider), then the received SecurityToken is taken to be valid. The secret associated with the SecurityContextToken is also retrieved from the cache, and set as an "additional property" in the TokenValidatorResponse using the key "sct-validator-secret". If the cached token has a stored principal, then this is also returned in the TokenValidatorResponse.

If you want to support the scenario of returning the secret key associated with the SecurityContextToken to the client (of the STS), then it is possible to do so via token transformation. This is where the client sends an additional Token Type (in this case for a SAML Token). After the token is validated, the SAMLTokenProvider is called with the additional properties map obtained from the SCTValidator. The SAMLTokenProvider then has access to the secret key via the "sct-validator-secret" tag, which it can insert into the Assertion using a custom AttributeProvider. Token Transformation will be covered in more detail in a future post.

5) The X509TokenValidator

Another TokenValidator implementation that ships with the STS is the X509TokenValidator. This class validates an X.509 V.3 certificate (received as a BinarySecurityToken). The BinarySecurityToken must use Base-64 encoding.
The received cert must be known (or trusted) by the STS crypto object, that is set on the STSPropertiesMBean object. The X509TokenValidator has a single property that can be configured:
  • void setValidator(Validator validator) - Set the WSS4J Validator instance to use to validate the received certificate. The default is SignatureTrustValidator.
No proof-of-possession is done with the received certificate. The subject principal of the certificate is set on the response, if validation is successful. Note that no caching is used in this TokenValidator implementation.


New Apache Santuario and CXF releases

Apache Santuario 1.4.6 has been released - it is available for download here. This release fixes a thread safety issue with XML Signature, a bug fix for the Canonical XML 1.1 algorithm, as well as a number of other bug fixes. See the release notes for more information.

Also, Apache CXF 2.5.0 has been released. This release features a brand new STS implementation - something I have been blogging extensively about. See Dan Kulp's blog for more thoughts on this release.