Cryptographic operations are required but token has no keys

| | Comments (0) | TrackBacks (0)
Here's the scenario: You're creating a .NET app that uses active federation to get a token from an STS and submit it to a downstream service. That other service might be another STS or it might be a Web service written in .NET or some other language (doesn't matter). The token that you're getting from the STS is a bearer token. You have some code like this:

private static void CallWebService(SecurityToken token)
{
    var factory = GetServiceChannelFactory<IFoobarService>();
    var channel = factory.CreateChannelWithIssuedToken(token);

    var order = channel.DoFoo();
}

When the call to DooFoo is made, you get an error like this:

The signing token Generic XML token:
   validFrom: 01/07/2012 09:33:36
   validTo: 01/07/2012 10:03:36
   InternalTokenReference: Saml2AssertionKeyIdentifierClause( Id = 'U8ovpOcJlJFu7udUreVI_4I69vj' )
   Token Element: (Assertion, urn:oasis:names:tc:SAML:2.0:assertion)
 has no keys. The security token is used in a context that requires it to perform cryptographic operations, but the token contains no cryptographic keys. Either the token type does not support cryptographic operations, or the particular token instance does not contain cryptographic keys. Check your configuration to ensure that cryptographically disabled token types (for example, UserNameSecurityToken) are not specified in a context that requires cryptographic operations (for example, an endorsing supporting token).

To fix this, do two things:

  1. Make sure the binding you're using for the service (not the STS, that doesn't matter) is WS2007FederationHttpBinding not WS2007HttpBinding or WSHttpBinding.
  2. On that binding, set Security.Message.IssuedKeyType to SecurityKeyType.BearerKey.

Error goes away and now you can fix the next problem ;-)

So, what was the deal? The token you had in hand was a bearer token, meaning there is no requirement on the presenter when submitting the token to prove that it was indeed the entity that got the token from the STS; however, in its default configuration, WCF is trying to do just that. Because the token doesn't have a proof key in it (the cryptographic key the error is talking about), WCF can't compute the digital signature it thinks it should send along.

Alternatively, if you really do want to prove to the RP Web service that you were the one who got the token from the STS, ask for a Holder of Key (HoK) assertion. You can do this by changing the TokenType in the RST, but your STS will have to support this.

If you have questions on this, leave a comment below or shoot me a mail.