Tag Archives: WCF

WCF and the AsyncPattern property (part 1)

The OperationContractAttribute is used, in WCF, to define operations on a service contract. This attribute contains the AsyncPattern property that can be used to implement or use services asynchronously.

AsyncPattern at the service side

Consider the following excerpt

   1: [ServiceContract]
   2: interface IService {
   3:     [OperationContract]
   4:     ReplyData Operation1(RequestData rd);
   5:  
   6:     [OperationContract(AsyncPattern = true)]
   7:     IAsyncResult BeginOperation2(RequestData rd, AsyncCallback ac, object obj);
   8:     ReplyData EndOperation2(IAsyncResult ar);
   9: }
  • The first [OperationContract], which has AsyncPattern set to false (the default), defines one request-response operation called ‘Operation1’. This operation is implemented synchronously by one method: Operation1. Synchronously means that the WCF dispatcher will call the Operation1 method, passing the RequestData. This call will block during the execution of the operation. Finally, the method returns the ReplyData that will be used in the response sent to the client.

 

  • The second [OperationContract], which has AsyncPattern set to true, also defines one request-response operation called ‘Operation2’. However, this operation is implemented asynchronously by two methods: BeginOperation2 and EndOperation2. Asynchronously (see Asynchronous Programming Overview) means that:
    • The WCF dispatcher will call the BeginOperation2 method, passing the RequestData, an AsyncCallback and some state information.
    • This method should start the execution of the operation and return an IAsyncResult immediately.
    • When the execution of the operation is completed, then the AsyncCallback should be called.
    • This AsyncCallback, implemented by the WCF runtime, will then call EndOperation2 to collect the ReplyData that will be used in the response sent to the client.

Note that, when using AsyncPattern set to true, there is no longer a 1-to-1 relation between the service contract methods and the service operations. Namely, the BeginOperation2 and EndOperation2 methods are both associated to a single operation named ‘Operation2’.

Also, from the outside of the service, both operations (‘Operation1’ and ‘Operation2’) are seen as request-response operations. This is visible in the generated WSDL description

   1: <wsdl:portType name="IService">
   2:  
   3:   <wsdl:operation name="Operation1">
   4:     <wsdl:input wsaw:Action="..." message="..." /> 
   5:     <wsdl:output wsaw:Action="..." message="..." /> 
   6:   </wsdl:operation>
   7:  
   8:   <wsdl:operation name="Operation2">
   9:     <wsdl:input wsaw:Action="..." message="..." /> 
  10:     <wsdl:output wsaw:Action="..." message="..." /> 
  11:   </wsdl:operation>
  12:  
  13: </wsdl:portType>

So, concluding, the AsyncPattern is an implementation detail of the service: it defines the communication pattern between the WCF runtime and the service implementation but not the communication pattern between the service client and the service.

Asynchronous delegate invocation of a WCF client channel

In an older post, Nicholas Allen stated that an asynchronous delegate invocation on a WCF client channel object will block until the response is received from a service.

The only given explanation was:

The problem is that BeginInvoke knows about and only works with specific types of proxy objects, which do not include the proxy objects generated by ChannelFactory

In a related post, the blog’s author stated that

why does BeginInvoke break when all the TP [Transparent Proxy]and RP [Real Proxy] plumbing is in place? This question is much trickier than it seems to be, after a bit of research on the default implementation of TP and RP mechanism used by .NET remoting using both  .NET reflector and the rotor 2.0 implementation of CLR, I finally figure out that for the current implementation of TP and RP mechanism, it only supports asynchronous call when the default RemotingProxy is in place, since the ServiceChannelProxy is WCF’s own implementation, it gets ignored by the BeginInvoke mechanism, and the BeginInvoke call against WCF’s proxies will be performed synchronously.

This explanation was not completely clear to me, however it provided some clues to the reasons why the asynchronous call could block.

