Imagine you have an OData Service installed on your domain somewhere, probably using the .NET Data Services producer libraries, and you want to authenticate clients against your corporate active directory.
How do you do this?
First on the IIS box hosting your Data Service you need to turn on integrated security, and you may want to turn off anonymous access too.
Now all unauthenticated requests to the website hosting your data service will be issued a HTTP 401 Challenge.
For Windows Authentication the 401 response will include these headers: WWW-Authenticate: NTLM WWW-Authenticate: Negotiate
The NTLM header means you need to use Windows Authentication. The Negotiate header means that the client can try to negotiate the use of Kerberos to authenticate. But that is only possible if both the client and server have access to a shared Kerberos Key Distribution Centre (KDC).
If, for whatever reason, a KDC isn’t available a standard NTML handshake will occur.
While we are looking into Windows Authentication it is worth quickly covering basic auth too because the process is very similar.
When you configure IIS to use Basic Auth the 401 will have a different header: WWW-Authenticate: Basic realm="mydomain.com"
This tells the client to do a Basic Auth handshake to provide credentials for 'mydomain.com'. The ‘handshake’ in Basic Auth is very simple – and very insecure – unless you are also using https.
Now that a NTLM challenge has been made, what happens next?
Most browsers will present a logon dialog when they receive a 401 challenge. So assuming the user provides valid credentials they are typically free to start browsing the rest of site and by extension the OData service.
Occasionally the browser and the website can "Negotiate" and agree to use kerberos, in which case the authentication can happen automatically without any user input.
The key takeaway though is that in a browser it is pretty easy to authenticate against a Data Service that is secured by Windows Authentication.
In a .NET client application using the standard .NET Data Services client – or for that matter the open source version – you need to tell data services your credentials.
Which you do like this:
MyDataContext ctx = new MyDataContext(uri); ctx.Credentials = System.Net.CredentialCache.DefaultCredentials; The example above makes sense if your client application is running under a windows account that has access to the server. If not however you will have to create a new set of NetworkCredentials and use them instead.
ctx.Credentials = new NetworkCredential( "username", "password", "domain");
As you can see, pretty simple.
Silverlight on the other hand is a little different.
If it is running in the browser – the only option in SL2 & 3 - then by default the Data Services client will re-use the cookies and authentication headers already established by the browser.
In fact in Silverlight 2 & 3 that is all it can do. The Silverlight client library doesn’t have a Credentials property so there is no way to use different credentials.
Typically if your SL app is hosted by a site that requires Windows Authentication, you don’t have a problem – because in order to download the Silverlight app, you need to authenticate in the browser first.
Which means from the perspective of the Data Service you are already authenticated.
Warning: While it is possible in Silverlight to do x-domain calls, so long as the other domain has a correctly configured ClientAccessPolicy.xml file, if the other domain needs you to logon, there is no way to provide your credentials.
Silverlight 4 is significantly more flexible, because it adds a Credentials property to the DataServiceContext. Which you can use to provide a different set of credentials if required.
In fact, if you think about it, because SL4 can run 'out of browser' the ability to set credentials directly is absolutely vital.
Despite this new feature in SL4 there are still some differences between .NET and SL4.
In SL4 there is no CredentialsCache so you can’t re-use the DefaultCredentials from the client. However we added a very handy property instead:
ctx.UseDefaultCredentials = true;
As you can see using Windows Authentication with OData is pretty simple, especially if you are using the Data Services libraries.
But even if you can’t, the principles are easy enough, so clients designed for other platforms should be able to authenticate without too much trouble too.
Next time out we’ll cover a more complicated scenario involving OAuth.