Protecting Your APIs with JWTs

or

How to secure your API so that it can be accessed by any device, including Angularjs

First lets ask the question

what is authentication?

Why do we need authentication?

How have we implemented authentication so far?

Cookie based auth

What are the problems?

  • Tightly couple the client and server
  • Limits the types of clients to browsers

What is the solution?

We need something that is

  • universal (all languages can handle)
  • persistant (can be stored in the DB)
  • trusted

We need a token

Story Time

Introducing JWTs

Stands for JSON Web Tokens

Pronounced JOT

Almost every language can use them

Lets make a JWT

var jwt = require('jsonwebtoken');

var payload = {id: 0};
var secret = 'wyuflgjwuylf';
var options = {};

jwt.sign(payload, secret, options, getToken);

function getToken(token){
  console.log(token);
}
angular-auth git:(auth) ✗ node creating-token.js
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MCwiaWF0IjoxNDU2NzgzMzk0fQ.yUuF48IMzTP0xIElmeHeQyaxy81jtRR8fU7xEBVz-aU
➜  angular-auth git:(auth) ✗ 

That results in

Lets verify a JWT

jwt.verify(token, secret, options, verifyToken);

function verifyToken(err, decoded){
  console.log(decoded);
}
➜  angular-auth git:(auth) ✗ node verify-token.js
{ id: 0, iat: 1456784065 }
➜  angular-auth git:(auth) ✗ 

That results in

Practice

  • Create a JWT
  • Slack it to someone in the room
  • Verify the JWT and extract the payload

Use the super secure secret:

galvanize_rocks!

Now for something different

Using JWTs with Angularjs

Using tokens with Angular is simple

  • When you get the token, save it to local storage
  • For every $http request to the api, add the token to the header
  • If there is an unauthenticated error, delete the token, and send the user back to the login route.
  • When the user logs out, delete the token and send the user back to the login route

Login controller

app.controller('LoginController', login);

function($scope, AuthService, LocalStorageService, $location){
  $scope.login = function(form){
    AuthService.login(form.username, form.password)
      .then(userLoggedIn);
  }

  function userLoggedIn(result){
    LocalStorageService.set('token', result.token);

    $location.path('/dashboard');
  }
}

Auth service

app.service('AuthService', auth);

function auth($http){
  function login(username, password){
    return $http({
      method: 'POST',
      url: '/api/v1/users/login',
      data: {
        username: username,
        password: password
      }
    });
  }

  return {
    login: login
  };
}

LocalStorage Service

app.service('LocalStorageService', localStorage);

function localStorage(){
  function set(key, value) {
    localStorage.setItem(key, value);
  }

  return {
    set: set
  };
}

Setting Headers on $http

app.service('BookService', book);

function book($http, LocalStorageService){
  function edit(dataToUpdate){
    var token = LocalStorageService.get('token');

    return $http({
      method: 'PUT',
      url: '/api/v1/books/' + dataToUpdate.id,
      headers: {
        token: token
      },
      data: dataToUpdate
    });
  }

  return {
    edit: edit
  };
}

Your turn

How would you delete the token?

Questions?

Your Turn

Start building that app!

apis-jwts-and-angularjs

By Brooks Patton

apis-jwts-and-angularjs

Ok, so you've built a great full-stack single page application by creating an API, and an angularjs app. However you are missing that one thing that makes it ready for users. Authentication. Well that is what we are going to talk about here, authentication for apis and angularjs.

  • 1,105