So, my next steps were to grab the SSCLI source code and analyze how BeginInvoke is implemented. My observations follow:

  1. When a compiler defines a delegate class, the BeginInvoke method does not contain any implementation. Instead, this method is annotated with the MethodImplAttribute attribute, with the MethodCodeType field set to MethodCodeType.Runtime. This means that the BeginInvoke implementation will be given by the runtime.
  2. In SSCLI, the class COMDelegate (defined in the comdelegate.h and comdelegate.cpp files) represents the native methods of the Delegate class. In this C++ class, the GetInvokeMethodStub method is used to get the stubs for each of the synchronous and asynchronous invoke methods. For the BeginInvoke method, this stub is returned by the TheAsyncDelegateStub function (defined in remoting.h).
  3. The stub returned by the TheAsyncDelegateStub method is created by the CTPMethodTable::EmitSetupFrameCode method (defined in remotingx86.h). This last method emits x86 assembly code that includes a call to the CTPMethodTable::OnCall method (defined in remoting.cpp).
  4. The CTPMethodTable::OnCall, among other things, tests if the target of the delegate is a transparent proxy.
  5. If it IS NOT a transparent proxy:
    1. the OnCall method calls the RemotingProxy.Invoke static method, which  performs the expected ThreadPool.QueueUserWorkItem call.
  6. However, if it IS a transparent proxy:
    1. the OnCall method obtains the real proxy behind the transparent proxy, and calls the RealProxy.PrivateInvoke method.
    2. This method ends up calling the virtual Invoke method of ServiceChannelFactory (the type of  real proxy behind the transparent proxy returned by a ChannelFactory<T>). This method checks if the called channels’ method is synchronous, and if so completes the call synchronously, despite the call being made via a delegate’s BeginInvoke.

So, in conclusion:

  1. A delegates’s BeginInvoke method call is handled by the remoting infrastructure. Aparently, this so to optimize the asynchronous remoting calls, avoiding extra context switchs (see this post by Chris Brumme).
  2. If the target of the delegate is not a transparent proxy, then a regular ThreadPool.QueueUserWorkItem is performed.
  3. If the target is a transparent proxy, then the BeginInvoke call is processed by the real proxy. If the delegate’s method is synchronous, then the WCF’s real proxy performs a synchronous service call.

Note, however, that an asynchronous delegate call on the synchronous method of the “client proxy” generated by svcutil.exe will not block waiting for the service’s response.  This is so because this “client proxy” is a regular class and not a transparent or real proxy, so the “normal” BeginInvoke behavior applies.

This does not mean that using asynchronous delegate calls on the synchronous “client proxy” methods is recommended. The appropriate method is to use the /async switch of the svcutil.exe tool to generate a service interface and a “client proxy” with asynchronous methods, as described in the original Nicholas Allen’s post.

The case of the missing ‘Dialect’ (epilogue)

Just a couple of concluding remarks on this series of posts.

1. Claims checking

The scenario presented in the previous posts contains a subtle flaw: the claims are being requested but not being checked by the service. Even in the first version, where the claim requirements are configured in the service’s binding, the presence of this claims in the message received by the service is not checked.

For this purpose, we must use a custom ServiceAuthorizationManager that overrides the CheckAccessCore method to check if the required claims are contained in the ServiceSecurityContext.AuthorizationContext property.

The BizTalk services SDK already contains such a class in the FederatedAccessManager sample project, so the following assignment will solve this flaw.

   1: sh.Authorization.ServiceAuthorizationManager = new System.ServiceBus.Samples.FederatedAccessManager();

 

2. The model below

The WCF platform defines a security framework based on the security model proposed by the WS-* family of specifications. It’s my opinion that platforms such as WCF simplify but do not isolate the architect/developer from this underlying model. This series of posts also aims to illustrate the importance of its knowledge.

.

The case of the missing ‘Dialect’ (part 5)

This is the fifth in a series of posts [part1, part2, part3, part4] where I describe some issues regarding the usage of claims requirements on the WCF platform.

In the last post, I described how to build a service that relies on the BizTalk Identity Services for the authorization decisions, and also how to build a client that uses this service. However, the execution of this client ended up on a “ID3037: The specified request failed.” fault returned by the BizTalk Identity Services STS.

