Adding the concept of an authorization server to your web APIs is the recommended architecture for managing authentication and authorization. But writing such a service from scratch is not an easy task.
To simplify that, Microsoft included an OAuth2 based authorization server “toolkit” as part of the Katana project, which is also used in the standard Web API templates that ship with Visual Studio 2013. I get a lot of questions about how this middleware works, whether I like it, what the limitations are and if I would use it at all. To make this discussion easier in the future – here’s my take.
What I like
Microsoft’s intentions were really noble – they tried to make it very easy for the “average” (read: not security expert) developer to do the right thing – namely push them to an architecture where authentication and authorization decisions can be abstracted away into a separate “component” while using a standard protocol (OAuth2). This would result in token-based authentication in general – and would also get rid of the cookie and CSRF problems for SPAs in particular. The pit of success so to speak.
The middleware produces encrypted and signed tokens (protected with the usual machine key mechanism) which can be automatically consumed by the corresponding token middleware, creates separate endpoints, forces you to at least think about client validation and requires SSL by default.
The two most common flows I see for Web API clients is resource owner flow and implicit flow. Resource owner flow is now very easy to implement with the new AS middleware. It really just takes a few lines of code and you are done. I like that a lot (if resource owner flow is the right architecture for you – which is a different discussion). I wrote about the implementation here.
The same applies to client credentials flow (not so common), and custom grant types (even less common).
What I don’t like
If you want to do anything beyond what I described so far, the complexity increases unproportionally – e.g. adding a “simple” extension to resource owner flow – namely the concept of refresh tokens, suddenly forces you to understand OAuth2 (see here) and the security implications around it. You also have to implement persistence yourself – which on its own is challenging if you would follow security best practices and the OAuth2 threat model. No pit of success.
Another example is implicit flow, which is often the more appropriate flow for native or JS based applications. Unfortunately the middleware implementation is riddled by the fact there is no Katana or Web API based view engine yet, which means you need to use an additional framework when you want to render proper login or consent screens. Scattering the logic of the flow between views, controllers and middleware providers doesn’t make it more intuitive. And when you made it that far, it seems some parts of the protocol are just missing – like returning proper errors from the UI.
In other words – the middleware forces you to understand the underlying protocol, forces you to understand the middleware itself and all its various callbacks and extensibility points, makes you implement the hard (and security related) things yourself, and in the end you have to live with the restrictions that the thin abstraction imposes on you.
Next is documentation – the built-in templates don’t do a very good job of isolating the features and trade-offs of the middleware. They combine all the new concepts of Katana, OWIN, OAuth2 and ASP.NET identity into a hard to follow sample “application”. It took me three blog posts (see here) to describe how the “Individual Accounts” sample works – and I am sure I missed some of the subtleties.
Just recently Microsoft released this very long article that describes all the aspects of the OAuth2 middleware – read it here. It’s good that this document finally exists, but I am not a huge fan of this disclaimer – after you followed the 83 easy steps:
Note: This outline should not be intended to be used for creating a secure production app. This tutorial is intended to provide only an outline on how to implement an OAuth 2.0 Authorization Server using OWIN OAuth middleware.
What would I like to see instead?
Well – it is always easy to bitch and moan about other people’s work – but I was actually asked for feedback during the development of the middleware – and this is just a repeat of what I said back then.
OAuth2 is not the most straightforward protocol to implement – but it is also not too hard. When you start working on it, you realize that the “protocol aspects” of it – like query string formats or response message layouts are actually the easiest part. The hard part is state management, secure data storage, input validation etc. And my main point of criticism is, that the middleware does not help you in any way with that. It simply implements a framework that exposes a developer to a limited subset of OAuth2 without really understanding the use cases.
Much more useful would have been super easy to use, focused and specific implementations of the two most common flows for Web API apps: resource owner and implicit – including ready to use support for login and consent page, scope handling and refresh tokens. That would have also included a persistence layer and state management. Our OSS project AuthorizationServer e.g. takes care of all that.
So overall I’d conclude with saying – even when the intentions were good – the whole authorization server middleware project was a little over ambitious and I can’t really recommend using it (besides for the most simplest cases).