OData and Authentication – Part 2 – Windows Authentication


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?

On the Serverside

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.

TurnOnIntegratedSecurity

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.

Detour: Basic Authentication

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.

On the Clientside

Now that a NTLM challenge has been made, what happens next?

In the browser:

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.

.NET Client Application:

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 Client Application:

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.

Silverlight 2 & 3:

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:

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;

Summary:

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.

Comments (16)

  1. Brian Orrell says:

    So how do you call an authenticated WCF Data Service from Javascript?  

  2. Rashan says:

    How we can achieve this when we use the open source odata library for Objective C.

    (I wants to use a WCF data service from iPhone app)

  3. DotNetWise says:

    You said in the part 2 you'll treat the FormsAuthentication – what happened to that?

  4. ahmed khan says:

    how about JAVA? how do we authenticate over https?

  5. java says:

    how about JAVA? how do we authenticate over https?

  6. Narf says:

    typo there –> "If, for whatever reason, a KDC isn’t available a standard NTML handshake will occur."

    NTLM not NTML

  7. GideonIsrael says:

    What about if the service is on a url in a asp.net mvc website (like nerddinner.com/…/Odata.svc) and I don't want the whole site under windows auth, but on the service at the url!

    (I actually have this scenario for my app)

  8. Samir says:

    I can't thank you enough, the authentication parts for OData have been of immense help. Wish I was first here!

    Please push up your blog rankings in MSDN Blogs directory.

  9. the seeker says:

    Why not provide a link to part 1 of the article?  it would be helpful

  10. Rahul says:

    It is very surprising that you would not provide a link to all the articles in this series !

  11. swapnil says:

    Please shed some light about how to perform authentication for ios apps which will be using the ODATA sdk fo r ios

  12. Andrew Law says:

    This article is EXACTLY what I needed.

  13. It would be really helpful to provide a case which is not from a windows client – e.g. from java (android) – how would it authenticate?  thanks.

  14. Ye Myint Win says:

    I tried to use ctx.UseDefaultCredentials = true; but it is not working.

    My web service hosted in another sub domain. Pls help me.

  15. Neal Ganslaw says:

    Thanks for this article… It helped me solve a problem of an MVC app calling an OData service.

  16. ziro says:

    cool stuff guys,

    but I need a sample for a selfhosted OData Service (DataServiceHost). There's nothing in the Doc..

    A simple approach for NTLM auth on the DataServiceHost –> app.config does not work for me. 🙁

    Can you give me a advice, please.

    Thank you.