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
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.
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".
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
- 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.
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.
Hi Colm, I am slightly confused so I will reiterate. The client and STS generate a secret key like so:
ReplyDeleteclient entropy(optional) + server entropy -> client supplied key algorithm -> secret key
This key is used for signing.
My first question: I'm assuming that you must secure communication between client and STS when exchanging entropy and key algorithms otherwise an threat agent could easily steal the key.
Same goes for key exchange between STS and SP (you mentioned this explicitly).
My second question: what is the benefit of the entropy exchange? How is it any better than having the server generate a key? Is it just to increase the randomness of the key? Is it so the client can have some guarantee that the key is more random?
Thanks.
DeleteYes, all communication between an STS client and the STS must be secured either via TLS or message level security.
I guess in theory the key exchange offers more security as an eavesdropper would have to intercept both the request + response to recreate the key. In practice though it doesn't make any real difference, as both should be secured.
Colm.