Colm O hEigeartaigh

Subscribe to Colm O hEigeartaigh feed
Colm O hEigeartaighhttp://www.blogger.com/profile/10711987281965801793noreply@blogger.comBlogger249125
Updated: 2 hours 36 min ago

Apache CXF STS documentation - part VIII

Tue, 11/08/2011 - 18:29
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.

Categories: Colm O hEigeartaigh

Apache CXF STS documentation - part VII

Mon, 11/07/2011 - 18:00
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.
Categories: Colm O hEigeartaigh

Apache CXF STS documentation - part VI

Fri, 11/04/2011 - 17:45
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.

    Categories: Colm O hEigeartaigh

    Apache CXF STS documentation - part V

    Wed, 11/02/2011 - 17:38
    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:
    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.

    Categories: Colm O hEigeartaigh

    New Apache Santuario and CXF releases

    Wed, 11/02/2011 - 17:15
    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.
    Categories: Colm O hEigeartaigh

    Apache CXF STS documentation - part IV

    Thu, 10/27/2011 - 13:45
    In the previous post I covered the TokenProvider interface, which is used to generate tokens in the STS, and an implementation that ships with the STS to generate SecurityContextTokens. In this post, I will cover the other TokenProvider implementation that ships with the STS, which issues SAML Tokens (both 1.1 and 2.0).

    1) The SAMLTokenProvider

    The SAMLTokenProvider can issue SAML 1.1 and SAML 2.0 tokens. To request a SAML 1.1 token, the client must use one of the following Token Types:
    • http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1
    • urn:oasis:names:tc:SAML:1.0:assertion
    To request a SAML 2.0 token, the client must use one of the following Token Types:
    • http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0
    • urn:oasis:names:tc:SAML:2.0:assertion
    The following properties can be configured on the SAMLTokenProvider directly:
    • List<AttributeStatementProvider> attributeStatementProviders - A list of objects that can add attribute statements to the token.
    • List<AuthenticationStatementProvider> authenticationStatementProviders - A list of objects that can add authentication statements to the token.
    • List<AuthDecisionStatementProvider> authDecisionStatementProviders - A list of objects that can add authorization decision statements to the token.
    • SubjectProvider subjectProvider - An object used to add a Subject to the token.
    • ConditionsProvider conditionsProvider - An object used to add a Conditions statement to the token.
    • boolean signToken - Whether to sign the token or not. The default is true.
    • Map<String, SAMLRealm> realmMap - A map of realms to SAMLRealm objects.
    We will explain each of these properties in more detail in the next few sections.

    2) Realms in the TokenProviders

    As explained in the previous post, the TokenProvider interface has a method that takes a realm parameter:
    • boolean canHandleToken(String tokenType, String realm) - Whether this TokenProvider implementation can provide a token of the given type, in the given realm
    In other words, the TokenProvider implementation is being asked whether it can supply a token corresponding to the Token Type in a particular realm. How the STS knows what the desired realm is will be covered in a future post. However, we will explain how the realm is handled by the TokenProviders here. The SCTProvider ignores the realm in the canHandleToken method. In other words, the SCTProvider can issue a SecurityContextToken in *any* realm. If a realm is passed through via the TokenProviderParameters when creating the token, the SCTProvider will cache the token with the associated realm as a property (this was explained in the previous post).

    Unlike the SCTProvider, the SAMLTokenProvider does not ignore the realm parameter to the "canHandleToken" method. Recall that the SAMLTokenProvider has a property "Map<String, SAMLRealm> realmMap". The canHandleToken method 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. So if the STS implementation is designed to issue tokens in different realms, then the realmMap of the SAMLTokenProvider must contain the corresponding realms in the key-set of the map.

    The realmMap property maps realm Strings to SAMLRealm objects. The SAMLRealm class contains the following properties:
    • String issuer - the Issuer String to use in this realm
    • String signatureAlias - the keystore alias to use to retrieve the private key the SAMLTokenProvider uses to sign the generated token
    In other words, if the SAMLTokenProvider is "realm aware", then it can issue tokens with an issuer name and signing key specific to a given realm. If no realm is passed to the SAMLTokenProvider, then these properties are obtained from the "system wide" properties defined in the STSPropertiesMBean object passed as part of the TokenProviderParameters, which can be set via the following methods:
    • void setSignatureUsername(String signatureUsername)
    • void setIssuer(String issuer)
    Two additional properties are required when signing SAML Tokens. A password is required to access the private key in the keystore, which is supplied by a CallbackHandler instance. A WSS4J "Crypto" instance is also required which controls access to the keystore. These are both set on the STSPropertiesMBean object via:
    • void setCallbackHandler(CallbackHandler callbackHandler)
    • void setSignatureCrypto(Crypto signatureCrypto)
    Note that the signature of generated SAML Tokens can be disabled, by setting the "signToken" property of the SAMLTokenProvider to "false". As per the SCTProvider, the generated SAML tokens are stored in the cache with the associated realm stored as a property.

    3) Populating SAML Tokens

    In the previous section we covered how a generated SAML token is signed, how to configure the key used to sign the assertion, and how to set the Issuer of the Assertion. In this section we will describe how to populate the SAML Token itself. The SAMLTokenProvider is designed to be able to issue a wide range of SAML Tokens. It does this by re-using the SAML abstraction library that ships with Apache WSS4J, which defines a collection of beans that are configured and then assembled in a CallbackHandler to create a SAML assertion.

    3.1) Configure a Conditions statement

    The SAMLTokenProvider has a "ConditionsProvider conditionsProvider" property, which can be used to configure the generated Conditions statement which is added to the SAML Assertion. The ConditionsProvider has a method to return a ConditionsBean object, and a method to return a lifetime in seconds. The ConditionsBean holds properties such as the not-before and not-after dates, etc. The SAMLTokenProvider ships with a default ConditionsProvider implementation that is used to insert a Conditions statement in every SAML token that is generated. This implementation uses a default lifetime of 5 minutes, and set the Audience Restriction URI of the Conditions Statement to be the received "AppliesTo" address, which is obtained from the TokenProviderParameters object.

    The DefaultConditionsProvider can be configured to change the lifetime of the issued token. If you want to remove the ConditionsProvider altogether from the generation assertion, or implement a custom Conditions statement, then you must implement an instance of the ConditionsProvider interface, and set it on the SAMLTokenProvider.

    3.2) Configure a Subject

    The SAMLTokenProvider has a "SubjectProvider subjectProvider" property, which can be used to configure the Subject of the generated token, regardless of the version of the token. The SubjectProvider interface defines a single method to return a SubjectBean, given the token provider parameters, the parent Document of the assertion, and a secret key to use (if any). The SubjectBean contains the Subject name, name-qualifier, confirmation method, and KeyInfo element, amongst other properties. The SAMLTokenProvider ships with a default SubjectProvider implementation that is used to insert a Subject into every SAML Token that is generated.

    The DefaultSubjectProvider has a single configuration method to set the subject name qualifier. It creates a subject confirmation method by checking the received key type. The subject name is the name of the principal obtained from TokenProviderParameters. Finally, a KeyInfo element is set on the SubjectBean under the following conditions:
    • If a "SymmetricKey" Key Type algorithm is specified by the client, then the secret key passed through to the SubjectProvider is encrypted with the X509Certificate of the recipient, and added to the KeyInfo element. How the provider knows the public key of the recipient will be covered later.
    • If a "PublicKey" KeyType algorithm is specified by the client, the X509Certificate that is received as part of the "UseKey" request is inserted into the KeyInfo element of the Subject.
    If a "Bearer" KeyType algorithm is specified by the client, then no KeyInfo element is added to the Subject. For the "SymmetricKey" Key Type case, the SAMLTokenProvider creates a secret key using a SymmetricKeyHandler instance. The SymmetricKeyHandler first checks the key size that is supplied as part of the KeyRequirements object, by checking that it fits in between a minimum and maximum key size that can be configured. It also checks any client entropy that is supplied, as well as the computed key algorithm. It then creates some entropy and a secret key.

    To add a custom Subject element to an assertion, you must create your own SubjectProvider implementation, and set it on the SAMLTokenProvider.

    3.3) Adding Attribute Statements

    The SAMLTokenProvider has a "List<AttributeStatementProvider> attributeStatementProviders" property, which can be used to add AttributeStatments to the generated assertion. Each object in the list adds a single Attribute statement. The AttributeStatementProvider contains a single method to return an AttributeStatementBean given the TokenProviderParameters object. This contains a SubjectBean (for SAML 1.1 assertions), and a list of AttributeBeans. The AttributeBean object holds the attribute name/qualified-name/name-format, and a list of attribute values, amongst other properties.

    If no statement provider is configured in the SAMLTokenProvider, then the DefaultAttributeStatementProvider is invoked to create an Attribute statement to add to the assertion. It creates a default "authenticated" attribute, and also creates separate Attributes for any "OnBehalfOf" or "ActAs" elements that were received in the request. If the received OnBehalfOf/ActAs element was a UsernameToken, then the username is added as an Attribute. If the received element was a SAML Assertion, then the subject name is added as an Attribute. 

    3.4) Adding Authentication Statements

    The SAMLTokenProvider has a "List<AuthenticationStatementProvider> authenticationStatementProviders" property, which can be used to add AuthenticationStatements to the generated assertion. Each object in the list adds a single Authentication statement. The AuthenticationStatementProvider contains a single method to return an AuthenticationStatementBean given the TokenProviderParameters object. This contains a SubjectBean (for SAML 1.1 assertions), an authentication instant, authentication method, and other properties. No default implementation of the AuthenticationStatementProvider interface is provided in the STS, so if you want to issue Authentication Statements you will have to write your own.

    3.5) Adding Authorization Decision Statements

    The SAMLTokenProvider has a "List<AuthDecisionStatementProvider> authDecisionStatementProviders" property, which can be used to add AuthzDecisionStatements to the generated assertion. Each object in the list adds a single statement. The AuthDecisionStatementProvider  contains a single method to return an AuthDecisionStatementBean given the TokenProviderParameters object. This contains a SubjectBean (for SAML 1.1 assertions), the decision (permit/indeterminate/deny), the resource URI, a list of ActionBeans, amongst other properties. No default implementation of the AuthDecisionStatementProvider interface is provided in the STS.

    Note that for SAML 1.1 tokens, the Subject is embedded in one of the Statements. When creating a SAML 1.1 Assertion, if a given Authentication/Attribute/AuthzDecision statement does not have a subject, then the standalone Subject is inserted into the statement. Finally, once a SAML token has been created, it is stored in the cache (if one is configured), with a lifetime corresponding to that of the Conditions statement. A TokenProviderResponse object is created with the DOM representation of the SAML Token, the SAML Token ID, lifetime, entropy bytes, references, etc.
      Categories: Colm O hEigeartaigh

      Apache CXF STS documentation - part III

      Tue, 10/25/2011 - 18:08
      In the next couple of blog posts I will describe how to generate tokens in the new STS implementation shipped as part of Apache CXF 2.5. In this post I will detail the interface that is used for generating tokens, as well as an implementation to generate SecurityContextTokens that ships with the STS. In the next post, I will describe how to generate SAML tokens.

      1) The TokenProvider interface

      Security tokens are created in the STS via the TokenProvider interface. It has three methods:
      • boolean canHandleToken(String tokenType) - Whether this TokenProvider implementation can provide a token of the given type
      • boolean canHandleToken(String tokenType, String realm) - Whether this TokenProvider implementation can provide a token of the given type, in the given realm
      • TokenProviderResponse createToken(TokenProviderParameters tokenParameters) - Create a token using the given parameters
      A client can request a security token from the STS by either invoking the "issue" operation and supplying a desired token type, or else calling the "validate" operation and passing a (different) token type (token transformation). Assuming that the client request is authenticated and well-formed, the STS will iterate through a list of TokenProvider implementations to see if they can "handle" the received token type. If they can, then the implementation is used to create a security token, which 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 issuing of a particular token type in an STS deployment, it is necessary to specify a TokenProvider implementation that can handle that token type. The STS currently ships with two TokenProvider implementations, one for generating SecurityContextTokens, and one for generating SAML Assertions. Before we look at these two implementations, let's take a look at the "createToken" operation in more detail. This method takes a TokenProviderParameters instance.

      2) TokenProviderParameters

      The TokenProviderParameters class is nothing more than a collection of configuration properties to use in creating the token, which are populated by the STS operations using information collated from the request, or static configuration, etc. The properties of the TokenProviderParameters are:
      • 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. This will be covered later.
      • EncryptionProperties encryptionProperties - A properties object that holds encryption information relevant to the intended recipient of the token. This will be covered later.
      • Principal principal - The current client Principal object. This can be used as the "subject" of the generated token.
      • WebServiceContext webServiceContext - The current web service context object. This allows access to the client request.
      • RequestClaimCollection requestedClaims - The requested claims in the token. This will be covered later.
      • 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.
      • String appliesToAddress - The URL that corresponds to the intended recipient of the token
      • ClaimsManager claimsManager - An object that can manage claims. This will be covered later.
      • Map<String, Object> additionalProperties - Any additional (custom) properties that might be used by a TokenProvider implementation.
      • STSTokenStore tokenStore - A cache used to store tokens.
      • String realm - The realm to create 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 TokenProviderParameters object if you are creating your own TokenProvider implementation.

      3) TokenProviderResponse

      The "createToken" method returns an object of type TokenProviderResponse. Similar to the TokenProviderParameters 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:
      • Element token - The (DOM) token that was created by the TokenProvider.
      • String tokenId - The ID of the token
      • long lifetime - The lifetime of the token
      • byte[] entropy - Any entropy associated with the token
      • long keySize - The key size of a secret key associated with the token.
      • boolean computedKey - Whether a computed key algorithm was used in generating a secret key.
      • TokenReference attachedReference - An object which gives information how to refer to the token when it is "attached".
      • TokenReference unAttachedReference" - An object which gives information how to refer to the token when it is "unattached".
      Most of these properties are optional as far as the STS operation is concerned, apart from the token and token ID. The TokenReference object contains information about how to refer to the token (direct reference vs. Key Identifier, etc.), that is used by the STS to generate the appropriate reference to return to the client. 

      4) The SCTProvider

      Now that we've covered the TokenProvider interface, let's look at an implementation that is shipped with the STS. The SCTProvider is used to provide a token known as a SecurityContextToken, that is defined in the WS-SecureConversation specification. 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. How this is done is "out of band" (more on this later).

      To request a SecurityContextToken, the client must use one of the following Token Types:
      • http://schemas.xmlsoap.org/ws/2005/02/sc/sct
      • http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512
      Two properties can be configured on the SCTProvider directly:
      • long lifetime - The lifetime of the generated SCT. The default is 5 minutes.
      • boolean returnEntropy - Whether to return any entropy bytes to the client or not. The default is true.
      The SCTProvider generates a secret key using the KeyRequirements object that was supplied, and constructs a SecurityContextToken with a random Identifier. It creates a CXF SecurityToken object that wraps this information, and stores it in the supplied cache using the given lifetime. The SecurityContextToken element is then returned, along with the appropriate references, lifetime element, entropy, etc.

      When requesting a token from an STS, the client will typically present some entropy along with a computed key algorithm. The STS will generate some entropy of its own, and combine it with the client entropy using the computed key algorithm to generate the secret key. Alternatively, the client will present no entropy, and the STS will supply all of the entropy. Any entropy the STS generates is then returned to the client, who can recreate the secret key using its own entropy, the STS entropy, and the computed key algorithm.

      This secret key is then used for the SCT use-case to encrypt/sign some part of a message. The SecurityContextToken is placed in the security header of the message, and referred to in the KeyInfo element of the signed/encrypted structure. As noted earlier, the service provider must obtain somehow the secret key corresponding to the SecurityContextToken identifier. Perhaps the service provider shares a (secured) distributed cache with an STS instance. Or perhaps the service provider sends the SCT to an STS instance to "validate" it, and receives a SAML token in response with the embedded (encrypted) secret key.

      5) Token caching in the TokenProvider

      Finally, we will cover token caching in a TokenProvider implementation. The SCTProvider is essentially useless without a cache, as otherwise there is no way for a third-party to know the secret key corresponding to a SecurityContextToken. Any TokenProvider implementation can cache a generated token in the STSTokenStore object supplied as part of the TokenProviderParameters. This object simply wraps the TokenStore interface in the CXF WS-Security runtime, which itself contains basic methods for adding/removing/querying CXF SecurityToken objects.

      The SCTProvider creates a SecurityToken with the ID of the SCT, the secret key associated with the SCT and the client principal. If a "realm" is passed through, then this is recorded as a property of the SecurityToken (keyed via STSConstants.TOKEN_REALM). Finally, the STS ships with two STSTokenStore implementations, an in-memory implementation based on eh-cache, and an implementation that uses Hazelcast.

        Categories: Colm O hEigeartaigh

        Apache CXF STS documentation - part II

        Fri, 10/21/2011 - 18:22
        In part I of the series of posts on the new Apache CXF STS implementation, I talked about what a Security Token Service can do, as well as the STS provider framework in CXF since the 2.4.0 release. In this part, I will leave the STS implementation to one side for the moment, and instead focus on how a client interacts with the STS in CXF.

        A simple example of how a CXF client can obtain a security token from the STS is shown in the "basic" STS system test "IssueUnitTest". This test starts an instance of the new CXF STS and obtains a number of different security tokens, all done completely programmatically, i.e. with no spring configuration. The STS instance that is used for the test-cases is configured with a number of different endpoints that use different security bindings (defined in the wsdl of the STS). For the purposes of this test, the Transport binding is used:

        <wsp:Policy wsu:Id="Transport_policy">
              <wsp:ExactlyOne>
                 <wsp:All>
                    <sp:TransportBinding
                       xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
                       <wsp:Policy>
                          <sp:TransportToken>
                             <wsp:Policy>
                                <sp:HttpsToken RequireClientCertificate="false"/>
                             </wsp:Policy>
                          </sp:TransportToken>
                          <sp:AlgorithmSuite>
                             <wsp:Policy>
                                <sp:Basic128 />
                             </wsp:Policy>
                          </sp:AlgorithmSuite>
                          <sp:Layout>
                             <wsp:Policy>
                                <sp:Lax />
                             </wsp:Policy>
                          </sp:Layout>
                          <sp:IncludeTimestamp />
                       </wsp:Policy>
                    </sp:TransportBinding>
                    <sp:SignedSupportingTokens
                       xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
                       <wsp:Policy>
                          <sp:UsernameToken
                             sp:IncludeToken=".../AlwaysToRecipient">
                             <wsp:Policy>
                                <sp:WssUsernameToken10 />
                             </wsp:Policy>
                          </sp:UsernameToken>
                       </wsp:Policy>
                    </sp:SignedSupportingTokens>
                    ...
                 </wsp:All>
              </wsp:ExactlyOne>
           </wsp:Policy>

        In other words, this security policy requires that a one-way TLS connection must be used to communicate with the STS, and that authentication is performed via a Username Token in the SOAP header.

        The object that communicates with an STS in CXF is the STSClient. Typically, the user constructs an STSClient instance (normally via Spring), sets it with certain properties such as the WSDL location of the STS, what service/port to use, various crypto properties, etc, and then stores this object on the message context using the SecurityConstants tag "ws-security.sts.client". This object is then controlled by the IssuedTokenInterceptorProvider in the ws-security runtime in CXF. This interceptor provider is triggered by the "IssuedToken" policy assertion, which is typically in the WSDL of the service provider. This policy assertion informs the client that it must obtain a particular security token from an STS and include it in the service request. The IssuedTokenInterceptorProvider takes care of using the STSClient to get a Security Token from the STS, and handles how long the security token should be cached, etc.

        An example of a simple IssuedToken policy that might appear in the WSDL of a service provider is as follows:

        <sp:IssuedToken sp:IncludeToken=".../AlwaysToRecipient">
            <sp:RequestSecurityTokenTemplate>
                <t:TokenType>
                    http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0
                </t:TokenType>
                <t:KeyType>
                    http://docs.oasis-open.org/ws-sx/ws-trust/200512/Bearer
                </t:KeyType>
            </sp:RequestSecurityTokenTemplate>
            ...
        </sp:IssuedToken>

        This policy states that the client should include a SAML 2.0 Assertion of subject confirmation method "Bearer" in the request. The client must know how to communicate with an STS to obtain such a token. This is done by providing the STSClient object with the appropriate information.

        We will come back to the IssuedTokenInterceptorProvider at a later date. The IssueUnitTest referred to above uses the STSClient programmatically to obtain a security token. Let's look at the "requestSecurityToken" method called by the tests. An STSClient is instantiated via the CXF bus, and the WSDL location of the STS, plus service and port names are configured:

        STSClient stsClient = new STSClient(bus);
        stsClient.setWsdlLocation("https://.../SecurityTokenService/Transport?wsdl");
        stsClient.setServiceName("{...}SecurityTokenService");
        stsClient.setEndpointName("{...}Transport_Port");

        A map is then populated with various properties and set on the STSClient. It is keyed with a different number of SecurityConstants tags. A username is supplied for use as the "user" in the UsernameToken. A CallbackHandler class is supplied to get the password to use in the UsernameToken. Compliance of the Basic Security Profile 1.1 is turned off, this is to prevent CXF throwing an exception when receiving a non-spec compliant response from a non-CXF STS:

        Map<String, Object> properties = new HashMap<String, Object>();
        stsClient.setProperties(properties);
        properties.put(SecurityConstants.USERNAME, "alice");
        properties.put(
                SecurityConstants.CALLBACK_HANDLER,
                "org.apache.cxf.systest.sts.common.CommonCallbackHandler"
        );
        properties.put(SecurityConstants.IS_BSP_COMPLIANT, "false");
              
        If the KeyType is a "PublicKey", then an X.509 Certificate is presented to the STS in the request to embed in the generated SAML Assertion. The X.509 Certificate is obtained from the keystore defined in "clientKeystore.properties", with the alias "myclientkey". Finally, the "useCertificateForConfirmationKeyInfo" property of the STSClient means that the entire certificate is to be included in the request, instead of a KeyValue (which is the default):

        if (PUBLIC_KEY_KEYTYPE.equals(keyType)) {
                properties.put(SecurityConstants.STS_TOKEN_USERNAME, "myclientkey");
                properties.put(SecurityConstants.STS_TOKEN_PROPERTIES, "clientKeystore.properties");
                stsClient.setUseCertificateForConfirmationKeyInfo(true);
        }

        Finally, the token type is set on the STSClient (the type of token that is being requested), as well as the KeyType (specific to a SAML Assertion), and a security token is requested, passing the endpoint address which is sent to the STS in the "AppliesTo" element:

                stsClient.setTokenType(tokenType);
                stsClient.setKeyType(keyType);
                return stsClient.requestSecurityToken(endpointAddress);

        The returned SecurityToken object contains the received token as a DOM element, the ID of the received token, any reference elements that were returned - which show how to reference the token, any secret associated with the token, and the lifetime of the token.
        Categories: Colm O hEigeartaigh

        Apache CXF STS documentation - part I

        Wed, 10/19/2011 - 18:00
        The forthcoming Apache CXF 2.5 release will have an STS (Security Token Service) implementation which has been donated by Talend. This is the first in a series of blog posts where I will be going into the STS implementation in detail. In this post I will be explaining what an STS is and talking about the STS provider framework in CXF.

        1) What is a Security Token Service?

        An informal description of a Security Token Service is that it is a web service that offers some or all of the following services (amongst others):
        • It can issue a Security Token of some sort based on presented or configured credentials.
        • It can say whether a given Security Token is valid or not
        • It can renew (extend the validity of) a given Security Token
        • It can cancel (remove the validity of) a given Security Token
        • It can transform a given Security Token into a Security Token of a different sort.
        Offloading this functionality to another service greatly simplifies client and service provider functionality, as they can simply call the STS appropriately rather than have to figure out the security requirements themselves. For example, the WSDL of a service provider might state that a particular type of security token is required to access the service. A client of the service can ask an STS for a Security Token of that particular type, which is then sent to the service provider. The service provider could choose to validate the received token locally, or dispatch the token to an STS for validation. These are the two most common use-cases of an STS.

        A client can communicate with the STS via a protocol defined in the WS-Trust specification. The SOAP Body of the request contains a "RequestSecurityToken" element that looks like:

        <wst:RequestSecurityToken Context="..." xmlns:wst="...">
            <wst:TokenType>...</wst:TokenType>
            <wst:RequestType>...</wst:RequestType>
            <wst:SecondaryParameters>...</wst:SecondaryParameters>
            ...
        </wst:RequestSecurityToken>

        The Apache CXF STS implementation supports a wide range of parameters that are passed in the RequestSecurityToken element. The SOAP Body of the response from the STS will contain a "RequestSecurityTokenResponse(Collection)" element, e.g.:

        <wst:RequestSecurityTokenResponseCollection xmlns:wst="...">
            <wst:RequestSecurityTokenResponse>
            ...
            </wst:RequestSecurityTokenResponse>
        </wst:RequestSecurityTokenResponseCollection>

        1.1 A sample request/response for issuing a Security Token

        A sample client request is given here, where the client wants the STS to issue a SAML 2.0 token for the "http://cxf.apache.org:8080/service" service:

        <wst:RequestSecurityToken Context="..." xmlns:wst="...">
            <wst:TokenType>
               http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0
            </wst:TokenType>
            <wst:RequestType>
                http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue
            </wst:RequestType>
            <wsp:AppliesTo>http://cxf.apache.org:8080/service</wsp:AppliesTo>
        </wst:RequestSecurityToken>

        The STS responds with:

        <wst:RequestSecurityTokenResponseCollection xmlns:wst="...">
            <wst:RequestSecurityTokenResponse>
                 <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="..." ... />
                 </wst:RequestedSecurityToken>
            </wst:RequestSecurityTokenResponse>
        </wst:RequestSecurityTokenResponseCollection>

        2) The STS provider framework in Apache CXF

        The first support for an STS in Apache CXF appeared in the 2.4.0 release with the addition of an STS provider framework in the WS-Security module. This is essentially an API that can be used to create your own STS implementation. As the STS implementation shipped in CXF 2.5 is based on this provider framework, it makes sense to examine it in more detail.

        The SEI (Service Endpoint Interface) is available here. It contains the following methods that are relevant to the STS features discussed above:
        • RequestSecurityTokenResponseCollectionType issue(RequestSecurityTokenType request) - to issue a security token
        • RequestSecurityTokenResponseType issueSingle( RequestSecurityTokenType request) - to issue a security token that is not contained in a "Collection" wrapper (for legacy applications).
        • RequestSecurityTokenResponseType cancel(RequestSecurityTokenType request) - to cancel a security token
        • RequestSecurityTokenResponseType validate(RequestSecurityTokenType request) - to validate a security token
        • RequestSecurityTokenResponseType renew(RequestSecurityTokenType request) - to renew a security token
        The SEI implementation handles each request by delegating it to a particular operation, which is just an interface that must be implemented by the provider framework implementation. Finally, a JAX-WS provider is available, which dispatches a request to the appropriate operation.

        Significant updates to the STS Provider framework after the CXF 2.4.0 release include support for SOAP 1.2, a major bug fix to support operations other than issue,  better exception propagation, and adding support for the WS-Trust 1.4 schema. These features are all available in the Apache CXF 2.4.3 release onwards.
        Categories: Colm O hEigeartaigh

        Using Kerberos with Web Services - part II

        Tue, 10/11/2011 - 18:03
        This is the second of a two-part series on using Kerberos with Web Services, with Apache WSS4J and CXF. Part I showed how to set up a KDC distribution, and how to generate client and service principals to use in some CXF system tests. The system tests showed how to obtain a Kerberos token from a KDC, package it in a BinarySecurityToken, and send it to a service endpoint for validation. In other words, part I illustrated how to use Kerberos for client authentication in a web service setting.

        This article builds on part I by showing how to use the secret key associated with a Kerberos Token to secure (sign and encrypt) the request. This functionality was added as part of WSS4J 1.6.3, and the related WS-SecurityPolicy functionality was released as part of CXF 2.4.3.

        1) Setting up the Kerberos system tests in Apache CXF 

        If you have not done so already, follow the instructions in part I to install a Kerberos distribution and to generate client and service principals to run the CXF Kerberos system tests. The KerberosTokenTest in Apache CXF contains a number of different Kerberos tests. In this article we will examine the tests that involve obtaining a Kerberos Token, and using the associated secret key to secure some part of the request.

        Firstly, make sure that the JDK has unlimited security policies installed, and then checkout the CXF WS-Security system tests via:
        svn co https://svn.apache.org/repos/asf/cxf/trunk/systests/ws-security/1.1) Installing a custom KerberosTokenDecoder

        Once the client obtains an AP-REQ token from the KDC, the client also has easy access to the session key, which can be used to secure the request in some way. Unfortunately, there appears to be no easy way to obtain the session key on the receiving side. WSS4J does not support extracting a Kerberos session key on the receiving side to decrypt/verify a secured request out-of-the-box. Instead, a KerberosTokenDecoder interface is provided, which defines methods for setting the AP-REQ token and current Subject, and a method to then get a session key. An implementation must be set on the KerberosTokenValidator to obtain a session key to decrypt or verify a signed request.

        To run the Kerberos system tests that require a secret key on the receiving side, download an implementation of the KerberosTokenValidator interface here, and copy it to "systests/ws-security/src/test/java/org/apache/cxf/systest/ws/kerberos/server". The implementation is based on code written by the Java Monkey, and uses internal sun APIs, and so can't be shipped in Apache CXF/WSS4J. Once this implementation has been copied into the ws-security module, then you must compile or run any tests with the "-Pnochecks" profile enabled, as otherwise the code fails checkstyle.

        Open the server configuration file ("src/test/resources/org/apache/cxf/systest/ws/kerberos/server/server.xml"), and uncomment the "kerberosTicketDecoderImpl" bean, and the property of the "kerberosValidator" bean that refers to it:
        <bean id="kerberosTicketDecoderImpl"   class="org.apache.cxf.systest.ws.kerberos.server.KerberosTokenDecoderImpl"/>
         
        <bean id="kerberosValidator"
               class="org.apache.ws.security.validate.KerberosTokenValidator">
                <property name="contextName" value="bob"/>
                <property name="serviceName" value="bob@service.ws.apache.org"/>
                <property name="kerberosTokenDecoder" ref="kerberosTicketDecoderImpl"/>
        </bean> 1.2) Running the tests

        Open KerberosTokenTest.java and comment out the "@org.junit.Ignore" entries for the last four tests, "testKerberosOverTransportEndorsing", "testKerberosOverAsymmetricEndorsing", "testKerberosOverSymmetricProtection" and "testKerberosOverSymmetricDerivedProtection". Finally, run the tests via:
        mvn -Pnochecks test -Dtest=KerberosTokenTest -Djava.security.auth.login.config=src/test/resources/kerberos.jaas 2) The tests in more detail

        In this section, we'll look at the tests in more detail. 

        2.1) WS-SecurityPolicy configuration

        The wsdl that defines the service endpoints contains WS-SecurityPolicy expressions that define the security requirements of the endpoints. The following security policies are used for the four tests defined above:
        • testKerberosOverTransportEndorsing: A (one-way) transport binding is defined, with a KerberosToken required as an EndorsingSupportingToken. 
        • testKerberosOverAsymmetricEndorsing: An asymmetric binding is used, where a KerberosToken is required as an EndorsingSupportingToken.
        • testKerberosOverSymmetricProtection: A symmetric binding is used, where a KerberosToken is specified as a ProtectionToken of the binding.
        • testKerberosOverSymmetricDerivedProtection: The same as the previous test-case, except that any secret keys that are used must be derived.
        The first two test-cases use an EndorsingSupportingToken, which means that the secret key associated with the KerberosToken is used to sign (endorse) some message part (the timestamp for the Transport binding). This illustrates proof-of-possession. For the latter two test-cases, the KerberosToken is defined as a ProtectionToken, meaning that the secret key is used to sign/encrypt the request (e.g. instead of using an X.509 Token to encrypt a session key).

        2.2) Kerberos LoginModule configuration

        Both the CXF client and service endpoint use JAAS to authenticate to the KDC. The JAAS file used as part of the system test is passed to the tests via the System property "java.security.auth.login.config". The client (alice) uses the following login module:
        alice {
            com.sun.security.auth.module.Krb5LoginModule required
            refreshKrb5Config=true useKeyTab=true keyTab="/etc/alice.keytab"
            principal="alice";
        };and the service endpoint (bob) uses:
        bob {
            com.sun.security.auth.module.Krb5LoginModule required
            refreshKrb5Config=true useKeyTab=true storeKey=true
            keyTab="/etc/bob.keytab" principal="bob/service.ws.apache.org";
        }; 2.3) Service endpoint configuration

        The service endpoints are spring-loaded. Each endpoint definition contains the JAX-WS property "ws-security.bst.validator" which is defined in SecurityConstants. WSS4J uses Validator implementations to perform validation on received security tokens. This particular property means that BinarySecurityTokens are to be validated by the given reference, e.g.:

        <jaxws:endpoint ...>
            <jaxws:properties>      
                <entry key="ws-security.bst.validator" value-ref="kerberosValidator"/>
            </jaxws:properties>
        </jaxws:endpoint> "kerberosValidator" is a KerberosTokenValidator instance given above. It requires a "contextName" property, which corresponds to the JAAS context name, as well as an optional "serviceName" property, and an optional "kerberosTokenDecoder" property to use to obtain a secret key. Combined with the JAAS properties file, this is all that is required for the service endpoint to validate a received Kerberos Token. 

        2.4 Client configuration

        Finally, the client must contact a KDC and obtain a Kerberos Token, once it sees that the service endpoint has a security policy that requires a KerberosToken. The client configuration is available here. A sample configuration for the Kerberos Test case is as follows:
        <jaxws:client name="{...}DoubleItKerberosTransportPort"
               createdFromAPI="true">
               <jaxws:properties>
                   <entry key="ws-security.kerberos.client">
                       <bean class="org.apache.cxf.ws.security.kerberos.KerberosClient">
                           <constructor-arg ref="cxf"/>
                           <property name="contextName" value="alice"/>
                           <property name="serviceName" value="bob@service.ws.apache.org"/>
                       </bean>           
                   </entry>
               </jaxws:properties>
        </jaxws:client>The JAX-WS property "ws-security.kerberos.client" (again, defined in SecurityConstants) corresponds to a KerberosClient object. Similar to the KerberosTokenValidator on the receiving side, this is configured with a JAAS context Name and service Name.
        Categories: Colm O hEigeartaigh

        Apache CXF STS articles

        Tue, 10/11/2011 - 15:21
        Two of my colleagues have written excellent articles on the forthcoming STS (Security Token Service) implementation in Apache CXF, complete with sample projects. See here for the article from Oliver Wulff, and here for the article from Glen Mazza.
        Categories: Colm O hEigeartaigh

        Using Kerberos with Web Services - part I

        Mon, 10/10/2011 - 18:00
        This is the first of a two-part series on using Kerberos with Web Services, with Apache WSS4J and CXF. WSS4J 1.6.2 adds support for obtaining a Kerberos ticket from a KDC (Key Distribution Center) and converting it to a BinarySecurityToken to be inserted into the security header of a SOAP request. On the receiving side, support has been added to validate the received Kerberos ticket accordingly. CXF 2.4.2 extends the Kerberos functionality available in WSS4J 1.6.2 to add support for WS-SecurityPolicy. No support is available yet (as of CXF 2.4.2) to use a secret key to sign and encrypt message parts, this will be the subject of part II.

        In this post we will talk about installing the MIT Kerberos distribution in Ubuntu, and creating the necessary credentials to run some tests. Then we will go into some system tests in CXF that show how a client can get a Kerberos AP-REQ ticket from a KDC and send it to a service provider, who then authenticates the ticket, all driven by some spring configuration and WS-SecurityPolicy.

        1) Installing MIT Kerberos

        1.1) Installing the product

        In this section we cover how to install the MIT Kerberos distribution in Ubuntu. This is needed to run the CXF Kerberos system tests. See here for more information on using Kerberos on Ubuntu. Open a command prompt and type:
        sudo apt-get install krb5-kdc krb5-admin-serverWhen the product is installing you'll be asked for the default Kerberos Version 5 realm. Enter:
        WS.APACHE.ORG You will then be prompted for the hostnames of Kerberos servers in the WS.APACHE.ORG Kerberos realm. As we are installing the KDC and running the tests on the same machine, we only need to enter "localhost". Similarly, enter "localhost" when prompted for the Administrative server for the Kerberos realm.

        1.2) Modifying configuration

        Once apt-get has finished, we need to modify the Kerberos configuration file ("sudo vi /etc/krb5.conf"):
        • Under the "[realms]" section, add a "default_domain" entry for ws.apache.org. The entire entry should look like:
          WS.APACHE.ORG = {
                       kdc = localhost
                       admin_server = localhost
                       default_domain = ws.apache.org
          }
        • Under the "[domain_realm]" section, add the following:     
        ws.apache.org = WS.APACHE.ORG   
        .ws.apache.org = WS.APACHE.ORG
        • Finally, add a logging section:
        [logging]

                kdc = FILE:/var/log/krb5kdc.log
                admin_server = FILE:/var/log/kadmin.log
                default = FILE:/var/log/krb5lib.log 1.3) Create principals

        The next step is to create some principals. Create a master key via:
        sudo kdb5_util create -sThe next step is to start kadmin locally via:
        sudo kadmin.localIf you run "listprincs" at the prompt you should see the ticket-granting-ticket principal "krbtgt/WS.APACHE.ORG@WS.APACHE.ORG". We will add a client principal and service principal:
        addprinc alice
        addprinc bob/service.ws.apache.org"quit" the kadmin prompt, and start the KDC with "sudo krb5kdc". If you see no error messages then everything should be working correctly. To test this try to get a ticket for "alice" via "kinit alice", entering the password given when creating the "alice" principal.

        1.4) Create keytabs

        To avoid having to enter passwords when running the tests, we will create Keytabs. Start kadmin.local again ("sudo kadmin.local"), and enter:
        ktadd -k /etc/alice.keytab alice
        ktadd -k /etc/bob.keytab bob/service.ws.apache.orgTo check that the keytabs were create correctly, you can inspect them with klist, e.g. "sudo klist -k /etc/alice.keytab". Finally make sure the keytabs are readable via "sudo chmod og+r /etc/*.keytab" - obviously this is not secure, but it is sufficient for this test application.

        2) Running the Kerberos system tests in Apache CXF

        Now that we have installed Kerberos and created the relevant principals, we can run the Kerberos system tests in Apache CXF. These tests are @Ignore'd by default. The KerberosTokenTest contains a number of different Kerberos tests. In this article we will just examine the tests that involve obtaining a Kerberos Token, and not any of the tests that involve using the secret key associated with a Kerberos Token to secure some part of the request.

        Firstly, make sure that the JDK has unlimited security policies installed, and then checkout the CXF WS-Security system tests via:
        svn co https://svn.apache.org/repos/asf/cxf/trunk/systests/ws-security/Open KerberosTokenTest.java and comment out the "@org.junit.Ignore" entries for the first four tests, "testKerberosOverTransport", "testKerberosOverSymmetric", "testKerberosOverSymmetricSupporting" and "testKerberosOverAsymmetric". Finally, run the tests via:

                mvn test -Dtest=KerberosTokenTest -Djava.security.auth.login.config=src/test/resources/kerberos.jaas

        2.1) WS-SecurityPolicy configuration

        The wsdl that defines the service endpoints contains WS-SecurityPolicy expressions that define the security requirements of the endpoints. The following security policies are used for the four tests defined above:
        • testKerberosOverTransport: A (one-way) transport binding is defined, with a KerberosToken required as a SupportingToken. Essentially, this means that the communication is secured with TLS, and authentication is handled by a Kerberos token.
        • testKerberosOverSymmetric: A symmetric binding is used, where a KerberosToken is required as a SignedSupportingToken. 
        • testKerberosOverSymmetricSupporting: A symmetric binding is used, where a KerberosToken is required as a SupportingToken.
        • testKerberosOverAsymmetric: An asymmetric binding is used, where a Kerberos token is required as a SignedSupportingToken.
        The WS-SecurityPolicy expression used for a KerberosToken is:
        <sp:KerberosToken sp:IncludeToken=".../Once">
            <wsp:Policy>
                <sp:WssGssKerberosV5ApReqToken11/>
            </wsp:Policy>
        </sp:KerberosToken>This means that a GSS V5 AP-REQ Token is required "once", in other words the initial invocation between the client and service endpoint must contain a token of this type encoded as a BinarySecurityToken in the security header of the request.

        2.2) Kerberos LoginModule configuration

        Both the CXF client and service endpoint use JAAS to authenticate to the KDC. The JAAS file used as part of the system test is passed to the tests via the System property "java.security.auth.login.config". The client (alice) uses the following login module:
        alice {
            com.sun.security.auth.module.Krb5LoginModule required 
            refreshKrb5Config=true useKeyTab=true keyTab="/etc/alice.keytab"  
            principal="alice";
        };and the service endpoint (bob) uses:
        bob {
            com.sun.security.auth.module.Krb5LoginModule required
            refreshKrb5Config=true useKeyTab=true storeKey=true
            keyTab="/etc/bob.keytab" principal="bob/service.ws.apache.org";
        }; 2.3) Service endpoint configuration

        The service endpoints are spring-loaded. Each endpoint definition contains the JAX-WS property "ws-security.bst.validator" which is defined in SecurityConstants. WSS4J uses Validator implementations to perform validation on received security tokens. This particular property means that BinarySecurityTokens are to be validated by the given reference, e.g.:
        <jaxws:endpoint ...>   
            <jaxws:properties>      
                <entry key="ws-security.bst.validator" value-ref="kerberosValidator"/>
            </jaxws:properties>
        </jaxws:endpoint> "kerberosValidator" is defined as:
        <bean id="kerberosValidator"
            class="org.apache.ws.security.validate.KerberosTokenValidator">
            <property name="contextName" value="bob"/>
            <property name="serviceName" value="bob@service.ws.apache.org"/>
        </bean>The KerberosTokenValidator class ships with Apache WSS4J. It requires a "contextName" property, which corresponds to the JAAS context name, as well as an optional "serviceName" property. Combined with the JAAS properties file, this is all that is required for the service endpoint to validate a received Kerberos Token. 

        2.4 Client configuration

        Finally, the client must contact a KDC and obtain a Kerberos Token, once it sees that the service endpoint has a security policy that requires a KerberosToken. The client configuration is available here. A sample configuration for the Kerberos Test case is as follows:
        <jaxws:client name="{...}DoubleItKerberosTransportPort"
               createdFromAPI="true">
               <jaxws:properties>
                   <entry key="ws-security.kerberos.client">
                       <bean class="org.apache.cxf.ws.security.kerberos.KerberosClient">
                           <constructor-arg ref="cxf"/>
                           <property name="contextName" value="alice"/>
                           <property name="serviceName" value="bob@service.ws.apache.org"/>
                       </bean>           
                   </entry>
               </jaxws:properties>
        </jaxws:client>The JAX-WS property "ws-security.kerberos.client" (again, defined in SecurityConstants) corresponds to a KerberosClient object. Similar to the KerberosTokenValidator on the receiving side, this is configured with a JAAS context Name and service Name.
        Categories: Colm O hEigeartaigh

        Improving decryption performance in Apache Santuario 1.5

        Fri, 10/07/2011 - 13:10
        Andreas Veithen alerted me some months back to a performance problem in Apache Santuario when decrypting messages. The issue emerged when some profiling was done on Dennis Sosnoski's test-code for measuring WS-Security performance across different web services stacks (see the original article here).

        The test scenario involves deploying an Apache CXF 2.4.2 endpoint in Tomcat and repeatedly testing the "signencr" invocation defined in the article (WS-Security signing of body and headers, with timestamp and encryption of body) using a CXF client. Two types of test-runs were executed, 1000 "large" messages at 0.2 density in one run, and 10000 "small" messages at 0.05 density in another. When doing some profiling using a sampling profiler on the client, it emerged that the time it took to deserialize a decrypted XML String into a DOM element was taking around 20% of the total execution time for all WS-Security processing!

        The way the default deserializing algorithm works in Apache Santuario 1.4.x is to parse the decrypted XML String into a new Document object, which is then imported into the existing Document. As Apache Xerces defers the creation of Node objects, the import operation triggers the full expansion of the DOM tree.

        There are a number of alternatives to using the DocumentBuilder/importNode approach used in Santuario 1.4.x. The first approach is to use a Transformer object to transform the Source (XML String) into a placeholder Node belonging to the existing Document. This approach avoids having to explicitly import the nodes back to the existing Document. The second approach, is to use the streaming API available in the JDK 1.6 (not an option for Santuario 1.5 which must compile against the JDK 1.5).

        Here are some (ad-hoc) test results. The first results show the total time for each test-run using both algorithms:
        • Large Messages:
          • Document Serializer: 119.46s
          • Transform Serializer: 115.68s
        • Small Messages:
          • Document Serializer: 222.32s
          • Transform Serializer: 216.76s
        The next results show the time spent in the Serializer.deserialize() operation as a percentage of the total WS-Security processing time:
        • Large Messages:
          • Document Serializer: 19.92%
          • Transform Serializer: 18.04%
        • Small Messages:
          • Document Serializer: 24.54%
          • Transform Serializer: 18.36%
        As there is a clear performance improvement in using the Transformer approach, it makes sense to use this as the default serializing mechanism in Apache Santuario 1.5. The Serializer interface is now public, and a different implementation can be set on XMLCipher. Two implementations are provided in the code, DocumentSerializer and TransformSerializer (the new default algorithm). If anyone is interested in running experiments of their own, the StreamSerializer algorithm is available here.

        Do you have any suggestions on how this could be improved further? Clearly, the time it takes to deserialize a decrypted XML String into a DOM node still takes far longer than it should. A fully StAX approach for XML Security would surely offer much improved performance - this is under development and planned for next year.
        Categories: Colm O hEigeartaigh

        Apache WSS4J 1.6.3 released

        Tue, 10/04/2011 - 14:39
        Apache WSS4J 1.6.3 has been released. It can be downloaded here and the issues fixed are listed in the WSS4J JIRA.

        Probably the most significant part of this release is that WSS4J now fully supports the Kerberos Token Profile 1.1. In the previous release, support was added to retrieve a Kerberos token from a KDC, and insert it into the security header of a request, and then validate it accordingly on the receiving side. In WSS4J 1.6.3, support has been added to use the secret key associated with the Kerberos token to sign and encrypt the request, and to verify and decrypt on the receiving side. I am planning on writing a series of blog posts soon about how to use Kerberos with WSS4J and CXF. The forthcoming Apache CXF 2.4.3 release will have full WS-SecurityPolicy support for working with Kerberos, based on the work done in WSS4J 1.6.3.

        In addition to the Kerberos work, WSS4J 1.6.3 features an upgraded Opensaml dependency, as well as several bug fixes.
        Categories: Colm O hEigeartaigh

        Talend donates Security Token Service (STS) to Apache CXF

        Fri, 09/23/2011 - 16:31
        I am pleased to announce that Talend has donated a Security Token Service (STS) implementation to Apache CXF, which will be part of the forthcoming 2.5 release. Since the 2.4.0 release, CXF ships with an STS framework (in the ws-security module), as well as a simple implementation of the framework in the examples. The STS that Talend has donated to the community is a sophisticated implementation of the STS framework that builds on top of CXF's existing mature security functionality.

        In future blog posts I will document the features of the STS and how to configure it, as well as walk through some system tests. Here are some of the features and standards that the new STS supports:
        • WS-Trust 1.3/1.4
        • WS-SecurityPolicy1.3
        • Authentication Mechanisms for a RST:UsernameToken, SAML token (1.1/2.0), KerberosToken, X.509 Token.
        • Security Binding supported: Symmetric,Asymmetric, Transport 
        • Supports WS-Trust Issue/Validate and Cancel binding 
        • Can issue the following tokens:SAML 1.1/2.0Holder-Of-Key/Bearer, SecurityContextTokens, Custom Tokens.
        • Issued token can be encrypted 
        • Validate binding supports issuing a new token (token transformation).
        • Custom Validators can be implemented 
        • Creation of SAML tokens can be customized.
        • Advanced RST elements:KeyType (Public, Symmetric, Bearer), Entropy (Symmetric, Public) , OnBehalfOf, ActAs, Claims, SecondaryParameters
        • Pluggable claims handling and management
        Categories: Colm O hEigeartaigh

        Specifying custom AlgorithmSuite policies in Apache CXF 2.4.3

        Mon, 09/19/2011 - 12:01
        When specifying a security binding via WS-SecurityPolicy, it is possible to define the algorithm suite via the "sp:AlgorithmSuite" policy. WS-SecurityPolicy defines a number of standard AlgorithmSuite policies, which control various security properties like the maximum and minimum Symmetric and Asymmetric key lengths, the encryption/signature/digest algorithms to use, etc. An example policy is given below. For this policy, the minimum symmetric key length is 256 bits, and the encryption algorithm is AES256:

        <sp:AlgorithmSuite>
            <wsp:Policy>
                <sp:Basic256 />
            </wsp:Policy>
        </sp:AlgorithmSuite>

        There are certain scenarios where a user might want to use a non-standard AlgorithmSuite. For example, the minimum Asymmetric Key Length for all standard AlgorithmSuites is 1024 bits. This requires that the JDK has unrestricted security policies installed. If it is not possible to install unresticted security policies, a user might decide that using 512 bits RSA keys is sufficient (this is not recommended).

        Apache CXF 2.4.3 provides support for specifying custom algorithm suites. A new interface is defined to create an AlgorithmSuite object given a policy, with a default implementation that supports the standard AlgorithmSuite policies. It is possible to create a new implementation of the AlgorithmSuiteLoader interface, and install it as a bus extension. For an example, there is a CXF system test that allows 512 bit asymmetric keys, with custom AlgorithmSuiteLoader and AlgorithmSuite implementations. The custom AlgorithmSuiteLoader implementation is spring-loaded, and registers itself as a bus extension.
        Categories: Colm O hEigeartaigh

        SAML SecurityPolicy enforcement in CXF 2.4.2

        Mon, 09/12/2011 - 14:44
        Apache CXF 2.4.2 was released recently. In this blog post I want to delve into how CXF 2.4.2 enforces WS-SecurityPolicy expressions relating to SAML Assertions on the inbound side.

        There are two policy expressions relating to SAML Assertions, the SamlToken and IssuedToken policy assertions. On the outbound side, the SamlToken expression will trigger a CallbackHandler to obtain a SAML Assertion to insert into the outbound security header, and the IssuedToken expression will use the STSClient to obtain a SAML Assertion from a Security Token Service (STS).

        On the inbound side, any SAML Assertion received as part of the security header will be parsed initially by WSS4J. If the assertion is signed, then the signature is verified. If the confirmation method of the Subject of the Assertion is "holder-of-key", then WSS4J will parse the Subject KeyInfo and extract whatever credentials it can find, i.e. secret key or an X509Certificate. If no credential is found (or understood), then the default behaviour is to throw an exception. If the confirmation method is "holder-of-key", then the default behaviour (which is configurable) is to enforce that the Assertion is signed. Finally, WSS4J verifies trust in a certificate that was used to sign the assertion.

        After WSS4J is done with validating a received SAML Assertion, CXF does some additional validation according to the configured security policy. For more information on any of the following terms (holder-of-key, sender-vouches, etc.), please consult the SAML Token Profile 1.1 specification.

        1) SamlToken policy

        If a SamlToken policy is used, the version of the received Assertion (1.1 or 2.0) is checked against the policy, e.g. if <sp:WssSamlV20Token11 /> is configured in the SAMLToken policy then the received Assertion must be a SAML 2.0 Assertion. Two checks are then done on the received Assertion, depending on what the subject confirmation method is.
        • Holder-of-key: If the subject confirmation method is "holder-of-key", there must be some proof-of-possession of the key associated with the subject of the assertion. CXF will enforce that either the key was used to sign some portion of the SOAP request, or alternatively the subject credential of the SAML Assertion must match a client certificate credential when 2-way TLS is used.
        • Sender-Vouches: If the subject confirmation method is "sender-vouches", then CXF will enforce that the SAML Assertion and SOAP Body are signed by the same signature. Alternatively, it will check that 2-way TLS is used.
        2) IssuedToken Policy

        If an IssuedToken policy is used, then the receiver is expecting to get a SAML Assertion that is issued by a third-party security service. If the subject confirmation method of the Assertion is "holder-of-key", then it does the same check as described above for a SamlToken policy. Additionally, if a "<sp:RequestSecurityTokenTemplate..../>" policy is configured, it will attempt to match the received Assertion against the RSTTemplate parameters:
        • TokenType: If a TokenType parameter is specified in the template, it will match this against the version of the received Assertion. For example, if the TokenType is "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1", then the Assertion must be a SAML 1.1 Assertion.
        • KeyType: If a KeyType parameter is specified in the template which ends with "SymmetricKey", then the subject of the Assertion must contain a secret key. If the KeyType parameter ends with "PublicKey", then the Subject must contain a Certificate or PublicKey.
        Here is an example of a RequestSecurityTokenTemplate:

        <sp:RequestSecurityTokenTemplate>
            <t:TokenType>
              http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile1.1#SAMLV1.1
           </t:TokenType>
           <t:KeyType>
             http://docs.oasis-open.org/ws-sx/ws-trust/200512/PublicKey
           </t:KeyType>
        </sp:RequestSecurityTokenTemplate>

        Issuer or IssuerName policies are not yet enforced, this will probably be done in a future version of CXF.
        Categories: Colm O hEigeartaigh

        Apache WSS4J 1.5.12 and 1.6.2 released

        Thu, 08/18/2011 - 15:21
        Apache WSS4J 1.5.12 and 1.6.2 have been released.

        WSS4J 1.5.12 is a bug-fix release, which fixes some problems relating to future-dated Timestamps, fixes a bug with deriving keys from UsernameTokens, and fixes a concurrency issue with EnvelopeIdResolver, amongst other things.

        WSS4J 1.6.2 contains some enhancements for SAML Token creation, fixes a bug with deriving keys from UsernameTokens, adds initial support for the Kerberos Token Profile 1.1, and fixes some problems relating to signature verification in certain containers.
        Categories: Colm O hEigeartaigh

        SAML token creation in Apache WSS4J 1.6

        Tue, 08/16/2011 - 20:10
        WSS4J 1.6 uses Opensaml2 to create and parse SAML Assertions. WSS4J ships with a library that wraps the Opensaml API to greatly simplify the process of creating a SAML Assertion. The user implements a CallbackHandler instance which must be able to handle a WSS4J SAMLCallback object. and set certain properties on this object. WSS4J then parses the properties that were set on the object and creates a SAML Assertion accordingly. In this blog post we will examine the process of creating a SAML Assertion by populating a SAMLCallback object in more detail.

        1) Obtain a SAMLCallback object

        First off, a SAMLCallback object must be obtained in the CallbackHandler implementation, e.g.:

        if (callbacks[i] instanceof SAMLCallback) {
            SAMLCallback callback = (SAMLCallback) callbacks[i];
            ....
        }

        2) Set the SAML Version

        The first thing to do is to set the desired SAML Version of the Assertion you want to create on the SAMLCallback object, e.g.:

        callback.setSamlVersion(SAMLVersion.VERSION_11);

        This method takes an org.opensaml.common.SAMLVersion object. For normal purposes, it will be one of the following:
        • SAMLVersion.VERSION_11
        • SAMLVersion.VERSION_20
        The default value in SAMLCallback is VERSION_11.

        3) Set the Issuer

        The next thing to do is to set the issuer (String) name of the token, e.g.:

        callback.setIssuer("sts");

        4) Set the Subject

        The next thing to do is to set the Subject of the Assertion. WSS4J defines a SubjectBean which encapsulates a SAML Subject. The Subject Name, NameQualifier, NameIDFormat and ConfirmationMethod Strings can be set on the SubjectBean instance. The NameIDFormat and ConfirmationMethod values that can be set are largely defined in the SAML1Constants and SAML2Constants classes. The default value for the SubjectBean NameIDFormat is SAML1Constants.NAMEID_FORMAT_UNSPECIFIED. Both constants classes contain the following values that can be used for the ConfirmationMethod value:
        •  SAML[1|2]Constants.CONF_BEARER
        •  SAML[1|2]Constants.CONF_HOLDER_KEY
        •  SAML[1|2]Constants.CONF_SENDER_VOUCHES
        In addition to this, WSS4J defines a KeyInfoBean that can be set on the SubjectBean, which represents a KeyInfo structure that will be embedded in a SAML Subject. There are a number of different ways to set the KeyInfo value:
        • A DOM element can be defined for a pre-existing KeyInfo element
        • A PublicKey object can be used
        • An X.509 Certificate can be used
        For the latter two cases, the KeyInfoBean contains a CERT_IDENTIFIER enum which defines how the PublicKey or X.509 Certificate will be output. The following values can be configured:
        • X509_CERT: An X509Certificate element will be output
        • X509_ISSUER_SERIAL: An X509 IssuerSerial element will be output
        • KEY_VALUE: A KeyValue element will be output
        The default value in the KeyInfoBean is X509_CERT. Here is a sample that shows how to create a SubjectBean:

        SubjectBean subjectBean = new SubjectBean();
        subjectBean.setSubjectName("uid=joe");
        subjectBean.setSubjectNameQualifier("apache.org");
        subjectBean.setSubjectConfirmationMethod(
             SAML1Constants.CONF_SENDER_VOUCHES
        );
        KeyInfoBean keyInfo = new KeyInfoBean();
        keyInfo.setCertificate(cert);
        subjectBean.setKeyInfo(keyInfo);

        Finally, it remains to store the SubjectBean instance in the SAMLCallback object. A SAML 2.0 Assertion contains a single Subject, and so for this case the SubjectBean instance can be set directly on the SAMLCallback, e.g.:

        callback.setSubject(subjectBean);

        For a SAML 1.1 Assertion, the Subject can be in a SubjectStatement (in which case it can be set directly on the SAMLCallback), or it can be embedded in one of the other statements which we will cover next.

        5) Create and set a Statement

        WSS4J contains a number of beans to create Statements for SAML Assertions, that can be set on a SAMLCallback object. They can be used in either SAML 1.1 or SAML 2.0 Assertions, with the caveat that SubjectBean instances are not used with statements in SAML 2.0.

        a) Attribute Statements

        WSS4J contains an AttributeStatementBean for creating Attribute statements. This contains a SubjectBean (for the SAML 1.1 case), and a list of AttributeBean objects. An attribute simple name, qualified name, and name format Strings can be set on the AttributeBean, as well as a list of attribute value Strings. Here is an example of creating and adding an AttributeStatement to a SAMLCallback object:

        AttributeStatementBean attrBean = new AttributeStatementBean();
        attrBean.setSubject(subjectBean);
        AttributeBean attributeBean = new AttributeBean();
        attributeBean.setSimpleName("role");
        attributeBean.setAttributeValues(Collections.singletonList("user"));
        attrBean.setSamlAttributes(Collections.singletonList(attributeBean));
        callback.setAttributeStatementData(Collections.singletonList(attrBean));

        b) Authentication Statements

        WSS4J contains an AuthenticationStatementBean for creating Authentication statements. For SAML 1.1 a SubjectBean instance can be set on this object. In addition to this, an authentication instant and authentication method can be set, as well as a SubjectLocalityBean object and a session index String. Various authentication method Strings are defined in the SAML1Constants and SAML2Constants given above. Here is an example:

        AuthenticationStatementBean authBean = new AuthenticationStatementBean();
        authBean.setSubject(subjectBean);
        SubjectLocalityBean subjectLocality = new SubjectLocalityBean();
        subjectLocality.setIpAddress(subjectLocalityIpAddress);
        subjectLocality.setDnsAddress(subjectLocalityDnsAddress);
        authBean.setSubjectLocality(subjectLocality);
        authBean.setAuthenticationMethod("Password");     callback.setAuthenticationStatementData(Collections.singletonList(authBean));

        c) Authorization Decision Statements

        WSS4J contains an AuthDecisionStatementBean for creating Authorization Decision Statements. For SAML 1.1 a SubjectBean instance can be set on this object. A Decision enum can be set (PERMIT, INDETERMINATE, DENY), as well as a resource String, evidence Object, and a list of ActionBeans, which in turn contain an action namespace and action contents. Here is an example:

        AuthDecisionStatementBean authzBean = new AuthDecisionStatementBean();
        authzBean.setSubject(subjectBean);
        ActionBean actionBean = new ActionBean();
        actionBean.setContents("Read");
        authzBean.setActions(Collections.singletonList(actionBean));
        authzBean.setResource("endpoint");
        authzBean.setDecision(AuthDecisionStatementBean.Decision.PERMIT);
        authzBean.setResource(resource);  callback.setAuthDecisionStatementData(Collections.singletonList(authzBean));
         
        6) Create a Conditions object

        Finally, a ConditionsBean object can be used to specify a set of Conditions on the SAML Assertion. This is optional, as by default a Conditions element will be generated with a NotBefore value of the present instant and a NotOnOrAfter value corresponding to 5 minutes into the future. This can be changed by creating a ConditionsBean and specifying either "notBefore" and "notAfter" dates, or else a token period in minutes in which the token is valid. It is also possible to specify an audience restriction URI on the ConditionsBean object. Here is an example:

        ConditionsBean conditions = new ConditionsBean();
        conditions.setTokenPeriodMinutes(10);
        conditions.setAudienceURI("http://ws.apache.org/wss4j");
        callback.setConditions(conditionsBean);

        For some examples of CallbackHandlers used to create SAML Assertions, check out the following CallbackHandlers used in the WSS4J unit tests - SAML1AuthnHOKHandler, SAML1CallbackHandler and SAML2CallbackHandler.
        Categories: Colm O hEigeartaigh

        WS-Trust 1.4 support in CXF

        Mon, 08/15/2011 - 17:43
        Apache CXF has had support for sending a WS-Trust 1.4 ActAs element as part of a RequestSecurityToken call to a Security Token Service (STS) since the 2.2.10 release. To quote from the WS-Trust 1.4 specification:
        /wst:RequestSecurityToken/wst:ActAs
         
        This OTPIONAL (sic) 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.The object to be placed in an ActAs element can be set by the SecurityConstants tag "STS_TOKEN_ACT_AS" on the Message properties. Prior to Apache CXF 2.4.1 the ActAs object could either be an XML String or else a DOM Element. See the following CXF wiki page for more information.

        Several enhancements were made in CXF 2.4.1 as part of this JIRA. First of all, support was added for OnBehalfOf. To quote from the spec again:
        /wst:RequestSecurityToken/wst:OnBehalfOf
        This OPTIONAL element indicates that the requestor is making the request on behalf of another.  The identity on whose behalf the request is being made is specified by placing a security token, <wsse:SecurityTokenReference> element, or <wsa:EndpointReference> element within the <wst:OnBehalfOf> element. The requestor MAY provide proof of possession of the key associated with the OnBehalfOf identity by including a signature in the RST security header generated using the OnBehalfOf token that signs the primary signature of the RST (i.e. endorsing supporting token concept from WS-SecurityPolicy). Additional signed supporting tokens describing the OnBehalfOf context MAY also be included within the RST security header.The object to be placed in an OnBehalfOf element can be set by the SecurityConstants tag "STS_TOKEN_ON_BEHALF_OF" on the Message properties. Similar to ActAs, this object can be an XML String or a DOM Element. In addition to this, the object for both ActAs and OnBehalfOf can now be a CallbackHandler instance. The CallbackHandler implementation must be able to process a DelegationCallback object, which has access to the current CXF Message, and returns a DOM Element to the STSClient for insertion into either ActAs or OnBehalfOf.

        Two sample CallbackHandler implementations are shipped with CXF 2.4.1 that can be used for either OnBehalfOf or ActAs. The ReceivedTokenCallbackHandler obtains the previously received message from the current message property of the DelegationCallback object, and extracts a token that has been received in that message (SAML Token/UsernameToken/BinarySecurityToken). This token is then used as the delegation token. This CallbackHandler implementation is useful as part of an WS-Trust intermediary scenario. Secondly, the WSSUsernameCallbackHandler obtains a username via the jax-ws property "ws-security.username" (SecurityConstants.USERNAME), and creates a wsse:UsernameToken (with no password) to be used as the delegation token.
        Categories: Colm O hEigeartaigh

        Pages