Series: User Auth

Token Authentication with Server Sessions

Published on Nov 04, 2015

While client-side sessions are great for keeping regular users out of trouble, it’s not enough to stop a determined hacker. For that, you’ll need token authentication.

In this episode we’ll set up token authentication between Ember and a Rails server session. We’ll cover two different ways to pass the token in Ember, with the strengths and weaknesses of each.


Links

Code

In the session service, we take the userName and password, send them to the server, get back the token, then log in using the current ID and the token.

  login(userName, password){
    return new Promise((resolve, reject)=>{
      Ember.$.ajax({
        method: "POST",
        url: '/sessions',
        data: {
          email: userName,
          password: password
        }
      }).then((data)=>{
        var token = data['authentication_token']
        var user_id = data['user_id']
        Cookies.set('userId', user_id)
        Cookies.set('authenticationToken', token)
        this.initializeFromCookie()
        resolve()
      }, ()=>{
        reject('Username and password did not match')
      })
    })
  },

In initializers/ajax-prefilter.js we tell jQuery how to attach the token to our headers. That's how initializeFromCookie in the above file succeeds, as well as all subsequent calls to protected APIs.

export function initialize( container, application ) {
  Ember.$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
    var token = Cookies.get('authenticationToken')
    if(token){
      jqXHR.setRequestHeader('X-CSRF-Token', token);
    }
  });
}

export default {
  name: 'ajax-prefilter',
  initialize: initialize
};

The server has to match the signature of these calls. Here is the Rails version of that code

Transcript

Hey and welcome back to Ember Screencasts. Today we’re going to continue talking about authentication. So last time we had our Monsters app and we had different pages that were authenticated that you couldn’t get to if you weren’t signed in. So if we log out and we try to get to those pages, it’ll just tell us to log back in. So our data is safe, right? Well, not so fast, because here we can still access all that data if we know a little bit about our API.

So a malicious hacker could probably guess something like this, especially if they’ve created web apps in the past. So today we’re going to be protecting this information with token authentication. We can think of this problem as having several different parts. One is like a security guard that’s asking for your identification. It wants to know that you have your ID badge. The second part is how our Ember app is displaying that ID badge. So we’ll set up the security guard first in our Rails app, and we’ll speed through that since it’s going to be a little bit different for every type of backend you use. And so with a snap, I’ve got a Rails app asking for identification, and since we haven’t yet set up our Ember app to give that authentication, it now blocks us out. That’s what we want. Let me show you how that works.

So first, we add an authentication_token to our users.

Then, in our application_controller which can be accessed by all of our other controllers, we create a method called current_user that’ll get the X-CSRF-Token from the frontend app. This is basically asking for your badge. And then it says alright, if your badge matches the user then you must be that user. So that’s our current_user method.

And then we have the authorize_user method which is saying, hey, check for the badge, and if not, give them a 401 unauthorized. And then we call that.

So for example in UsersController, we use the before_action so it’s going to check for their badge before it ever gives them any user information.

We can also set up some API endpoints to only give you information that’s related to your current user. So here when we’re asking for multiple team_memberships, it’ll only give you the memberships that are on the current_user, not all the memberships.

So that’s what having a badge gets you. That’s how it protects you. But just checking for the badge isn’t enough. You have to give the user a badge. And so, we do that in the sessions_controller. So what it does is you send it the email and the password, this is what happens when you login, and then it tries to authenticate that user with the password. And if it authenticates, then it returns the json with the user_id in the authentication_token, their badge, and if it doesn’t authenticate then it gives them back a 401, the ‘you’re not allowed here’ header.

So the specific Rails application for this is you do this with bcrypt,

and has_secure_password.

And then also whenever you save a user for the first time, we have some stuff set up so it’ll create the authentication token. And for the passwords, it has a password hash so it never stores the plain password in the database. That’s very important, never save the plain password.

Alright, so that is the Rails details, and I’ll go over this all as a system at the end after I go over the Ember stuff, and so that’ll help you when you’re trying to make it so you’re setting up with a different backend that’s not Rails.

So now we’re going to work on our Ember app.

This is the login method we had before. It’s obviously terrible. Let’s get rid of a lot of that terrible stuff, leaving the stuff that we’ll need to keep and put in somewhere in our new system.

Alright, so it’s returning a promise, and now we’re going to want to actually send something up to the server. We’ll do that with an ajax call. So we’ll take our ajax call, it’s a POST, and we’ll send it to the url: '/sessions' and send it the userName and password, and then it’ll get back the data. The data is the stuff that we’ve sent back from the create session method on our Rail server, so we’ll be getting the user_id and the authentication_token. So we’ve got our token and user.id and we’ll want to use those.

First, we’ll set the user.id cookie, and we’ll have to change this to an underscore so it’s setting the user ID so Ember knows what is happening, who signed in, and then, we’ll also need to set another cookie, the authenticationToken cookie, and that will of course be authentication_token and we’ll be using that to send up to the server.

And then we’ll want to sign in the user. We don’t have the user yet. We’ll need to grab that from the server. Luckily, we’ve already built in the initializeFromCookie method which is usually done on init, but we can call it here.

So that will take the userId, and it’ll just find that user from the store.

Alright. And finally we will resolve.

And of course we need to figure out how to reject it if it’s rejected, so we’ll put that in here, in the fail block.

Then we’ll need to do some cleanup on logout. So we remove the userId. We’ll also want to remove the authenticationToken.

So now that Ember has our badge, our authentication token set in our cookies, let’s go about using this, showing it on every request. How do we do that?

Well, one way is to create an initializer,

and what this initializer does is it will... we’ll use jquery ajaxPrefilter, and then we’ll set the request header, the X-CSRF-Token, to the token that is set in our cookies.

And so what this will do is every time we’re sending a request via ajax, it’ll set the request header, the X-CSRF-Token header, as the token. So this message of showing the token using the ajaxPrefilter will work on both Ember data calls and plain ajax calls.

If you’re sure that you’re only going to be using Ember data calls, then you can use the headers hash in your Ember data adapter.

So let’s try out our setup.

So as we can see, it redirects us back to Login as it should, and we can’t access other people’s data. But if we login, then it’ll correctly show us everything.

Let me walk you through every step of what just happened. So when the login method is called, it sends the userName and the password to the sessions create method in Rails.

And so in the sessions create method, it tries to authenticate it by email and password. And if that works, then it sends back the user_Id and the authentication_token.

Now that authentication token and user ID are set in the Cookies, and then the user is initialized from Cookies.

And so then whenever you send something, it’ll get passed through the ajaxPrefilter, and that’ll attach the authentication token to the request header.

Then in Rails, or your server, whenever you try to get something, it’ll get that request header, and then it’ll find the current_user from that token, like this.

And there are also places where it won’t get by unless that current_user exists and you have the right token, and we call that before most of our methods.

Of course if you have the correct X-CSRF-Token, then you’ll get what you had before and you’ll get all the information you need.

So that’s how you do token authentication with Ember and your backend server.

Next session, we’ll be talking about how to create a user. So we have how to login a user and how to authenticate that user and get what they need, but we need a way to create that user. We’ll do that next time. I’ll see you then.

User Auth

Subscribe to our mailing list