Managing User Sessions with JWT-based Authentication in Angular: A Complete Guide
User authentication is an essential part of any web application, and managing user sessions is equally important. Session management involves tracking user activity and keeping them logged in until they explicitly log out or their session expires.
How to manage User Sessions with JWT-based Authentication in Angular
In Angular, JSON Web Tokens (JWTs) provide a secure way to authenticate users and manage their sessions. In this article, we will discuss how to implement JWT-based authentication and manage user sessions in Angular.
Step 1: Set up the Angular project
First, create a new Angular project using the Angular CLI:
ng new my-app
cd my-app
Step 2: Install the necessary dependencies
Next, install the following dependencies:
npm install @auth0/angular-jwt
npm install jwt-decode
Step 3: Create the authentication service
Create a new service called auth.service.ts
using the following command:
ng g service auth
This service will handle the user authentication and session management logic. Here is an example implementation:
import { Injectable } from '@angular/core';
import { JwtHelperService } from '@auth0/angular-jwt';
import { Router } from '@angular/router';
import { HttpClient } from '@angular/common/http';
import { tap } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class AuthService {
private readonly apiUrl = 'https://my-api.com';
constructor(
private readonly jwtHelper: JwtHelperService,
private readonly router: Router,
private readonly http: HttpClient
) {}
login(username: string, password: string) {
return this.http.post<{ token: string }>(`${this.apiUrl}/auth/login`, { username, password })
.pipe(
tap(res => {
localStorage.setItem('access_token', res.token);
})
);
}
logout() {
localStorage.removeItem('access_token');
this.router.navigate(['/login']);
}
isAuthenticated() {
const token = localStorage.getItem('access_token');
return !this.jwtHelper.isTokenExpired(token);
}
}
Step 4: Implement the authentication flow
Now that we have the AuthService
in place, let's implement the authentication flow. Create a new component called login.component.ts
that will handle user login:
import { Component } from '@angular/core';
import { AuthService } from '../auth.service';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent {
username: string;
password: string;
constructor(private readonly authService: AuthService) {}
onSubmit() {
this.authService.login(this.username, this.password).subscribe(
() => {
if (this.authService.isAuthenticated()) {
this.router.navigate(['/dashboard']);
}
},
(error) => {
console.log(error);
}
);
}
}
In the login.component.html
template, create a simple form with two input fields for the username and password:
<form (ngSubmit)="onSubmit()">
<input type="text" [(ngModel)]="username" name="username" placeholder="Username">
<input type="password" [(ngModel)]="password" name="password" placeholder="Password">
<button type="submit">Log in</button>
</form>
Step 5: Protect your routes
To protect your routes, create a
new route guard called auth.guard.ts
that will check if the user is authenticated before allowing them to access protected routes:
import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';
import { AuthService } from './auth.service';
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
constructor(private readonly authService: AuthService, private readonly router: Router) {}
canActivate(): boolean {
if (!this.authService.isAuthenticated()) {
this.router.navigate(['/login']);
return false;
}
return true;
}
}
Finally, add the AuthGuard
to the routes that you want to protect:
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { DashboardComponent } from './dashboard/dashboard.component';
import { LoginComponent } from './login/login.component';
import { AuthGuard } from './auth.guard';
const routes: Routes = [
{ path: 'login', component: LoginComponent },
{ path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard] }
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
Step 6: Decode the JWT token
Finally, to display user information or perform other actions based on the user's identity, you need to decode the JWT token. To do this, create a new method in the AuthService
called getUserInfo()
:
import { Injectable } from '@angular/core';
import { JwtHelperService } from '@auth0/angular-jwt';
import { Router } from '@angular/router';
import { HttpClient } from '@angular/common/http';
import { tap } from 'rxjs/operators';
import jwt_decode from 'jwt-decode';
@Injectable({
providedIn: 'root'
})
export class AuthService {
private readonly apiUrl = 'https://my-api.com';
constructor(
private readonly jwtHelper: JwtHelperService,
private readonly router: Router,
private readonly http: HttpClient
) {}
login(username: string, password: string) {
return this.http.post<{ token: string }>(`${this.apiUrl}/auth/login`, { username, password })
.pipe(
tap(res => {
localStorage.setItem('access_token', res.token);
})
);
}
logout() {
localStorage.removeItem('access_token');
this.router.navigate(['/login']);
}
isAuthenticated() {
const token = localStorage.getItem('access_token');
return !this.jwtHelper.isTokenExpired(token);
}
getUserInfo() {
const token = localStorage.getItem('access_token');
return jwt_decode(token);
}
}
Conclusion:
In this article, we discussed how to manage user sessions with JWT-based authentication in Angular. We started by setting up the Angular project, installing the necessary dependencies, and creating the AuthService
to handle user authentication and session management. Then implemented the authentication flow, protected our routes with the AuthGuard
, and finally decoded the JWT token to display user information. By following these steps, you can secure your Angular application and manage user sessions effectively.