Thursday, August 13, 2015

Nancy Authentication with Owin and JWT

A huge part of this stuff is based upon blog posts by Jonathan Channon and Mike Hadlow.

It took me a bit of time to figure out all the working bits to building something atop Nancy using JWT for authentication. I decided to create an example app that could be used as a reference when I need to do this again. This isn't a tutorial. It's the descriptions of all the different moving parts.

The app has a very basic SPA, some RESTful endpoints, and basic unit tests. This particular app is setup for ASP.NET hosting (handy for hosting it in Azure).

The example app is on GitHub.

Solution Layout

The solution consists of two projects: NancyAspNetOwin.WebApp and NancyAspNetOwin.WebApp.UnitTests. The App directory contains all the files which comprise the SPA front-end. The Authentication directory houses the C# classes which support the token authentication. It also includes the Nancy Module which provides the endpoints that support authentication. Content, fonts, and Scripts all hold the plumbing bits such as Bootstrapper, KnockoutJS, etc. MyBootstrapper.cs and Startup.cs wire up the Nancy and Owin bits. index.html and IndexModule.cs are the kick off point.

Setting Things Up

There are a boat load of NuGet packages which need to be added when starting from an empty web application project. Some are the Nancy/Owin related stuff for the back-end. Others support the front-end SPA stuff. For this app, there were a few other things I dropped.

Nancy/Owin NuGet Packages:
  • JWT
  • Microsoft.Owin
  • Microsoft.Owin.Host.SystemWeb
  • Nancy
  • Nancy.Hosting.Aspnet
  • Nancy.Owin
  • OWIN
  • Owin.StatelessAuth
SPA NuGet Packages:
  • Bootstrap CSS
  • KnockoutJS
  • RequireJS
  • Require.JS.Text
Other Bits:
  • login.css - Pulled from
  • form.css

The web.config file needs to be updated. The system.web and system.webServer sections need things for Nancy. An appSettings entry is created for the OWIN middleware.

You'll also want to set the project to use HTTPS.
The Workflow

The flow for this app is pretty simple. A login form is displayed when first landing on the home page. When the credentials are entered, a token is retrieved from the login endpoint. This token is then used to pull the greeting from the secure endpoint.

Startup Code

There are two files running the show here: Startup.cs and MyBootstrapper.cs. Startup.cs has the Owin stuff. The pathsToIgnore variable contains all the routes we want exempted from the token-based security. These paths, along with an instance of the SecureTokenValidator class are passed into the RequiresStatelessAuth() method.

MyBootstrapper has two overrides. The RequestStartup() override contains the glue for the Owin stuff. The ConfigureConventions() override tells Nancy about the other directories that hold static content (JavaScript files, CSS files, etc.).

The Client UI

The UI implementation starts with the index.html file. Its layout was pulled from a template site. The rest of the client app is housed within the App folder. It contains the two knockout components, the config for RequireJS (config.js), and the basic application view model (myapp.js).

The index.html and myapp.js files act as the main view/view model for the app. index.html contains the markup, CSS file references, and script file references. myapp.js has the data bindings used by the app.

Each component is split into three files. These three files contain the HTML which serves as the view, the JavaScript view model, and code to register the component in Knockout.

The login component view (login-control.html) is a basic html file.

The login component view model (login-control.js) is a little more interesting. The params are come from a data binding on the index.html page. If a token is returned the page adds the token to future headers, raises an event, and hides the form. This is the spot you could store the token in a cookie or something.

The login component registration (login-control-register.js) tells Knockout what files to use to display the component. Pay attention to the template property. The use of "text!" lets RequireJS know that the file isn't a code file.

The Service Stuff

Nancy supports a number of view engines, routing definitions, etc. The NancyModule is quite capable of returning views, exposing RESTful endpoints, etc. Each module can support different authentication requirements.

IndexModule.cs is a NancyModule with two endpoints: /, and ./health. Both require an https call. /health requires that the caller supply a valid token in the request header. The RequiresAuthentication() method uses the ClaimsPrincipal data created by the SecureTokenValidator class.

The SecureTokenValidator class (lifted from here) verifies that the token provided in a request is valid. It also converts the token into the ClaimsPrincipal object used by Nancy. It's interesting to note that I've seen two variations on this class. Both have noted that the token does not directly decode to a set of claims.

Testing Notes

Nancy was designed to be very testable. There's the Nancy.Testing package goes a long way to helping with that. The Nancy documentation does a good job of explaining how to test your Nancy app. Testing Nancy with OWIN is a little more involved. You'll need the Microsoft.Owin.Testing package. OwinTests.cs in the test project gives an example of how those tests are done.

In Closing

That's all I have so far. Hopefully, this will help some other people who are trying to work through these issues.