Tag Archives: WCF

Claims and claims sets in WCF

How are claims represented in WCF?

As described in an earlier post, the Identity Metasystem proposes a model where identities are defined by claim sets.

The WCF platform adopts this view and provides a claims-based authentication model, mostly defined in the System.IdentityModel.dll assembly, introduced with .NET 3.0.

In both the Identity Metasystem and the WS-* specifications, the claim concept is kept rather abstract.

The model defined by the System.IdentityModel assembly concretizes this concept through a class model presented in the next figure

claims.old

A claim, represented by the Claim class, is defined as:

A claim is the expression of a right with respect to a particular value. A right could be read, write, or possess. A value could be a database, a file, a mailbox, or a property. Claims also have a claim type

The main properties of this class are

  • ClaimType, defining the type of the claim. For examples of claim types, see the ClaimTypes class.
  • Resource, defining the value of the claim.
  • Right, defining the right associated with the claim.

At first, I found this new definition hard to grasp and not completely in synch with the definition in the Identity Metasystem. However, in practice, the only used rights are:

  • PossessProperty – “specifies that the right represents a property that the entity associated with a claim possesses“, that is, the claim represents a property.
  • Identity – “specifies that the right represents an identity“. This right defines a property that uniquely identifies an entity.

What are claim sets?

Claims are grouped in claim sets, represented by the ClaimSet class. All the claims in a claim set must have the same issuer, which is recursively represented by a claim set (see the Issuer property of the ClaimSet class). This shouldn’t be a surprise, since in this model all identities are represented by claim sets.

How are claim sets accessible?

In WCF, the claim sets associated with a given context are accessible via an instance of AuthorizationContext, present as the a property of the current ServiceSecurityContext.

These claim sets are computed based on the security tokens attached to messages and also on external policies. The details of this process will be the subject of future posts.

WCF and the AsyncPattern property (part 3)

This is the third in a series of posts about the AsyncPattern in WCF.

The previous two posts described the purpose and usage of this property on the service side. The present post addresses the client side.

AsyncPattern at the client side

The AsyncPattern=true is used at the client side to expose an asynchronous programmatic interface to a service operation. Similarly to what happens at the service side, this property defines the local communication pattern between the service’s client code and the WCF runtime (at the client side).

Consider the following WSDL excerpt defining a portType with two request-response operations

   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>