Unfortunately this message error is not documented, so I went to analyze the message exchange between the client and the STS. For this, I used the message logging capability of WCF. I enabled the logging at service level and not at transport level, because at this level the messages are enciphered.

Here is the body of the Security Token Request message:

   1: <s:Body>
   2:    <t:RequestSecurityToken xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
   3:       <t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>
   4:       <wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
   5:          <EndpointReference xmlns="http://www.w3.org/2005/08/addressing">
   6:             <Address>http://<servicehost>:8080/saac/ep1</Address>
   7:             <Identity xmlns="http://schemas.xmlsoap.org/ws/2006/02/addressingidentity">
   8:                <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
   9:                   <X509Data>
  10:                      <X509Certificate><!--removed--></X509Certificate>
  11:                   </X509Data>
  12:                </KeyInfo>
  13:             </Identity>
  14:          </EndpointReference>
  15:       </wsp:AppliesTo>
  16:       <t:Entropy><!--Removed--></t:Entropy>
  17:       <t:TokenType>http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1</t:TokenType>
  18:       <t:KeyType>http://schemas.xmlsoap.org/ws/2005/02/trust/SymmetricKey</t:KeyType>
  19:       <t:KeySize>256</t:KeySize>
  20:       <t:EncryptWith>http://www.w3.org/2001/04/xmlenc#aes256-cbc</t:EncryptWith>
  21:       <t:SignWith>http://www.w3.org/2000/09/xmldsig#hmac-sha1</t:SignWith>
  22:       <t:CanonicalizationAlgorithm>http://www.w3.org/2001/10/xml-exc-c14n#</t:CanonicalizationAlgorithm>
  23:       <t:EncryptionAlgorithm>http://www.w3.org/2001/04/xmlenc#aes256-cbc</t:EncryptionAlgorithm>
  24:       <t:Claims>
  25:          <ClaimType Uri="http://schemas.xmlsoap.org/ws/2006/12/authorization/claims/action" xmlns="http://schemas.xmlsoap.org/ws/2006/12/authorization">
  26:             <Value></Value>
  27:          </ClaimType>
  28:       </t:Claims>
  29:       <t:ComputedKeyAlgorithm>http://schemas.xmlsoap.org/ws/2005/02/trust/CK/PSHA1</t:ComputedKeyAlgorithm>
  30:    </t:RequestSecurityToken>
  31: </s:Body>

The problems is not evident, but it is visible in the above message: the <t:Claims> element does not have the Dialect attribute.

Why wasn’t it there?

Before answering this question, let’s recall why it should be there?

Remember that the required claims are one of the service requisites expressed in the service’s policy. Namely, in the <RequestSecurityTokenTemplate>. According to the WS-SecurityPolicy spec:

This required element contains elements which MUST be copied into the request sent to the specified issuer. Note: the initiator is not required to understand the contents of this element.

So, the next step was to verify if the Dialect attribute was in the service policy. Remember, from last post, that the claims requirements were defined in an XML element inserted in the TokenRequestParameters collection.

As seen in the above fragment, the Dialect attribute is present in the service’s policy

   1: <sp:RequestSecurityTokenTemplate>
   2:    <t:TokenType xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1</t:TokenType>
   3:    <t:KeyType xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">http://schemas.xmlsoap.org/ws/2005/02/trust/SymmetricKey</t:KeyType>
   4:    <t:KeySize xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">256</t:KeySize>
   5:    <t:EncryptWith xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">http://www.w3.org/2001/04/xmlenc#aes256-cbc</t:EncryptWith>
   6:    <t:SignWith xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">http://www.w3.org/2000/09/xmldsig#hmac-sha1</t:SignWith>
   7:    <t:CanonicalizationAlgorithm xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">http://www.w3.org/2001/10/xml-exc-c14n#</t:CanonicalizationAlgorithm>
   8:    <t:EncryptionAlgorithm xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">http://www.w3.org/2001/04/xmlenc#aes256-cbc</t:EncryptionAlgorithm>
   9:    <Claims Dialect="http://schemas.xmlsoap.org/ws/2006/12/authorization/authclaims" xmlns="http://schemas.xmlsoap.org/ws/2005/02/trust">
  10:       <ClaimType Uri="http://schemas.xmlsoap.org/ws/2006/12/authorization/claims/action" xmlns="http://schemas.xmlsoap.org/ws/2006/12/authorization">
  11:          <Value/>
  12:       </ClaimType>
  13:    </Claims>
  14: </sp:RequestSecurityTokenTemplate>

