So you liked my article about JWT and you want to see some examples right?
I have you covered with two basic but functional implementations of it both in
Rails which you can adapt to you own framework of choice without hassle.
First, I created a service to handle the
decode (this JWT implementation calls those methods
verify respectively), let’s see it:
1 2 3 4 5 6 7 8 9 10
We export two functions, one that will issue a token and one that will verify it. Here you can see how we pass our payload and the secret key. I suggest you to use an
ENV variable to hold our secret, much better than a simple string. Also, a large random string is much harder to crack.
For the decoding, we pass there our token, our secret, no options (for advanced usages of JWT) and a callback that will be fired when the verifying is done.
Good, let’s see our
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
We check that we passed credentials, then we find our user and we call a custom
validPassword function (not interesting for this article but you can check it on the demo) to see if our user / pass combination is correct. So if our credentials are valid, we issue a token using our
user.id as a payload and we also pass the complete user on the json (so
angular can have it without hassle).
So: We send our credentials > we check its validity and if they are ok > we receive our user and a token via json.
Nothing fancy right? No special session stuff or code, just a normal function that returns a token.
The register method is not fancy either:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
We just create a user with those new credentials and if they are valid, we issue a token like we did on the
authenticate method. We do that so the user doesn’t need to login by hand after registering.
So, how we manage incoming requests? Sails has a concept called
Policies which are basically middlewares that runs before a controller. There we can check for our token, let’s see:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
First we check if we have the token on the header which basically is a header called
authorization with the content
Bearer token_string. If we have this kind of header we store the
token_string part. If there is no header, we also check if we have it on the query string like:
When we finally have the token, we just verify it, extract its payload and assign it to
req.token so we can access it from a controller. If there is no token, we just send an error json.
Now that we have our token verified and saved on the request object, we could do stuff like (this is not in the demo because
Sails generates a virtual REST for you):
1 2 3 4 5
Since our token is just our user id, we can use it to query it when needed.
There is nothing more to add. Surprised? We just needed a simple library to manage the encoding/decoding of the token and just issue it when we register or login and check for its existence before each request.
You will be surprised to see that this implementation is almost the same (if we ignore my Rails ignorance this days). I created a lib for the encoding/decoding:
1 2 3 4 5 6 7 8 9 10 11 12 13
Basically it does the same as the sails one. The secret we are using here is the one that comes with the rails instalation. We can use what we want, I just took the advantage of having a good one already created.
So for the
AuthController, let’s begin with register:
1 2 3 4 5 6 7 8 9 10
We create an user and if all is correct, we issue a new token which we will return with our user via json.
For the authenticate method:
1 2 3 4 5 6 7 8 9 10
No surprises here. If the credentials are valid, we issue the token and return it via json with our user.
How do we manage the request here? I created a base controller for all the API controllers (which I assume that all of them needs authentication) and there I created a method like:
1 2 3 4 5 6 7 8 9 10 11
To be honest, my
Sails implementation is far more complete, and we can certainly do all those checkings here, but for the demo I was simple. We split the header, we get the token and we verify it. If it is valid, we create our
@current_user based on the payload we had on the token. We could just store the id as we did in
Sails but I decided to always have our user ready too show you that all of this implementation is really flexible.
And that is all! We don’t need anything else. Of course we assume we have a
User model with some password digest system like
has_secure_password but that is really up to you. You can issue a token when you want to but the most common way is the login/pass. Nothing stops you of writing valid tokens on paper and give them away on the street like propaganda.
Well, how we decide to work with the token on angular is really personal and I won’t lie, this is the first time I do auth on angular but I am quite happy with my approach.
I decided to store the token on the local storage, so I don’t need to login everytime I enter the page, but that is based on your personal use case.
Let’s see the auth service:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
For the login, we make a post with our credentials and if it succeds, we store the token (and also the user, I got lazy here) into the localstorage. For the registering, we remove the token if any and well, same thing as login.
To see if we are authenticated I decided to check for the token existence. Since the backend doens’t know about logins, having the token means that we can query our stuff so if the token exist, we are “logged in”. Of course the server can reject it on the next request if the user no longer exist, it expired or we used the “rotate tokens” technique.
Look how the logout works! We just need to delete the token because as I said, the backend is not concerned about logins as there is no sessions or stuff like that.
The authorize method is a helper method I use to check if a user is authenticated or not before I enter a route (more on this later).
I also created a
AuthInterceptor to handle the request/response:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
If there is a token saved, put it on a header so every request we make, will have it (just what we need!). For the response, if we get a 401 or 403, redirect me to login and delete the token if any.
The routes are like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
We have a parent state for anonymous routes and a parent state for authenticated users. The important part here is that we have an access data there to give a nice UX on our page.
To handle the routes I do:
1 2 3 4 5 6 7 8
If we are not authorized to enter the page (using the access data we put on the routes) we redirect to login. Here I use the method I have on the
Auth service to basically check if the user is authenticated for the user routes. We can expand this implementation to put more roles like an admin one.
And that is it! Since the token goes via header, we can query our backend as we normally do. There is no need to do something extra.
I have a live demo here. You can login with
firstname.lastname@example.org / 123123 or create your own user. About if the live demo is sails or rails… I forgot, they behave the same :)