Only showing posts tagged with "WCF"
March 24, 2010 2:43 PM by Daniel Chambers (last modified on June 07, 2010 3:35 PM)
After a hell of a lot of work, I am happy to announce that the 1.0.0 version of DigitallyCreated Utilities has been released! DigitallyCreated Utilities is a collection of many neat reusable utilities for lots of different .NET technologies that I’ve developed over time and personally use on this website, as well as on others I have a hand in developing. It’s a fully open source project, licenced under the Ms-PL licence, which means you can pretty much use it wherever you want and do whatever you want to it. No viral licences here.
The main reason that it has taken me so long to release this version is because I’ve been working hard to get all the wiki documentation on CodePlex up to scratch. After all, two of the project values are:
And truly, nothing is more frustrating than code with bad documentation. To me, bad documentation is the lack of a unifying tutorial that shows the functionality in action, and the lack of decent XML documentation on the code. Sorry, XMLdoc that’s autogenerated by tools like GhostDoc, and never added to by the author, just doesn’t cut it. If you can auto-generate the documentation from the method and parameter names, it’s obviously not providing any extra value above and beyond what was already there without it!
So what does DCU v1.0.0 bring to the table? A hell of a lot actually, though you may not need all of it for every project. Here’s the feature list grouped by broad technology area:
DCU is split across six different assemblies so that developers can pick and choose the stuff they want and not take unnecessary dependencies if they don’t have to. This means if you don’t use Unity in your application, you don’t need to take a dependency on Unity just to use the Error Reporting functionality.
I’m really pleased about this release as it’s the culmination of rather a lot of work on my part that I think will help other developers write their applications more easily. I’m already using it here on DigitallyCreated in many many places; for example the Error Reporting code tells me when this site crashes (and has been invaluable so far), the CompiledQueryReplicator helps me use compiled queries effectively on the back-end, and the ReaderWriterLock is used behind the scenes for the Twitter feed on the front page.
I hope you enjoy this release and find some use for it in your work or play activities. You can download it here.
March 05, 2010 3:37 AM by Daniel Chambers (last modified on March 05, 2010 3:49 AM)
While working with WCF for my part time job, I came across this page on MSDN that condemned the C# using block as unsafe to use when working with a WCF client. The problem is that the using block can silently swallow exceptions without you even knowing. To prove this, here’s a small sample:
public static void Main() { try { using (new CrashingDisposable()) { throw new Exception("Inside using block"); } } catch (Exception e) { Console.WriteLine("Caught exception: " + e.Message); } } private class CrashingDisposable : IDisposable { public void Dispose() { throw new Exception("Inside Dispose"); } }
The above program will write “Caught exception: Inside Dispose” to the console. But where did the “Inside using block” exception go? It was swallowed by the using block! How this happens is more obvious when you unroll the using block into the try/finally block that it really is (note the outer braces that limit crashingDisposable’s scope):
{ CrashingDisposable crashingDisposable = new CrashingDisposable(); try { throw new Exception("Inside using block"); } finally { if (crashingDisposable != null) ((IDisposable)crashingDisposable).Dispose(); //Dispose exception thrown here } }
As you can see, the “Inside using block” exception is lost entirely. A reference to it isn’t even present and the exception from the Dispose call is the one that gets thrown up.
So, how does this affect you in WCF? Well, when a WCF client is disposed it is closed, which may throw an exception. So if, while using your client object, you encounter an exception that escapes the using block, the client will be disposed and therefore closed, which could throw an exception that will hide the original exception. That’s just bad for debugging.
This is obviously undesirable behaviour, so I’ve written a construct that I’ve dubbed a “Safe Using Block” that stops the exception thrown in the using block from being lost. Instead, the safe using block gathers both exceptions together and throws them up inside an AggregateException (present in DigitallyCreated.Utilities.Bcl, but soon to be found in .NET 4.0) Here’s the above using block rewritten as a safe using block:
new CrashingDisposable().SafeUsingBlock(crashingDisposable => { throw new Exception("Inside using exception"); });
When this code runs an AggregateException is thrown that contains both the “Inside using exception” exception and the “Dispose” exception. So how does this work? Here’s the code:
public static void SafeUsingBlock<TDisposable>(this TDisposable disposable, Action<TDisposable> action) where TDisposable : IDisposable { try { action(disposable); } catch (Exception actionException) { try { disposable.Dispose(); } catch (Exception disposeException) { throw new DigitallyCreated.Utilities.Bcl.AggregateException(actionException, disposeException); } throw; } disposable.Dispose(); //Let it throw on its own }
SafeUsingBlock is defined as an extension method off any type that implements IDisposable. It takes an Action delegate, which represents the code to run inside the “using block”. Since the method uses generics, the Action delegate is handed the concrete type of IDisposable you created, not just an abstract IDisposable.
You can use a safe using block in a very similar fashion to a normal using block, except for one key thing: goto-style statements won’t work. So for example, you can’t use return, break, continue, etc inside the safe using block and expect it to affect the method outside. You must keep in mind that you’re writing inside a new anonymous method, not inside a code block.
SafeUsingBlock is part of DigitallyCreated Utilities, however, it is currently only available in the trunk repository, not as a part of a release. Once I’m done working on the documentation, I’ll put it out in a full release.
June 10, 2009 2:00 PM by Daniel Chambers
Let's say you've got a web service that exposes data (we could hardly say that you didn't! :D). This particular data always relates to a particular user; for example, financial transactions are always viewed from the perspective of the "user". If it's me, it's my transactions. If it's you, it's your transactions. This means every call to the web service needs to identify who the user is (or you can use a session, but let's put that idea aside for now).
However, lets also say that these calls are "on behalf" of the user and not from them directly. So we need a way of authenticating who is putting the call through on behalf of the user.
This scenario can occur in a user-centric web application, where the web application runs on its own server and talks to a business service on a separate server. The web application server talks on behalf of the user with the business server.
So wouldn't it be nice if we could do the following with the WCF service that enables the web application server to talk to the business server: authenticate the user at the message level using their username and password and authenticate the web application server at the transport level by checking its certificate to ensure that it is an expected and trusted server?
Currently in WCF the out-of-the-box bindings net.tcp and WSHttp offer authentication at either message level or the transport level, but not both. TransportWithMessageCredential security is exactly that: transport security (encryption) with credentials at the message level. So how can we authenticate at both the transport and message level then?
The answer: create a custom binding (note: I will focus on using the net.tcp binding as a base here). I found the easiest way to do this is to continue doing your configuration in the XML, but at runtime copy and slightly modify the netTcp binding from the XML configuration. There is literally one switch you need to enable. Here's the code on the service side:
ServiceHost businessHost = new ServiceHost(typeof(DHTestBusinessService)); ServiceEndpoint endpoint = businessHost.Description.Endpoints[0]; BindingElementCollection bindingElements = endpoint.Binding.CreateBindingElements(); SslStreamSecurityBindingElement sslElement = bindingElements.Find<SslStreamSecurityBindingElement>(); //Turn on client certificate validation sslElement.RequireClientCertificate = true; CustomBinding newBinding = new CustomBinding(bindingElements); NetTcpBinding oldBinding = (NetTcpBinding)endpoint.Binding; newBinding.Namespace = oldBinding.Namespace; endpoint.Binding = newBinding;
Note that you need to run this code before you Open() on your ServiceHost.
You do exactly the same thing on the client side, except you get the ServiceEndpoint in a slightly different manner:
DHTestBusinessServiceClient client = new DHTestBusinessServiceClient(); ServiceEndpoint endpoint = client.Endpoint; //Same code as the service goes here
You'd think that'd be it, but you'd be wrong. :) This is where it gets extra lame. You're probably attributing your concrete service methods with PrincipalPermission to restrict access based on the roles of the service user, like this:
[PrincipalPermission(SecurityAction.Demand, Role = "MyRole")]
This technique will start failing once you apply the above changes. The reason is because the user's PrimaryIdentity (which you get from OperationContext.Current.ServiceSecurityContext.PrimaryIdentity) will end up being an unknown, username-less, unauthenticated IIdentity. This is because there are actually two identities representing the user: one for the X509 certificate used to authenticate over Transport, and one for the username and password credentials used to authenticate at Message level. When I reverse engineered the WCF binaries to see why it wasn't giving me the PrimaryIdentity I found that it has an explicit line of code that causes it to return that empty IIdentity if it finds more than one IIdentity. I guess it's because it's got no way to figure out which one is the primary one.
This means using the PrincipalPermission attribute is out the window. Instead, I wrote a method to mimic its functionality that can deal with multiple IIdentities:
private void AssertPermissions(IEnumerable<string> rolesDemanded) { IList<IIdentity> identities = OperationContext.Current.ServiceSecurityContext.AuthorizationContext.Properties["Identities"] as IList<IIdentity>; if (identities == null) throw new SecurityException("Unauthenticated access. No identities provided."); foreach (IIdentity identity in identities) { if (identity.IsAuthenticated == false) throw new SecurityException("Unauthenticated identity: " + identity.Name); } IIdentity usernameIdentity = identities.Where(id => id.GetType().Equals(typeof(GenericIdentity))) .SingleOrDefault(); string[] userRoles = Roles.GetRolesForUser(usernameIdentity.Name); foreach (string demandedRole in rolesDemanded) { if (userRoles.Contains(demandedRole) == false) throw new SecurityException("Access denied: authorisation failure."); } }
It's not pretty (especially the way I detect the username/password credential IIdentity), but it works! Now, at the top of your service methods you need to call it like this:
AssertPermissions(new [] {"MyRole"});
Ensure that your client is providing a client certificate to the server by setting the client certificate element in your XML config under an endpoint behaviour's client credentials section:
<clientCertificate storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectDistinguishedName" findValue="CN=mycertficatename"/>
Now, I mentioned earlier that the business web service should be authenticating the web application server clients using these provided certificates. You could use chain trust (see the Chain Trust and Certificate Authorities section of this page for more information) to accept any client that was signed by any of the default root authorities, but this doesn't really provide exact authentication as to who is allowed to connect. This is because any server that has a certificate that is signed by any trusted authority will authenticate fine! What you need is to create your own certificate authority and issue your own certificates to your clients (I covered this process in a previous blog titled "Using Makecert to Create Certificates for Development").
However, to get WCF to only accept clients signed by a specific authority you need to write your own certificate validator to plug into the WCF service. You do this by inheriting from the X509CertificateValidator class like this:
public class DHCertificateValidator : X509CertificateValidator { private static readonly X509CertificateValidator ChainTrustValidator; private const X509RevocationMode ChainTrustRevocationMode = X509RevocationMode.NoCheck; private const StoreLocation AuthorityCertStoreLocation = StoreLocation.LocalMachine; private const StoreName AuthorityCertStoreName = StoreName.Root; private const string AuthorityCertThumbprint = "e12205f07ce5b101f0ae8f1da76716e545951b22"; static DHCertificateValidator() { X509ChainPolicy policy = new X509ChainPolicy(); policy.RevocationMode = ChainTrustRevocationMode; ChainTrustValidator = CreateChainTrustValidator(true, policy); } public override void Validate(X509Certificate2 certificate) { ChainTrustValidator.Validate(certificate); X509Store store = new X509Store(AuthorityCertStoreName, AuthorityCertStoreLocation); store.Open(OpenFlags.ReadOnly); X509Certificate2Collection certs = store.Certificates.Find(X509FindType.FindBySubjectDistinguishedName, certificate.IssuerName.Name, true); if (certs.Count != 1) throw new SecurityTokenValidationException("Cannot find the root authority certificate"); X509Certificate2 rootAuthorityCert = certs[0]; if (String.Compare(rootAuthorityCert.Thumbprint, AuthorityCertThumbprint, true) != 0) throw new SecurityTokenValidationException("Not signed by our certificate authority"); store.Close(); } }
As you can see, the class re-uses the WCF chain trust mechanism to ensure that the certificate still passes chain trust requirements. But it then goes a step further and looks up the issuing certificate in the computer's certificate repository to ensure that it is the correct authority. The "correct" authority is defined by the certificate thumbprint defined as a constant at the top of the class. You can get this from any certificate by inspecting its properties. (As an improvement to this class, it might be beneficial for you to replace the constants at the top of the class with configurable options dragged from a configuration file).
To configure the WCF service to use this validator you need to set the some settings on the authentication element in your XML config under the service behaviour's service credential's client certificate section, like this:
<authentication certificateValidationMode="Custom" customCertificateValidatorType="DigitallyCreated.DH.Business.DHCertificateValidator, MyAssemblyName" trustedStoreLocation="LocalMachine" revocationMode="NoCheck" />
And that's it! Now you are authenticating at transport level as well as at message level using certificates and usernames and passwords!
This post was derived from my question at StackOverflow and the answer that I researched up and posted (to answer my own question). See the StackOverflow question here.
June 09, 2009 3:00 PM by Daniel Chambers
Programming to an interface and not an implementation is one of the big object-oriented design principles. So, when working with a web service client auto-generated by WCF, you will want to program to the service interface rather than the client class. However, as it currently stands this is made a little awkward.
Why? Because the WCF service client class is IDisposable and therefore needs to be explicitly disposed after you've finished using it. The easiest way to do this in C# is to use a using block. A using block takes an IDisposable, and when the block is exited, either by exiting the block normally, or if you quit it early by throwing an exception or something similar, it will automatically call Dispose() on your IDisposable.
The problem lies in the fact that, although the WCF service client implements IDisposable, the service interface does not. This means you either have to cast to the concrete client type and call Dispose() or you have to manually check to see whether the service-interfaced object you posses is IDisposable and if it is then Dispose() it. That is obviously a clunky and error-prone way of doing it.
Here's the way I solved the problem. It's not totally pretty, but it's a lot better than doing the above hacks. Firstly, because you are programming to an abstract interface, you need to have a factory class that creates your concrete objects. This factory returns the concrete client object wrapped in a DisposableWrapper. DisposableWrapper is a generic class I created that aids in abstracting away whether or not the concrete class is IDisposable or not. Here's the code:
public class DisposableWrapper<T> : IDisposable { private readonly T _Object; public DisposableWrapper(T objectToWrap) { _Object = objectToWrap; } public T Object { get { return _Object; } } public void Dispose() { IDisposable disposable = _Object as IDisposable; if (disposable != null) disposable.Dispose(); } }
The service client factory method that creates the service looks like this:
public static DisposableWrapper<IAuthAndAuthService> CreateAuthAndAuthService() { return new DisposableWrapper<IAuthAndAuthService>(new AuthAndAuthServiceClient()); }
Then, when you use the factory method, you do this:
using (DisposableWrapper<IAuthAndAuthService> clientWrapper = ServiceClientFactory.CreateAuthAndAuthService()) { IAuthAndAuthService client = clientWrapper.Object; //Do your work with the client here }
As you can see, the factory method returns the concrete service client wrapper in a DisposableWrapper, but exposed as the interface because it the interface type as the generic type for DisposableWrapper. You call the factory method and use its resulting DisposableWrapper inside your using block. The DisposableWrapper ensures that the object it wraps, if it is indeed IDisposable, is disposed when it itself is disposed by the using block. You can get the client object out of the wrapper, but as the service interface type and not the concrete type, which ensures you are programming to the interface and not the implementation.
All in all, it's a fairly neat way to program against a service interface, while still retaining the ability to Dispose() the service client object.