By default, the interface generated by svcutil.exe has a synchronous interface

   1: public interface IService {
   2:         
   3:     [System.ServiceModel.OperationContractAttribute(Action=".../Operation1", ReplyAction=".../Operation1Response")]
   4:     ReplyData Operation1(RequestData rd);
   5:         
   6:     [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService/Operation2", ReplyAction="http://tempuri.org/IService/Operation2Response")]
   7:     ReplyData Operation2(RequestData rd);
   8:  
   9: }

However, using the /async switch, the svcutil.exe can also generate an interface with synchronous and asynchronous methods.

   1: public interface IService {
   2:     
   3:     // Operation 1 synchronous method   
   4:     [System.ServiceModel.OperationContractAttribute(Action=".../Operation1", ReplyAction=".../Operation1Response")]
   5:     ReplyData Operation1(RequestData rd);
   6:  
   7:     // Operation 1 asynchronous method pair         
   8:     [System.ServiceModel.OperationContractAttribute(AsyncPattern=true, Action=".../Operation1", ReplyAction=".../Operation1Response")]
   9:     System.IAsyncResult BeginOperation1(RequestData rd, System.AsyncCallback callback, object asyncState);        
  10:     ReplyData EndOperation1(System.IAsyncResult result);
  11:         
  12:     // Operation 2 synchronous method   
  13:     [System.ServiceModel.OperationContractAttribute(Action=".../Operation2", ReplyAction=".../Operation2Response")]
  14:     ReplyData Operation2(AsyncPattern.Client.AsyncClient.RequestData rd);
  15:         
  16:     // Operation 2 asynchronous method pair         
  17:     [System.ServiceModel.OperationContractAttribute(AsyncPattern=true, Action=".../Operation2", ReplyAction=".../Operation2Response")]
  18:     System.IAsyncResult BeginOperation2(RequestData rd, System.AsyncCallback callback, object asyncState);        
  19:     ReplyData EndOperation2(System.IAsyncResult result);
  20:     
  21: }

Note that:

  • This setting does not change the communication pattern between the client and the service.
  • Using AsyncPattern=true at the client side is not in any way related to using AsyncPattern=true at the service side (the service doesn’t even have to implemented over WCF!)

AsyncPattern=true versus BeginInvoke

As stated here, using the delegate’s BeginInvoke method is not a way to achieve the same effect as AsyncPattern=true.

Namely:

  • If the delegate target is a client channel instance (returned by a ChannelFactory), then the call will block (as described in a previous post).

 

  • If the delegate target is a “client proxy” (ClientBase derived class generated by svcutil.exe), then the call will not block. However a thread will remain blocked until the reply is received (the thread from the thread pool used to call the asynchronous method). This does not happens when using AsyncPattern=true, since the WCF supports full asynchronous requests.
    The blocking of this thread may not be significant on a smart client scenario. However, this “thread consumption” may be problematic on a middle-tier scenario, where a significant amount of requests may be pending at a given moment in time.

WCF and the AsyncPattern property (part 2)

This is the second in a series of posts about the AsyncPattern in WCF.

The previous post described the consequences of setting AsyncPattern = true on an OperationContractAttribute.

However, a question still remains: when and how to use AsyncPattern = true on the service-side?

When?

  • The WCF documentation states that

Use an asynchronous approach in a service operation implementation if the operation service implementation makes a blocking call, such as doing I/O work. When you are in an asynchronous operation implementation, try to call asynchronous operations and methods to extend the asynchronous call path as far as possible

  • Similarly, Kenny Wolf (from the WCF/WF group) states that

If you have an operation that is blocking (accessing SQL, Channels, etc) then you should use AsyncPattern=true.  That way you’ll free up whatever thread we’re using to call your operation from

      and also that

If you aren’t doing something that’s “natively async”, then you shouldn’t be using AsyncPattern=true. That is, you shouldn’t just create a thread just for the sake of performing “background work” as part of an asynchronous operation

My conjecture is that asynchronous operation implementation should be used when there are conditions to release the calling thread, without requiring the creation of a new thread, and the time needed for the operation completion is significant. This happens when the operation performs “lengthy” IO requests. If the IO interface has an asynchronous interface, then the asynchronous operation call can be “linked” to the asynchronous IO call (see diagram below). Note that a service request is just a special kind of an IO request and that WCF also provides an asynchronous interface for clients.

 How?

The following sequence diagram shows the “linkage” between the asynchronous operation implementation and an asynchronous IO request.

AsyncPattern

  1. The WCF dispatcher calls the BeginOperation method, which in turn starts the asynchronous IO request (BeginIO) and returns immediately,. This sequence is done on an IO thread, which is “released” after BeginOperation returns.
  2. When the IO request is completed, the Operation Callback is called on an IO thread (not necessarily the same from the above sequence). This callback:
    1. Calls EndIO to finish the IO request and collects the IO result.
    2. Calls the WCF provided callback (passed as a parameter to BeginOperation).
    3. The WCF callback then calls EndOperation to finish the operation and collect the operation result.

Notice that the operation’s execution is divided into two sequences (two threads):

  • The “left-to-right” sequence processes the request, running on the IO thread associated with the service request.
  • The “right-to-left” sequence produces the reply, running on the IO thread associated with the IO request completion.

Namely there is no blocked thread between the start of the operation and the completion of the IO. This property is important in scenarios were there can be a significant amount of operations waiting for “lengthy” IO requests (e.g. middle-tier services).

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.