Skip to main content

Enabling Custom Username/Password Authentication WCF in IIS

A couple of posts back I was bemoaning the inability to use custom username/password authentication for all endpoints (WsHttp, BasicHttp and WebHttp) for a WCF service hosted in IIS.  The problem arises when you get to the WebHttp binding, because you can’t use message-level authentication (since it’s just a JSON packet), therefore you have to use Transport-level authentication.  Then you get to the biggest issue - that using Transport-level means having to use Basic/Windows/Digest authentication and IIS always automatically intercepts those authentication headers and attempts to authenticate to the server’s default windows account store (typically the domain it’s on, or it’s own local user store).

In this case, even if you configure your Custom UserName Password validator, it’ll never fire.

My solution to do a full, roll-your-own solution using Message Inspectors etc.  This still wouldn’t have solved the JSON problem fully, but it did mean that I could use my own Http headers to transmit my secure credentials.

I had a thought, though – what if IIS’ authentication could be extended, so that Basic authentication headers could be used on a per-endpoint basis (meaning that I was still free to use message-level for SOAP and Ws-Http if need-be)?

My initial google results were poor, and so I decided to use the MSDN Forums to get some ideas.  Needless to say – the answer that Marco Zhou has been exactly the thing I was looking.  All I did was to download the source for the excellent CustomBasicAuth project from CodePlex, and by following Dominick’s walkthrough was then able to extrude my own implementation that I could then plug into any WCF service.

The extra upshot of doing all this was that I can now use Role-based security on all my WCF methods, and the client just has to know how to send the credentials according to the type of endpoint they are using.  With the JSON endpoints I’m using the trick I posted earlier on how to intercept web service calls from Asp.Net Ajax client code in order to inject extra headers, but with the SOAP endpoints (currently from Silverlight) I’m using message-level headers and a Message Inspector (TIP – if you follow the CustomBasicAuth walkthrough exactly, you’ll add an Authorization provider to your WCF service.  If you then implement a message inspector to extract authentication details from a SOAP message, you can set the current Principal in that code – but here’s the beauty of it – it happens before WCF security kicks in, so the same Authorization provider will also work!).

So while it is a bit of a pain – once you’ve got the skeleton up and running, it’s actually pleasingly simple.

Comments

Popular posts from this blog

Asp.Net 2 and 4 default application pool generates CS0016 IIS7.5

Before I start – if you’ve found a bunch of other articles about this around the net, tried the fixes that are mentioned and still not getting any joy – then read on – you might find this solves your problem. Earlier today I discovered that when I run any ASP.Net 2 or 4 application through IIS7.5 using the default application pools (which use ApplicationPoolIdentity) on Windows 2008 R2 x64 I get an error message similar to this: Server Error in '/MvcApplication31' Application. Compilation ErrorDescription: An error occurred during the compilation of a resource required to service this request. Please review the following specific error details and modify your source code appropriately.
Compiler Error Message: CS0016: Could not write to output file 'c:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\mvcapplication31\222b4fe6\4e80a86\App_global.asax.clb4bsnc.dll' -- 'The directory name is invalid. '
Source Error:[No relevant source lines]
Sou…

Serializing to attributes in WCF with DataContractSerializer

It’s a common problem – you want to return an object from a WCF service as XML, but you either want, or need, to deliver some or all of the property values as XML Attributes instead of XML Elements; but you can’t because the DataContractSerializer doesn’t support attributes (you’re most likely to have seen this StackOverflow QA if you’ve done a web search).  Most likely you’ve then migrated all your WCF service code to using the XmlSerializer (with all the XmlElement/XmlAttribute/XmlType attributes et al) – and you’ve cursed loudly.Well, I’m here to rescue you, because it is possible – and the answer to the problem is actually inferred from the MSDN article entitled ‘Types supported by the Data Contract Serializer’.The example I’m going to give is purely for illustration purposes only.  I don’t have a lot of time, so work with me!Create a new Asp.Net WCF service application, you can use Cassini as your web server (probably easier – otherwise you might have to enable Asp.Net compatibil…

Adding ‘Deny’ functionality to AuthorizeAttribute in Asp.Net Web API

For the web service project I’m working on at the moment I need to be able to treat authorization differently based on the hostname of the URL that requests are made through.To state more clearly – these web services will have a ‘sandbox’ mode in addition to the real mode, and the mode a request will operate under is determined as part of the controller-selection phase early in the Web API request lifecycle.  So, say that my web services will be hosted on services.acme.com; the sandbox will simply be sandbox.services.acme.com.Please note – a discussion of how this is implemented is entirely outside the scope of this article; but I’ll just say that I’ve developed an in-house multi-tenancy layer for both MVC 4 and Web API that allows us to define ‘brands’ and, under those, you can then redefine content, controllers, and even the DI container that is used.These services are going to require caller-level authentication for most operations via SCRAM Authentication (RFC 5802), and as such m…