Well, apparently this is a “bug” in WCF’s WSDL import process, which handles the <Claims> element differently.

What are the workarounds?

  1. One method is to intercept the token request at the client side, using a custom token provider and explicitly insert the correct claim requirements. This is what is done by some of the BizTalk services SDK samples.
  2. Another method is to change the clients’s binding (obtained via the the MetadataResolver) and insert the claims requirement. This is done in the following fragment
   1: XNamespace wst = "http://schemas.xmlsoap.org/ws/2005/02/trust";
   2: XNamespace wsf = "http://schemas.xmlsoap.org/ws/2006/12/authorization";
   3:  
   4: var claims = new XElement(wst + "Claims",
   5:     new XAttribute("Dialect", "http://schemas.xmlsoap.org/ws/2006/12/authorization/authclaims"),
   6:     new XElement(wsf + "ClaimType",
   7:         new XAttribute("Uri", "http://schemas.xmlsoap.org/ws/2006/12/authorization/claims/action"),
   8:         new XElement(wsf + "Value")
   9:     )
  10: );
  11: var xdoc = new XmlDocument();
  12: xdoc.Load(claims.CreateReader());
  13: clientBinding.Security.Message.TokenRequestParameters.Add(xdoc.DocumentElement);

In both workarounds, it is necessary to remove the original Claims element (the one imported without the Dialect attribute).

After this change everything runs well.

The case of the missing ‘Dialect’ (Part 4)

This is the fourth in a series of posts [part1, part2,part3] where I describe some issues regarding the usage of claims requirements on the WCF platform.

In the previous two posts, I presented some information regarding the BizTalk Identity Services STS.

In this post I will show how to build a minimalistic WCF service that relies on this STS for the authorization decisions. I will also show how to build a client that uses this service.

For the sake of clarity, I will use no configuration file, so everything will be done in code. 

Service

The service’s endpoint uses a WSFederationHttpBinding, configured as follows

   1: WSFederationHttpBinding binding = new WSFederationHttpBinding();
   2: binding.Security.Message.IssuedKeyType = SecurityKeyType.SymmetricKey;
   3: binding.Security.Message.IssuedTokenType = "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1";
   4: binding.Security.Message.IssuerAddress = new EndpointAddress("http://identity.biztalk.net/sts/<username>/issued_for_certificate");
   5: binding.Security.Message.IssuerMetadataAddress = new EndpointAddress("http://identity.biztalk.net/sts/<username>/mex");
  • The IssuedKeyType property is set to SecurityKeyType.SymmetricKey. This means that the proof-of-possession key will be a symmetric key (see WS-Trust for details). It also means that the STS must have the certificate of the service, in order to encipher the proof-of-possession key (see below for how to configure the STS with this certificate).
  • The IssuedTokenType property reflects the type of token issued by the STS (a version 1.1 SAML token).
  • The IssuerAddress property points to the STS endpoint that issues the required tokens. In this case, it’s the endpoint with name ‘SelfSignedSamlForCertificate’ (see part3), that accepts self-issued SAML tokens. 
  • The IssuerMetadataAddress property points to the address of the STS metadata.

Why is the IssuerAddress necessary? Namely, isn’t the IssuerMetadataAddress enough? Because, as seen in the previous part, this metadata contains several endpoints that implement the STS contract. By specifying the required endpoint’s address, this ambiguity is solved.

