JWT based authentication is the most common way for securely transmitting information between parties as a JSON object. Here is a simple and general guide to start with JWT in Angular.
In this guide we are going to deal with a basic login and profile page. Profile page can only be accessed if the user is logged in. We will also add route guards to prevent page access for unauthenticated users.
- A service for http communiction (
connector.service.ts
) - Routes and Routing Module
- Route Guard
- Http Interceptor
- JWT package:
@auth0/angular-jwt
(Optional)
Create 2 components : login and profile
ng g c login --spec false
ng g c profile --spec false
Create a service for http connection with backend
ng g s connector --spec false
Add @auth0/angular-jwt
package to play with jwt (Optional)
npm i --save @auth0/angular-jwt
Create a Routing Module
ng g m app-routing --flat --module=app --spec false
Modify the routing module as following
import { NgModule } from '@angular/core';
import { Routes, RouterModule, Router } from '@angular/router';
import { LoginComponent } from './login/login.component';
import { ProfileComponent } from './profile/profile.component';
const routes: Routes = [
{ path: '', redirectTo: '/login', pathMatch: 'full'},
{ path: 'login', component: LoginComponent },
{ path: 'profile', component: ProfileComponent }
]
@NgModule({
imports: [ RouterModule.forRoot(routes) ],
exports: [ RouterModule ]
})
export class AppRoutingModule { }
Put the <router-outlet></router-outlet>
in app.component.html
ng g s token-interceptor --spec false
import { Injectable } from '@angular/core';
import { HttpInterceptor } from '@angular/common/http'
@Injectable({
providedIn: 'root'
})
export class TokenInterceptorService implements HttpInterceptor {
constructor() { }
intercept(req, next) {
if (this.getToken()) {
let tokenizedReq = req.clone({
setHeaders : {
Authorization : "Bearer " + this.getToken()
}
})
return next.handle(tokenizedReq);
} else {
return next.handle(req);
}
}
private getToken() {
if (!!localStorage.getItem("token")) {
return localStorage.getItem("token")
} else {
return false;
}
}
}
...
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { TokenInterceptorService } from './token-interceptor.service';
...
@NgModule({
...
providers: [
...,
TokenInterceptorService,
{
provide: HTTP_INTERCEPTORS,
useClass: TokenInterceptorService,
multi: true
}
]
})
export class AppRoutingModule { }
We will create a seperate service that will handle all http requests(get + post) and will also take care of authorization token
ng g s connector --spec false
Content of connector.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http'
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class ConnectorService {
constructor(
private http: HttpClient
) { }
public getRequest(url,params) : Observable<any> {
return this.http.get(
url,
{
params : params
}
)
}
public postRequest(url, params) : Observable<any> {
return this.http.post(
url,
{
params : params
}
)
}
}
ng g guard auth --spec false
Content of auth.guard.ts
import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
constructor(
private router : Router
) {}
canActivate() {
if (!this.checkToken()) {
// not allowed, redirect to login
this.router.navigate(["/login"]);
return false;
} else {
// allowed
return true;
}
}
public checkToken() {
return !!localStorage.getItem("auth");
}
}
ng g module app-routing
Content of app-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule, Router } from '@angular/router';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { LoginComponent } from './login/login.component';
import { ProfileComponent } from './profile/profile.component';
import { TokenInterceptorService } from './token-interceptor.service';
import { AuthGuard } from './auth.guard';
const routes: Routes = [
{
path: 'profile',
component: ProfileComponent,
canActivate: [AuthGuard]
},
{
path: 'login',
component: LoginComponent
},
{
path: '',
redirectTo: '/login',
pathMatch: 'full'
},
]
@NgModule({
imports: [ RouterModule.forRoot(routes) ],
exports: [ RouterModule ],
providers: [
TokenInterceptorService,
{
provide: HTTP_INTERCEPTORS,
useClass: TokenInterceptorService,
multi: true
}
]
})
export class AppRoutingModule { }
Content of login.component.ts
import { Component, OnInit } from '@angular/core';
import { ConnectorService } from '../connector.service';
import { Router } from '@angular/router';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
public errorMsg;
public email;
public password;
public loginUrl;
constructor(
private connector : ConnectorService,
private router : Router
) { }
ngOnInit() {
this.loginUrl = "http://localhost/index.php"
}
login() {
let credentials = {
"email" : this.email,
"password" : this.password
};
this.connector.getRequest(this.loginUrl, credentials).subscribe(res => {
if (res["auth"] !== undefined) {
localStorage.setItem("auth", res["auth"]);
// redirect to profile page
this.router.navigate(["/profile"]);
}
})
}
}