JSON Web Token (JWT) is a JSON-based open standard (RFC 7519) for passing claims between parties in web application environment. The tokens are designed to be compact, URL-safe and usable especially in web browser single sign-on (SSO) context.JWT is a means of providing a simple claims based authentication between a client and a server. The token is an encrypted piece of data which can be sent as part of a payload to allow access to restricted services. The full RFC is here https://tools.ietf.org/html/rfc7519
The basic gist of JWT is this:
- User authenticates with server (identity/password, oAuth etc)
- Server generates JWT using secret key and some payload (usually a JSON string that provides some basic identification information, a subset of the User object for instance)
- Server responds with JWT access_token
- Client stores access_token in cookie or local storage (we will be using local storage)
- Client provides access_token in future requests.
Waterlock is a nifty little user authentication//JSON web token management tool built for Sails:
The best way for handling auth in an Ember app is through the use of Ember Simple Auth:
So that's the server side and UI components. I'm not going to go through setting up each of these components - you can see how that's all done on each of their repos. I'm also asuming that if you're interested in this little cocktail of code you're probably aware of each of them but a little confused as to how you go about pinning it all together.
So down to the code! The repo is here: https://github.com/wayne-o/ember-waterlock-example go ahead and clone it if that's what flicks your switch - I expect it does else you wouldn't have read this far.
There's 2 parts to this repo:
- The Server
- The Client
I've added a couple of extras here that help make things simple. Ember-Data is a brilliant little library - it doesn't do everything and I don't use it everywhere but where it is used it's very clever and ahead of it's time. One of those areas is being a pretty complete implementation of the JSON-API spec: http://jsonapi.org/. And to get SailsJs dancing nicely with this spec we need to update the blueprints. To do this I use the brilliant repo by mphasize: https://github.com/mphasize/sails-ember-blueprints. What this does is turn the standard JSON output from sails into nice neat JSON API compatible JSON. Neat.
I've also included waterlock and waterlock-local-auth. To get all these you just need to cd into the /sonatribe-api directory and run
npm installNow - that's pretty much it - if you're doing these from fresh you'll need to run the generate blueprints command but that's all documented on the repo's readme.md - RTFM ;)
The noteworthy config changes include in the /config/models.js file:
You can see that I've added the "associations" and "validations" nodes to the config. It just defines explicitly how you want these types of nodes to appear in the JSON output.
Next up is waterlock.js:
You're going to need to tell it to pluralizeEndpoints and also you need to rename the token name - ember-simple-auth expects "access_token" - don't do this and you're into a world of pain. You also want to set "stateless" to false - we don't want any nasty sessions on the server thank you please. Sessions are grotty at the best of time and mess with your head when you try and step up in the scalability realm. JWT is stateless authentication. It keeps things clean.
That's it for the API! Simple yeah.
So now onto the client - this is where things can get a little... involved. But considering what you're getting - I'd say not too involved. You'll want to cd into the /sonatribe-ui folder and do the usual npm install && bower install stuff.
I've included ember-cli-simple-auth and ember-cli-simple-auth-token which are set up in the /config/environment.js file: https://github.com/wayne-o/ember-waterlock-example/blob/master/sonatribe-ui/config/environment.js
Go with my defaults for now - you can mess with these later if you want.
Things to note:
- I've used pod structure - it's great for organising an app small or large.
- I've used the new computed decorators: https://github.com/rwjblue/ember-computed-decorators meaning we get Java style attribute decoration for things like @observe and @property and even @whateverYouWant
- Login: https://github.com/wayne-o/ember-waterlock-example/blob/master/sonatribe-ui/app/pods/components/login/login-panel/component.js
- Register: https://github.com/wayne-o/ember-waterlock-example/blob/master/sonatribe-ui/app/pods/components/register/register-panel/component.js
So the process is to call /login if the validations for username / email pass - get the user registered and logged in and then, using the response with our authentication data we can populate the users User model and save. Finally we push the user off to the main app by sending an action to the parent route ("userAuthenticated").
I'm aware that because I am accessing Ember-Data and JQ.Ajax within this component I am completely side stepping DDAU (http://www.samselikoff.com/blog/data-down-actions-up/) - and this is a bit cringe but I'm going to leave it as is as I want the example to be clear. The simplicity of using these libraries side by side should be unhindered!