Sidwell’s flagship web product, Portico, is growing in so many ways. In addition to maintaining the original Silverlight control, I’ve developed a mobile website, and I am about to develop a whole new application containing several “widgets” using the Web AppBuilder for ArcGIS. We also have an Advanced Print Preview and some custom reports that access the backend. Portico has become so much more than a website — it’s a development platform — and I certainly will not predict the next applications to be built on this platform. So, I decided the time has come to separate the traditional Portico website from it’s backend services, and deliver the backend through a new API.
For all intents and purposes, we are a Microsoft shop. We’re all in Visual Studio, everything is .NET, and we use SQL Server. The one exception is the Portico website, which is running PHP. I spent years developing PHP early in my career, and I’m glad to have moved on. It’s got it’s place, and I think the Portico website is one of them. But, the entire backend system has grown far too complex for a dynamically typed language with limited tooling support. So, I decided to develop our API using Microsoft’s WebAPI framework. It’s familiar territory for me, since I’m an expert at MVC, even developed some API’s using MVC, and spent some time struggling with WCF.
Security – JSON Web Tokens
Developing the API was actually quite straightforward. But, the key challenge on the project was Authentication and Authorization. It’s the thing that literally kept me up at night. I spent weeks banging my head, doodling on anything at hand, trying to make the existing, common frameworks fit our needs. Finally, I discovered JSON Web Tokens.
JSON Web Tokens are an emerging piece of the emerging OAuth2 framework. I usually spend time at Pluralsight, Microsoft Virtual Academy, and on my Kindle, learning about new technologies. This time, I found a surprising wealth of information on YouTube. Really, YouTube!!!
The cryptography is quite simple. One party signs a message with a secret key, and transmits the message plus the signature. The other party receives the message, signs it with the secret key, and verifies that signature matches. If it does, the receiving party can be sure that the message was not tampered with. The whole system relies upon two parties knowing a secret key, which is NOT known by anybody else. Anybody can view the ticket, but if it’s modified, the signature becomes invalid. You’d have to know the secret key to create a new signature. The process has been around for a very long time. The only new thing is the format through which this data is passed.
It’s important to note that the ticket is passed fully in the clear. Actually, it is base 64 encoded, but encoding is not encryption, so that might as well be in the clear. Therefore, you can never store anything sensitive in the ticket — like Password or IsSecretAgent. If you want to store sensitive data in the ticket, you must encrypt the ticket. That’s an additional complication.
JWT is perfect for single sign-on situations, like Portico, where we want our user to sign in to the website, and not have to additionally sign in to the API. The user has one ticket that’s valid in both places. That’s because both applications know the secret key, and can validate the ticket.
Another thing that I like about JWT is that it plays so well with Claims authentication. Microsoft is moving away from “roles”, and replacing that with “claims”. Well, a JWT is nothing more than a list of claims. So, it’s very easy to transform a JWT to a ClaimsPrincipal.
The list of claims is what makes JWT play so well with any RESTful API. Recall that a RESTful API does not have sessions. So, you cannot just fill up the session with things like UserName, IsAdmin, Roles, etc. When calling a RESTful API, you need to pass a ticket that contains everything that the API needs to know to authenticate and authorize the user.
OWIN OAuth Server
The latest version of WebAPI is built on the OWIN framework. Amazingly, OWIN includes a built-in OAuth server. So, I just needed to configure my WebAPI to use the OAuth flows that I was using. Aaron Parecki has written the best, most accessible description of the flows on his blog. Of course, I’m using the “password” flow, which you really do not want to use unless you are the OAuth server — which I am! I am also using the “client_credentials” flow, because the application needs to access configuration information, independent of the user.
There is a lot of work to be done on the API. One area is refresh tokens. Currently, when a token expires, the user is logged out. That’s not very friendly, and it forces me to use longer token lifespans than I want. The JWT spec does not include anything about refresh tokens, so it would be a roll-your-own kind of thing. The obvious solution would be that you’d present a valid token that is about to expire, and receive a new token with a new lease on life.
The other area of development is the Administration side. Currently, the API is GET only. I have a different application that uses traditional methods of connecting the database to perform Create, Update, and Delete. I would prefer that all of those calls go to the API as POST, PUT and DELETE. I’m not sure I will get the time for that, though.