The previous settings define the required token type but not the required claims types. However, the desired claims dialect (“http://schemas.xmlsoap.org/ws/2006/12/authorization/authclaims“) is not directly supported by WCF, so the ClaimTypeRequirement property cannot be used. For this purpose, this requirement must be directly configured in the TokenRequestParameters collection.

   1: XNamespace wst = "http://schemas.xmlsoap.org/ws/2005/02/trust";
   2: XNamespace wsf = "http://schemas.xmlsoap.org/ws/2006/12/authorization";
   3: var claims = new XElement(wst + "Claims",
   4:    new XAttribute("Dialect", "http://schemas.xmlsoap.org/ws/2006/12/authorization/authclaims"),
   5:    new XElement(wsf + "ClaimType",
   6:       new XAttribute("Uri", "http://schemas.xmlsoap.org/ws/2006/12/authorization/claims/action"),
   7:       new XElement(wsf + "Value")
   8:    )
   9: );
  10: var xdoc = new XmlDocument();
  11: xdoc.LoadXml(claims.ToString());
  12: binding.Security.Message.TokenRequestParameters.Add(xdoc.DocumentElement);

Finally, I create a service host, add an endpoint with this binding, set the service’s certificate and enable metadata retrieval.

   1: ServiceHost sh = new ServiceHost(typeof(ServiceImpl), new Uri("http://<servicehost>:8080/saac"));
   2: sh.AddServiceEndpoint(typeof(IService), binding, "ep1");
   3: // Set the service's certificate
   4: sh.Credentials.ServiceCertificate.SetCertificate("cn=<servicehost>");
   5: // Enable metadata retrieval
   6: ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
   7: smb.HttpGetUrl = new Uri("http://<servicehost>:8080/saac/md");
   8: smb.HttpGetEnabled = true;
   9: sh.Description.Behaviors.Add(smb);
  10: sh.Open();

The <servicehost> string should be replace by the host name.

BizTalk Identity Services configuration

The following configurations are required at the BizTalk Identity Services, after login under the <username> account:

  • Manage Access Control/Relying Party: add the address of the service’s endpoint’s (http://<servicehost>:8080/saac/ep1) and the service’s certificate. This association between an address and a certificate is necessary because the STS needs the public key of the relying service to encrypt the proof-of-possession token.
  • Manage Access Control/Rules: define a claim mapping with:

Client

At the client side, I use the MetadataResolver class to dynamically build the binding and address to the service, instead of statically using the svcutil.exe tool. Just to simply the example. the interface with the service contract is shared between the service and the client.

   1: ServiceEndpointCollection sec = MetadataResolver.Resolve(
   2:    typeof(IService),
   3:    new Uri("http://<servicehost>:8080/saac/md"),
   4:    MetadataExchangeClientMode.HttpGet);
   5: ServiceEndpoint sep = sec[0];
   6: WSFederationHttpBinding clientBinding = sep.Binding as WSFederationHttpBinding;

Then I create a ChannelFactory<T>, using the resolved binding and address, set the client certificate authentication details (PeerTrust because the service’s certificate is “home made”), create a binding and call the service’s operation.

   1: ChannelFactory<IService> cf = new ChannelFactory<IService>(clientBinding, sep.Address);
   2: cf.Credentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.PeerTrust;
   3: cf.Credentials.ServiceCertificate.Authentication.RevocationMode = X509RevocationMode.NoCheck;
   4: IService ch = cf.CreateChannel();
   5: Console.WriteLine(ch.Operation("hello"));

Running the scenario

When I first ran this scenario, the CardSpace UI popped up, because the STS requires a SAML token but does not point to the metadata of its issuer. Then I selected the card that I registered in BizTalk Services, waited a couple of seconds for the client to request the authorization token and got a “ID3037: The specified request failed.” fault exception.

Why? Well, that’s the subject of the next post of this series.

The case of the missing ‘Dialect’ (part 3)

This is the third in a series of posts [first, second] where I describe some issues regarding the definition and usage of claim requirements on the WCF platform.

In the last post, I introduced the BizTalk Identity Services as an example of an publicly available STS. In this post I will describe some aspects of the metadata (WSDL based description) exposed by this STS.

Recall that this metadata can be retrieved at: http://identity.biztalk.net/sts/<username>/sts.wsdl

where <username> is the registered used name.

Beginning at the end (<wsdl:service> element), the service exposes 5 endpoints (<wsdl:port> elements) with the following names:

  • ‘UserNameForCertificate’
  • ‘SelfSignedSamlForCertificate’
  • ‘TgtSamlForCertificate’
  • ‘AnySamlForCertificate’
  • ‘MutualCertificateForCertificate’
   1: <wsdl:service name="SecurityTokenService">
   2:     <wsdl:port name="UserNameForCertificate" binding="tns:UserNameForCertificate">
   3:       <soap12:address location="http://identity.biztalk.net/sts/<username>/username_for_certificate"/>
   4:       <wsa10:EndpointReference>
   5:         <wsa10:Address>http://identity.biztalk.net/sts/<username>/username_for_certificate</wsa10:Address>
   6:         <Identity xmlns="http://schemas.xmlsoap.org/ws/2006/02/addressingidentity">
   7:           <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
   8:             <X509Data>
   9:               <X509Certificate>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</X509Certificate>
  10:             </X509Data>
  11:           </KeyInfo>
  12:         </Identity>
  13:       </wsa10:EndpointReference>
  14:     </wsdl:port>
  15:     <wsdl:port name="SelfSignedSamlForCertificate" binding="tns:SelfSignedSamlForCertificate">
  16:       <soap12:address location="http://identity.biztalk.net/sts/<username>/issued_for_certificate"/>
  17:       <wsa10:EndpointReference>
  18:         <wsa10:Address>http://identity.biztalk.net/sts/<username>/issued_for_certificate</wsa10:Address>
  19:         <Identity xmlns="http://schemas.xmlsoap.org/ws/2006/02/addressingidentity">
  20:           <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
  21:             <X509Data>
  22:               <X509Certificate>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</X509Certificate>
  23:             </X509Data>
  24:           </KeyInfo>
  25:         </Identity>
  26:       </wsa10:EndpointReference>
  27:     </wsdl:port>
  28:     <wsdl:port name="TgtSamlForCertificate" binding="tns:TgtSamlForCertificate">
  29:       <soap12:address location="http://identity.biztalk.net/sts/<username>/tgt_for_certificate"/>
  30:       <wsa10:EndpointReference>
  31:         <wsa10:Address>http://identity.biztalk.net/sts/<username>/tgt_for_certificate</wsa10:Address>
  32:         <Identity xmlns="http://schemas.xmlsoap.org/ws/2006/02/addressingidentity">
  33:           <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
  34:             <X509Data>
  35:               <X509Certificate>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</X509Certificate>
  36:             </X509Data>
  37:           </KeyInfo>
  38:         </Identity>
  39:       </wsa10:EndpointReference>
  40:     </wsdl:port>
  41:     <wsdl:port name="AnySamlForCertificate" binding="tns:AnySamlForCertificate">
  42:       <soap12:address location="http://identity.biztalk.net/sts/<username>/saml_for_certificate"/>
  43:       <wsa10:EndpointReference>
  44:         <wsa10:Address>http://identity.biztalk.net/sts/<username>/saml_for_certificate</wsa10:Address>
  45:         <Identity xmlns="http://schemas.xmlsoap.org/ws/2006/02/addressingidentity">
  46:           <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
  47:             <X509Data>
  48:               <X509Certificate>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</X509Certificate>
  49:             </X509Data>
  50:           </KeyInfo>
  51:         </Identity>
  52:       </wsa10:EndpointReference>
  53:     </wsdl:port>
  54:     <wsdl:port name="MutualCertificateForCertificate" binding="i1:MutualCertificateForCertificate">
  55:       <soap12:address location="http://identity.biztalk.net/sts/<username>/certificate"/>
  56:       <wsa10:EndpointReference>
  57:         <wsa10:Address>http://identity.biztalk.net/sts/<username>/certificate</wsa10:Address>
  58:         <Identity xmlns="http://schemas.xmlsoap.org/ws/2006/02/addressingidentity">
  59:           <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
  60:             <X509Data>
  61:               <X509Certificate>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</X509Certificate>
  62:             </X509Data>
  63:           </KeyInfo>
  64:         </Identity>
  65:       </wsa10:EndpointReference>
  66:     </wsdl:port>
  67:   </wsdl:service>

All of these endpoints expose the same Security Token Service contract, defined by the WS-Trust (Feb. 2005 version) spec.

   1: <wsdl:portType name="SecurityTokenService">
   2:     <wsdl:operation name="RequestSecurityToken">
   3:       <wsdl:input wsaw:Action="http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue" name="RequestSecurityTokenMsg" message="tns:RequestSecurityTokenMsg"/>
   4:       <wsdl:output wsaw:Action="http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/Issue" name="RequestSecurityTokenResponseMsg" message="tns:RequestSecurityTokenResponseMsg"/>
   5:     </wsdl:operation>
   6: </wsdl:portType>

The principal difference between these endpoints is their policy, referenced by the <wsdl:binding> elements associated to each endpoint. Namely, each policy requires a different token type and claims types in the token request message. This difference is visible in the <sp:SignedSupportingTokens> element.

For instance, the policy of the ‘UserNameForCertificate‘ endpoint requires an UsernameToken.

   1: <sp:SignedSupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
   2:    <wsp:Policy>
   3:       <sp:UsernameToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
   4:          <wsp:Policy>
   5:            <sp:WssUsernameToken10/>
   6:          </wsp:Policy>
   7:       </sp:UsernameToken>
   8:    </wsp:Policy>
   9: </sp:SignedSupportingTokens>

The ‘SelfSignedSamlForCertificate‘ endpoint’s policy requires a SAML v1.1 token with the Private Personal Identifier claim.

   1: <sp:IssuedToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
   2:    <sp:RequestSecurityTokenTemplate>
   3:       <t:TokenType xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1</t:TokenType>
   4:       <t:KeyType xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">http://schemas.xmlsoap.org/ws/2005/02/trust/SymmetricKey</t:KeyType>
   5:       <t:Claims xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
   6:          <wsid:ClaimType Uri="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier" xmlns:wsid="http://schemas.xmlsoap.org/ws/2005/05/identity"/>
   7:       </t:Claims>
   8:    </sp:RequestSecurityTokenTemplate>
   9: </sp:IssuedToken>

 

The ‘…ForCertificate’ suffix, present in all endpoint’s names, means that the messages are protected using a X.509 certificate based scheme. This requirement is expressed by the <sp:ProtectionToken> assertion, present in all policies.

   1: <sp:ProtectionToken>
   2:    <wsp:Policy>
   3:       <sp:X509Token sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/Never">
   4:          <wsp:Policy>
   5:             <sp:RequireDerivedKeys/>
   6:             <sp:RequireThumbprintReference/>
   7:             <sp:WssX509V3Token10/>
   8:          </wsp:Policy>
   9:       </sp:X509Token>
  10:    </wsp:Policy>
  11: </sp:ProtectionToken>

So, the existence of multiple endpoints for the same contract, each with a different policy, allows for different token and claim types to be used with the same STS.

Notice that this metadata describes the STS requirements (required token and claims types) but not its capabilities (issued token and claims types). This type of capabilities are not addressed by the WS-SecurityPolicy language. Instead, they belong to the federation metadata model defined in the (still not very used) WS-Federation spec. However, to the best of my knowledge, the BizTalk Identity Services don’t expose this type of metadata, so these capabilities must be acquired out-of-band.

 

In the next post, I will show how to create a WCF service that relies on this STS for the authorization decisions. I will also show how to build a client that uses this service.

The case of the missing ‘Dialect’ (part 2)

This is the second post of a series where I describe some issues regarding the definition and usage of claim requirements on the Windows Communication Foundation (WCF) platform. On the first post, I introduced the concept of claim requirements, and how to express them in WS-Policy and WCF. In this post I begin to introduce a usage scenario.

BizTalk Identity Services

(disclaimer: the information below refers to Community Technological Preview, so things will probably change in the future)

Among several other things, BizTalk Services provides a publicly-accessible STS for each registered user. This STS can play two different roles: Identity Provider or Resource side STS (R-STS). In the later role, this STS act as a Policy Decision Point (PDP), responsible for evaluating the service’s access control policy,

  1. First, it receives a token request from the service’s client with:
    • A description of the required authorization claims
    • The claims of the requestor
    • The address of the target service
  2. Then, it evaluates the service’s policy using the above input information.
  3. Finally, if the authorization claims are granted by the authorization policy, it issues a token with them to the requestor.

This R-STS can be used by:

  • Services with endpoints “hosted” by BizTalk Connectivity Services. In addition to the connectivity functionality, BizTalk Connectivity Services also plays the role of a Policy Enforcement Point, verifying if the messages received by the “hosted” endpoint contain security tokens with the required authorization claims.
  • Independent (“stand alone”) services, that is, services not hosted by BizTalk Services. In this case, the policy enforcement must be done by the service.

The policy of a BizTalk Services STS is defined by a set of rules. Each rule defines a mapping between one or more input claims (claims of the token requestor) and an output claim (claim present in the issued token). When playing the role of an R-STS, these output claims belong to the authorization dialect defined by WS-Federation (see last post).

The metadata of the STS is available at the following addresses:

where <username> should be replaced by the user’s name (remember that there is an STS for each registered user).

Observing the contents of this metadata (just register with BizTalk Services and point a browser to the above address) is a rather educative experience, that will be the subject of the next post in this series.

The case of the missing ‘Dialect’ (Part 1)

This is the first post of a series where I describe some issues regarding the definition and usage of claim requirements on the Windows Communication Foundation (WCF) platform.

Introduction

The constraints and requirements of a WCF service can be expressed by a policy, defined according to the WS-Policy spec framework. Typically, this policy is automatically generated from the endpoint’s binding information and embedded into the service’s WSDL.

A policy is composed by assertions, that define specific constraints and requirements. The WS-SecurityPolicy spec defines a set of security specific assertions. One of those is the <IssuedToken> assertion, that is used by services to require security tokens issued by token issuers. The “parameters” of this assertion include:

  • An endpoint reference to the token issuer, optionally including the issuer’s address and metadata location
  • A set of elements that should be present in the request made by the client to the issuer. These elements, defined by the WS-Trust specs, define aspects such as:
    • The requested token and key types.
    • The required claims – claims that should be present in the issued token.

The required claims are defined by the <Claims> element, present inside the <IssuedToken> assertion and on the request sent by the client to the token issuer. This <Claims> element supports different ways of expressing the claims requirements. For that purpose, it contains a Dialect attribute (an URI) indicating the specific language used inside the <Claims> element.

The WS-Federation spec (version 1.1) defines a specific dialect for expressing authorization claims, depicted in the following XML

1: <wst:Claims

2:        Dialect=”http://schemas.xmlsoap.org/ws/2006/12/authorization/authclaims”>

3:    <auth:ClaimType Uri=“xs:anyURI” Optional=“xs:boolean”>

4:       (<auth:Value>…</auth:Value> | xs:any) ?

5:    </auth:ClaimType> *

6: </wst:Claims>

The Information Card Profile also defines a claim dialect where a required claim is represented by a <ClaimType> element:

1: <wst:Claims Dialect=”http://schemas.xmlsoap.org/ws/2005/05/identity”>

2:    <ic:ClaimType Uri=”http://…/ws/2005/05/identity/claims/givenname”/>

3:    <ic:ClaimType Uri=”http://…/ws/2005/05/identity/claims/surname”

4:       Optional=”true” />

5: </wst:Claims>

WCF directly supports this last dialect via the Security.Message.ClaimTypeRequirements property of both WFederationHttpBinding and WS2007FederationHttpBinding. This property represents a collection of ClaimTypeRequirement, where the claim types required by the service can be added.

In principle, it is also possible to use another dialect with WCF. In WS-SecurityPolicy, the <Claims> element is contained inside the <RequestSecurityTokenTemplate> element, which can be populated via the Security.Message.TokenRequestParameters property of any federation binding. This property represents the collection of XmlElement that are childs of the <RequestSecurityTokenTemplate>.