Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Authenticating SPAs Using JWT

DZone's Guide to

Authenticating SPAs Using JWT

If you are looking to secure your single page application through a token-based authentication system, then this post is definitely for you.

· Security Zone ·
Free Resource

Discover how to provide active runtime protection for your web applications from known and unknown vulnerabilities including Remote Code Execution Attacks.

A successful token authentication system requires you to know security details and other authentication credentials. SPA’ are often tied to a Restful API to bind your UI with the required data and give your UI a much better look and feel. But the question is, how do you open your API access in a secure way?

One such SPA framework is Angular. We can authenticate our Angular applications with the help of JSON Web token-based authentication. So, when you are creating your Angular application, one big question is, how do you know who your users are and what they can access?

An answer to all such questions and a solution to authentication and authorization problems for APIs is the JWT authentication system which is replacing traditional cookie-based authentication. This gives you an amazing way to declare a user and their access permissions in the application. It gives you an encrypted header as a token to secure your apps from unauthenticated users and build access control logic for your front-end and backend.

Let’s dive deeper into it by looking at several pieces of code for authentication in your Angular app (version 2+).

Front-End Work

When a user makes a login request, we make the call to backend through our authentication service, as shown below:

login(username: string, password: string): Observable < boolean > {
    return this.http.post('/api/authenticate', JSON.stringify({
            username: username,
            password: password
        }))
        .map((response: Response) => {
            // login successful if there's a jwt token in the response
            let token = response.json() && response.json().token;
            if (token) {
                // set token property
                this.token = token;
                // store username and jwt token in local storage to keep user logged in between page refreshes
                localStorage.setItem('currentUser', JSON.stringify({
                    username: username,
                    token: token
                }));
                // return true to indicate successful login
                return true;
            } else {
                // return false to indicate failed login
                return false;
            }
        });
}

Server-Side Work

When a user tries to log in to the application with their username and password, the server will:

  • Authenticate the user.

  • Generate the token.

  • Send the token to the user.

The backend could be any server-side framework like Node.js that uses the npm ‘jsonwetoken’ module to sign and verify JSON web tokens. Below is some sample code:

Modules:

var jwt = require("jsonwebtoken");
var bcrypt = require("bcryptjs");

And the login function:

  login: function (req, res) {
      // this is param checking if they are provided 
    if (!_.has(req.body, 'email') || !_.has(req.body, 'password')) {
      return res.serverError("No field should be empty.");
    }
      // check if the username matches any email or phoneNumber
    User.findOne({
      email: req.body.email
    }).exec(function callback(err, user) {
      if (err) return res.serverError(err);
      if (!user) return res.serverError("User not found, please sign up.");
      //check password
      bcrypt.compare(req.body.password, user.password, function (error, matched) {
        if (error) return res.serverError(error);
        if (!matched) return res.serverError("Invalid password.");
      //save the date the token was generated for already inside toJSON()
        var token = jwt.sign(user.toJSON(), "this is my secret key", {
          expiresIn: '10m'
        });
       //return the token here
        res.ok(token);
      });
    });
  }

How Does the Token Return Work?

After the user successfully logs in using his credentials, a web token is returned that is stored in local storage. Now, whenever the user wants to access a protected route, it should send the JWT in the authorization header using the Bearer schema. The content of the header looks like:

Authorization: Bearer 

Thus, JWT will be used to authenticate and authorize APIs which will grant access to their protected routes and resources.

Handling Web Tokens With Angular

Since the JWT is now stored in our local storage, we can use it to prevent unauthenticated users from accessing restricted routes. It’s used in routing modules to protect any route. For this purpose, we use AuthGuard in Angular 2. AuthGuard uses the CanActivate method from @angular/router.

import { Injectable } from '@angular/core';
import { Router, CanActivate } from '@angular/router';
@Injectable()
export class AuthGuard implements CanActivate {
    constructor(private router: Router) { }
    canActivate() {
        if (localStorage.getItem('currentUser')) {
        // logged in so return true
            return true;
        }
        // not logged in so redirect to login page
        this.router.navigate(['/login']);
        return false;
    }
}

Thus, the route can be protected in the routing module like this:

{ path: '', component: SomeComponent, canActivate: [AuthGuard] } 

Next, we use this token to fetch the data our SPA needs. It gives the access to the user's API endpoint. This endpoint would respond with the data your SPA needs for the user. We can use the user service as shown below.

  getUsers(): Observable<User[]> {
        // add authorization header with jwt token
        let headers = new Headers({ 'Authorization': 'Bearer ' + this.authenticationService.token });
        let options = new RequestOptions({ headers: headers });
        // get users from api
        return this.http.get('/api/users', options)
            .map((response: Response) => response.json());
  }

Notice how we attach headers using RequestOptions with the Authorization Bearer discussed above. For this purpose, another module from npm could be used, i.e. ‘angular2-jwt.’ It is a helper library for working with JWTs in Angular 2 apps. It automatically attaches a JWT as an authorization header when making HTTP requests from your app. It sends a JWT request using its AuthHttp class (imported in your app.module.ts as a factory function in providers) and thereby conditionally allows route navigation based on the JWT status. It can be installed as shown below.

npm install angular2-jwt 

AuthHTTP can be used when calling A user's API as demonstrated below:

  // get users from api
        return this.authHttp.get('/api/users')
            .map((response: Response) => response.json());

In Closing

My idea for this post was to give you all an overview of JWTs and how you can use them to secure your single page applications. I hope I was able to deliver some insight. Happy securing!

Find out how Waratek’s award-winning application security platform can improve the security of your new and legacy applications and platforms with no false positives, code changes or slowing your application.

Topics:
jwt ,json web tokens ,web application security ,security ,angular application development

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}