Skip to content

Implement the Access Guard and Secure the Customers Route #18

@hazartilirot

Description

@hazartilirot

Here would be a tricky one.

Open your guard directory in a terminal window, and enter the following:
ng generate guard Access

In the app.module.ts file, in the bottom, paste the code:

export class AppModule {
    constructor(private injector: Injector) {
        AppInjector = this.injector;
    }
}

Right after all imports and before @NgModule paste the piece:
export let AppInjector: Injector;

you would also need to import Injector
import { Injector, NgModule } from "@angular/core";

I leave my complete authentication.service.ts,

import { Inject, Injectable, Injector } from "@angular/core";

import { AuthenticationRequest } from "../../models/authentication-request";
import { AuthenticationResponse } from "../../models/authentication-response";
import { Observable } from "rxjs";
import { HttpClient } from "@angular/common/http";
import { JwtHelperService } from "@auth0/angular-jwt";
import { Router } from "@angular/router";

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

    constructor(
        private http: HttpClient,
        private router: Router,
    ) {
    }

    authenticate(credentialsForLogin: AuthenticationRequest): Observable<AuthenticationResponse> {
        return this.http.post<AuthenticationResponse>(
            "http://localhost:8080/api/v1/auth/login",
            credentialsForLogin
        );
    }

    setSession(authenticationResponse: AuthenticationResponse): void {
        localStorage.setItem("userId", `${authenticationResponse.customerDto.id}`);
        localStorage.setItem("token", authenticationResponse.token);
    }

    isSessionValid(): boolean {
        const userId: number = Number(localStorage.getItem("userId"));
        const token: string = localStorage.getItem("token");

        if (this.isLocalStorageInfringed(userId, token) || this.isTokenExpired(token)) {
            this.logout();
            return false;
        }
        return true;
    }

    private logout(): void {
        localStorage.clear();
        this.router.navigate(["login"])
    }

    private isTokenExpired(token: string): boolean {
        return new JwtHelperService().isTokenExpired(token);
    }

    private isLocalStorageInfringed(userId: number, token: string): boolean {
        return !userId || !token;
    }
}

in login.component.ts insert in constructor

if (authenticationService.isSessionValid()) {
            router.navigate(["customer"]);
        }

the login function in the same file has setSeesion method you need to place

next: authenticationResponse => {
                    this.authenticationService.setSession(authenticationResponse);
                    this.router.navigate(["customer"]);
                },

Now the Guard itself.... I just don't know how to create an instance in the method... It complains on httpClient, then router.... so I've found a solution relying on injection

import { CanActivateFn } from "@angular/router";
import { AuthenticationService } from "../authentication/authentication.service";
import { AppInjector } from "../../app.module";

export const accessGuard: CanActivateFn = (route, state) => {
    return AppInjector.get(AuthenticationService).isSessionValid()
};

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions