OAuth 2.0 in Web API

This week I’ll be pushing a sample to the WebAPI-Prototype branch in our Codeplex repository for doing an OAuth 2.0 dance for Web APIs. Before I get into how the sample works, let’s quickly define some OAuth 2.0 terms (note that these are all defined in the OAuth 2.0 spec, but I’m defining them here so that you don’t need to read the spec as a prerequisite for this blog post).

Some Context

Resource owner – represents the entity who actually owns the protected resources. In the case of this sample, the user (e.g. – you) is the resource owner.

Client – represents the application which accesses a resource owner’s protected resources after the resource owner has explicitly granted it permission – this last part can also be said, “after the resource owner has authorized the client to his/her protected resources”.

Resource Server – represents the application that is responsible for hosting the resource owner’s protected resource. The resource server uses access tokens when processing and responding to requests for protected resources.

Authorization Server – represents the application that is responsible for authenticating a resource owner, enabling the resource owner to authorize a client, and ultimately issuing an access token to the client.

However, in practice, nothing is ever as simple as the abstract flow makes it seems (that’s probably why they call it “abstract”). For each of the stages of this flow, there are multiple ways of accomplishing the stage. In this post, I’m going to discuss one way of implementing the OAuth 2.0 flow, but know that this represents only 1 of several possible options. Moving forward, I plan on adding more flows into the prototype branch (and of course, blogging about them here).

A Brief Disclaimer

I’m a big believer in the principle of “the right tool for the right job” – and as I’m building out this prototype, one of the thoughts I keep arriving at is that while OAuth gives you authentication as a byproduct of having the resource owner authorize a client to a resource server, the focus of OAuth seems much more on authorization than it does federated identity. I think that what I’m getting at is in the difference between delegated authorization and federated identity, but I’m having a hard time getting to a crisp, non-philosophical articulation of the differences between those 2 terms. Judging from a quick Google search, I’m not the only one having trouble coming up with a clean articulation of the differences (I suspect this is because authN is always required at some point to do authZ).

At any rate, you may end up asking yourself a similar question as we go through the discussion of the sample, so I wanted to be up front in saying that I feel the same sense of weirdness and am also actively investigating OAuth patterns that use a federated identity system for authN and OAuth for authZ (or patterns to simply make it easier to integrate with federated identity systems, if simply not managing credentials is really the thing you care about).

The OAuth 2.0 Sample Workflow

For the sample, the goal was to secure a Web API using Facebook’s OAuth 2.0 capabilities so that the Web API didn’t need to maintain any usernames or passwords. The resulting workflow looks like the following:

As you can see right off the bat, the concrete example is a good bit more complex than the abstract flow defined by the OAuth 2.0 spec. Why is that? As I see it, there are 2 primary drivers of the added complexity to the end-to-end flow. First, I decided that my Web API represents my OAuth client. This means that once authorized by the resource owner (e.g. user), my Web API can get resources directly from the resource server (e.g. Facebook) without having to expose that data to the resource owner, or any malicious application pretending to be the resource owner. However, because the end user experience is still a browser, and because my browser experience is AJAX-based (meaning that I can’t count on the browser to act directly on 302 status codes), I need a mini-protocol between my Web API and my AJAX code.

The second reason for the added complexity relates a bit to the “brief disclaimer” above. That is, this workflow takes advantage of the fact that authentication is required for authorization – and my Web API client does call into Facebook (in its resource server role) to get some resource owner data. However, the Facebook access token is used by my Web API only long enough to get a piece of user-identifying data which it then plugs into an existing authorization store – I’ve faked out the ASP.NET membership provider in this case.

I’ll be writing another post on my general thoughts here, but for now, this workflow works (even with the additional complexity) and should set the stage for showing how AuthN/AuthZ can work for Web API.

Plugging into Web API

One of the goals I had for the prototype was to enable the auth mechanism to plug into Web API using the standard extensibility points. Additionally, I wanted it to use the standard AuthorizeAttribute that MVC uses. As such, I took advantage of 2 Web API extensibility hooks: operation handlers and message handlers. Additionally, there’s some logic behind wiring everything up that I encapsulated into an extension method that works with the HttpConfiguration object.

First, we have the OAuthFacebookOperationHandler. The responsibility of this operation handler is to examine the incoming request to see whether the operation being called needs to be protected and if so, determine whether the user has been authorized (currently making this determination using a cookie). Based on whether or not the user has been authorized for the operation, the handler will either pass control over to the operation or return a standard Http challenge response containing the Facebook OAuth authorization dialog URL.

First, I’m sure you’ll notice that there’s a bunch of todo notes still in the code. I’m actively working on getting this more seamlessly plugged into things like the membership provider, the AuthorizeAttribute, and the forms authentication cookie generator. However, the purpose of this post is to show the mechanics of initiating an OAuth flow, so hopefully those unfinished aspects won’t be too big of a distraction. But that aside, the basic workflow looks like this:

check to see whether the user has already gone through the OAuth dance, been authenticated, and has authorized the Web API. If this process has happened, there will be a cookie in the request

If the user has been authenticated, authorize the user based on the AuthorizeAttribute on the service operation

If the user has not been authenticated, throw a 401 challenge response with a scheme of OAuth and a location parameter of the Facebook auth dialog

In my sample, I have an AJAX client, so the following jQuery is able to take the challenge response, parse out the location and popup the Facebook auth dialog…

Like I said, this jQuery uses a regex to get the value of the location parameter in the response. It then uses that to open the Facebook auth dialog. The user will then interact with Facebook to authenticate and then authorize my Web API to a Facebook application that I created (note: you’ll need to create register an application with Facebook to use its OAuth authorization server endpoints). If you look back at the URL that’s passed to the location header (line 45 of the operation handler), you’ll notice that one of the query values is the redirect URI. My operation handler will always generate a value that is the address of the originally requested resource with an additional path segment called “authtoken”. Therefore, if my resource is localhost/comments, the redirect URL will be localhost/comments/authtoken (this isn’t a requirement of any kind – it was just how I put this code together). The thing is, I don’t have a resource or service named authtoken. So how does this get picked up? Enter the OAuthFacebookMessageHandler.

If you remember from Glenn’s post about Web API extensibility, message handlers give you an opportunity to plug in down in the channel stack and work directly with HttpRequestMessage and HttpResponseMessage. And while this isn’t terribly helpful if you need details about the operation (parameters, return values, etc.), it’s great if you need only work at the Http level – and it’s very fast! In my case, I need to basically capture all requests that have authtoken as the last path segment, get some information about the user from Facebook so that I can correlate that with my local authorization store (e.g. membership provider) and then drop a cookie that can be used in subsequent requests.

As you would expect, this code takes in an HttpRequestMessage. However, because it’s task-based, it needs to return a Task<HttpResponseMessage> rather than just an HttpResponseMessage. With async operation handlers, the basic principles are as follows:

To continue the flow of execution to the inner message handler and ultimately up through the service operation, call base.SendAsync(..) . If you want to do some processing on the response side only, after the operation has been called, call base.SendAsync, but then add a ContinueWith(..) call.

To short circuit all further processing of the request and simply return a response, return your own Task<HttpResponseMessage> using Task.Factory.StartNew(..)

Because there is no actual service operation for /authtoken, I’m really dealing purely at the Http layer, so I’ll just be returning a new task rather than allowing the incoming message to propagate – and within my request processing I’m doing the following things:

Exchange the auth code returned to me from Facebook for an access token – this is the thing that is actually used to access Facebook data

Use the access token to get my username

Drop my username to a cookie so that my operation handler can pick it up on subsequent calls (note: don’t EVER, EVER, EVER actually do this in production – I’m trying to show you the mechanics of the OAuth dance, and only that)

Emit some script to close the popup window

If all is successful, this handler will set future calls up for success, then signal the parent window to both close the popup and retry the newly-authorized request, so that while there’s a lot of moving parts here, it feels pretty seamless for the end user.

Finally, there’s the question around how all of this gets wired up. I extracted the configuration code into a single, more simple extension method:

This means that I can register for OAuth with code similar to:

config.RegisterOAuth(new FacebookOAuthClient(FB_APP_ID, FB_SECRET));

Where To Next?

There are a bunch of identity and auth related scenarios that I’m currently prototyping, in addition to cleaning up some of the hard-coded stuff in this one. Here’s how I’ve currently prioritized security-related scenario investigations:

Ensure that Http basic over SSL works without any issues

Web API as an AuthN + AuthZ + Resource server – this would make the Web API equivalent to a service like Twitter where you could enable users to authorize 3rd party applications to your Web API (along with manage the permissions of those applications) – the key here is that Web API would have manage its own credential store.

Web API as an AuthZ + Resource server – this is similar to the previous with the notable exception that Web API would rely on a federated identity provider for AuthN. In this scenario, we would integrate with an STS (or broker like ACS).

Do these look like the right scenarios? The right ordering? As with everything else, I welcome your feedback!

I’d love to see a multi-provider sample as well. You could probably take advantage of returning mutliple www-authenticate header in the response (??) and the client could display links to each “realm/location”. I’m not sure what the best practice is for this, according to the spec….

Adro

Thanks, Howard. I have opted for a browser approach, since my users authenticate with facebook with the javascript sdk prior to making calls to my API. I’m using a message handler to validate the sent token against facebook and set the authorized identity (httpcontext.current.user) there.

howarddierking

because in this case, my server application (the Web API) was the application accessing Facebook – not the browser. As such, from an OAuth perspective, the user is authorizing my Web API and that is why there’s the extra complexity. I believe that there is an OAuth flow that would account for storing the AT on the browser – however, in this design, I don’t want the browser maintaining the AT.

AdRo

This all seems over-engineered. Why not just pass the facebook access token as, say, a header value in every ajax request and have an action filter check the validity of the token on every call?

Hi Jeremy – yea – it wasn’t too long after writing this post that I moved on to a different team and stopped prototyping the OAuth scenarios. I know that the team is still investigating this scenario – follow http://blogs.msdn.com/b/henrikn/ for updates as they emerge.

Jeremy

Howard, This discribes a scenario that we are trying to accomplish as well. We have a similar implementation in strait WCF services, but we would like to move towards the Web API with OAuth approach. Please let us know if you’ve made any progress prototyping this since it was posted a number of months ago. We would be happy to provide feedback on any solutions.

Hi this is very interesting post. I am trying to make WCF Web API service
that accept Facebook, Twitter and custom login.
Custom login also need to works by generating token . (I think I cannot use here OAuth but need to build custom Authorization server) I have planned to use
FormsAuthenticationTicket for this.I will also have ASP.NET MVC3 web site that will call WCF Web API service.Can you point me to source code from this blog post and comment my approach ?Thanks very much for your help.

Luís Carlos Calado Lameirão Go

Hi Howard,

I would like to use OAuth 2.0 with Google Prediction API. I have it in PHP but since I want to use Chrome Extensions, I have to do it in Javascript. Can you help me with this?

http://www.facebook.com/people/Kevin-Davie/1353257071 Kevin Davie

congratulations!

— —

At the moment I have a webapp which offers username/password login or
login via Twitter OAuth. I want to add a REST API for this
application. Users can login via HTTP authentication AND/OR OAuth:Inspired by your great post I created a sample flow: http://i.stack.imgur.com/EM446.png
Can this work?

Anonymous

ok – just updated Codeplex to move the OAuth sample out of HttpEnhancements and into its very own end-to-end sample project called SecureServices (http://wcf.codeplex.com/SourceControl/changeset/changes/9f94d015f305). It’s on the WebAPI-Prototype branch, under the samples folder. Please let me know if you have any questions or run into any issues.

Anonymous

Will do within a week – was planning to do this week but we had a baby on Wednesday, so that’s set me back a few days

http://twitter.com/RobGibbens RobGibbens

This is exactly what I was looking for. Like Alan, I was looking for a more complete end to end example, as I’m just getting started using the Web Api. Do you happen to have an estimate of when that might be wired up? Thanks for this code and post; it’s very helpful.

What’s the ETA of getting this sample in the Prototype branch? I want to pick this apart.

The first two of your bullet points are very high priority for me. I’m glad that you are working on it. Please reach out to me if you want some early feedback.

Cheers,

++Alan

Ineedadip

You guys are describing my exact scenario, just more eloquently. This is something we have been kicking around internally. Let me know if you need any beta testers.

Anonymous

this actually sounds like a great example of bullet #2. In this scenario, your mobile client would ask the user to authorize it to the his/her protected resources in your REST api. Your Web API would support (via plugin) the OAuth auth server role which would enable your end users to authenticate to it using Http basic and then authorize the mobile app – at which point, the mobile app would get an access token which it would pass to the Web API on subsequent calls. Because the Web API implements both the auth server and resource server roles, the token can be cracked open and the IPrincipal can be attached to the thread context, so that you can use it just like any other principal-based scenario.

Does this sound about right? As we’re prototyping this scenario out, I would love to keep in touch so that you can verify if the work we’re doing will work for your scenario. Send me an email at howard at microsoft dot com.

John Waters

Actually, I have a scenario which I believe is quite common. I have a variety of mobile devices connecting to the REST api I am building on WebAPI, including iOS, Android and Windows Phone. I want to use Basic Auth for the initial log in, but then I want to send back some token that is stored on the device and used for subsequent calls. I have a prototype working but it feels pretty clunky, I would love to see some strong support for this scenario in the API. I would like to be able to just plug in code that does the login check for both the username/password and the token, and that returns the initial token, and have the rest be boilerplate. I would also like access to the current caller in my operations. If you want to discuss my current code base I would be happy to share.

Ineedadip

We are not using ASP.NET Membership, but as long as that is abstracted away as much as possible I’m sure we’ll find it useful.

API Keys (GUIDS) that our clients can generate is how the API is currently used. We would like to provide another option for third parties so that they can do some fancy “OAuth stuff” and provide our clients with an option to put in their credentials (Username and Password) to grant authority.

Just to reiterate, right now third parties have to say “Go into your account, generate an API Key, then paste it here so we can access your account”. We’d like to go the OAuth route so that clients don’t have to know about/generate/paste API Keys.

Hopefully some of that makes sense. Great posts by the way.

Anonymous

Just so that I’m clear on your scenario, are you imagining that your clients would authenticate using their existing keys and then authorize 3rd party applications to access their protected resources in your RESTful API? I think that’s what I’m reading, but just want to make sure I’m not missing anything.

I’m planning to approach this using the ASP.NET membership provider as a baseline credential store – do you see any issues with this approach for your scenario?

Anonymous

At the moment, this scenario works if you’re using Windows credentials. There some ways to get around this (they are different between IIS hosted and self-hosted) but we’re working on making it much more straightforward. More to come on that topic.

John Waters

Cool, I am also looking to do Basic Auth using a MessageHandler, do you have any code examples for that?

Ineedadip

Exciting, I’ve had great success with the WCF Web API. We’ve provided a great RESTful API for our clients using API Keys (GUIDs) that are passed as a header, querystring, or using Basic Authentication. But now third parties want to build applications and nobody likes the idea of generating more API Keys to cut and paste… Everyone is asking if/when we can have some kind of OAuth Implementation. I hope your second bullet point at the bottom provides some guidance.