I’ve started working with AngularJS for any new websites, and one of the first things I needed to revisit was the authentication strategy. Pretty much every website I build requires the user to be logged in to access (at least part of) the website. I wanted to put together a ‘template’ that I could reuse each time I start a new project. TLDR: the end result is up on github at: https://github.com/capesean/JWTKickStart After doing some research, I really like OAuth2 and JSON Web Tokens (JWT). I use .NET on the server, but one of the appeals of JWT and Angular was a complete decoupling of the browser app from the server’s API. As you’ll see from the Github repo, there are two Visual Studio projects:
- APP: this is the AngularJS application. Although it’s in a Visual Studio project ‘container’, there is no dependency on Visual Studio at all.
- API: this is the server back-end, which has been built using .NET’s WebAPI 2 with OWIN & C#. Although, as mentioned, this could be any API that issues JWT tokens & refresh tokens.
Before I start, my inspiration came from the following sources:
- The BitOfTech blog by Taiseer Joudeh is an amazing resource for Angular/JWT/.NET/OWIN articles. Just amazing. Thank you, Taiseer! However, the main series of articles I drew from used OAuth bearer tokens, not JWT tokens. There are other articles that cover JWT tokens. I rewrote some aspects (e.g. the Refresh Token side) for JWTs.
- I also really liked this article on the Brewhouse.io blog. It shows how to build a modal login that pops up if the user makes an API call which is not authenticated, giving the user a change to re-enter his/her credentials before re-attempting the API call, which is very slick. I extended this to use the Refresh Token before requiring the modal login.
- In the comments on the Brewhouse.io article is a video from a talk by Martin Gontovnikas, from Auth0. He suggests a very similar strategy. Some new nuggets in there too, though.
Some of my requirements:
- Typically my requirements won’t include multiple clients (website, mobile app, etc.), so I removed the multi-client aspect (where client data gets stored in the database) to keep the starting point simple. It should be relatively easy to add back: check out the BitOfTech articles if that’s a requirement.
- Typically I wouldn’t need to cater for CORS either, so I initially left that part out. However, when I separated the system into the two projects (APP & API), that run on two localhost ports, then I needed to add it back. So it’s a pretty simple CORS * at the moment, but for production it’s easy enough to remove the CORS AppSetting so it falls back to a same-origin policy.
- Typically I would have the Resource Server, the Authorization Server, and the Authentication Server as one & the same. I don’t need Facebook etc. logins (I only require username & password access), and my API backend handles everything: authentication, authorization, and the actual API itself. So I merged these all into one.
Some notes for setting it up to run:
- A SQL Server .bak file is included in the API projects App_Data folder.
- When it’s run, it will create a user with username ‘firstname.lastname@example.org’ and password ‘password’ in the database.
- The token & refresh token Url is at /token
- An authorisation protected resource is at Url /api/protected
- Login details are prefilled in the login forms
- Settings for the API project (e.g. Base64 encoded secret, connection string, Client Id, token expirations, etc.) are stored in web.config.
- When logged in, you should see your jwt & refresh tokens outputted as JSON, and the response from the protected API call, which outputs the claims for the logged in user, as shown below:
- You can set the auth token to expire in a minute (1), and then log in: after a minute, the system will use the refresh token to keep you logged in. The neat thing here is, if your claims have changed, I’ve built it to update the ticket, so for example if your permissions change, the app will ‘silently’ get updated with your new status.
I’m going to (hopefully) maintain this repo, so it’s always a good boilerplate project to get started with. In the meantime, here’s the Url again: https://github.com/capesean/JWTKickStart I hope it helps someone!