Angular Lockdown: Router Security + JWT

Secure our angular application using route guards and jwt.

6 days ago

Latest Post Ansible to Slack by Matthew Davis

Today we're going to secure our angular application using route guards and jwt. We'll first declare a service to handle the mundane things and then a AuthGuard which implements CanActivate.

Before we get started you'll need to install @auth0/angular-jwt with an npm install @auth0/angular-jwt.

The AuthGuard

The AuthGuard is responsible for indicating whether or not a route should be accessible. This is configured in your routes declaration (further below). When a route is loaded it calls the canActivate method of our AuthGuard and will only route the user if true.

import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
import { Injectable } from '@angular/core';
import { AuthenticationService } from '@matthewdavis.io/ngsoa-api';

@Injectable()
export class AuthGuard implements CanActivate {

    public constructor(private router: Router) {
    }

    public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {

        if (AuthenticationService.isLoggedIn()) {

            return true;

        } else {

            this.router.navigate(['/login'], { queryParams: { returnUrl: state.url } });

            return false;
        }

    }

}
AuthGuard.ts

The AuthenticationService

The AuthenticationService is responsible for not only calling an http method for logging in but also checking to see if a) a "token" exists in localStorage but b) the token hasn't expired yet.

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { JwtHelperService } from '@auth0/angular-jwt';
import { Subject } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class AuthenticationService {

    public static getToken(): string {

        return localStorage.getItem('token');

    }

    public static isLoggedIn(): boolean {

        const helper = new JwtHelperService();

        const token: string = localStorage.getItem('token');

        if (token) {

            return !helper.isTokenExpired(token);

        }

    }
    
    public constructor(private httpClient: HttpClient) {

    }

    public isLoggedIn(): boolean {

        const helper = new JwtHelperService();

        const token: string = localStorage.getItem('token');

        if (token) {

            return !helper.isTokenExpired(token);

        }

    }

    public login(email: string, password: string): any {

        localStorage.removeItem('token');

        let subject: Subject<RequestResult<any> | boolean> = new Subject();

        this.post<any>(`users/login`, {

            email,
            password

        }).subscribe((result: any) => {

            if(result) {

            	subject.next(result);
                
            }

        });

        return subject;

    }

    public logout() {

        console.log('AutenticationService.logout()');

        this.clear();

        location.href = '/login';

    }

    public clear(): void {

        localStorage.removeItem('token');

    }

}
AuthenticationService.ts

Routing Configuration

Now we are ready to configure our route(s) to use canActivate by passing an array containing our AuthGuard Class.

canActivate will also apply to all children route(s) if present.
...
@NgModule({

    imports: [

        CommonModule,

        RouterModule.forRoot([

            {

                path: 'profile',
                component: ProfileComponent,
                canActivate: [ AuthGuard ],

                children: [
                
                	...
                    
                ]
                
            }
            
        ])
        
    ]
    
})
...
app.module.ts
Matthew Davis

Published 6 days ago

Comments?

Leave us your opinion.

powered by Typeform