Introduction
In modern web development, implementing secure authentication and authorization mechanisms is of utmost importance. JSON Web Token (JWT) has emerged as a popular solution for handling user authentication and authorization securely. JWTs offer numerous advantages, such as statelessness and enhanced security, making them a preferred choice for web application developers. In this blog, we will explore the implementation of JWT for authorization in an Angular web application with practical examples.
If you want to learn more about the Principles and Concepts of Functional Programming, please refer here.
What is JSON Web Token (JWT)?
JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way of transmitting information between parties as a JSON object. JWTs are commonly used to authenticate users and transmit user-related information securely. A JWT consists of three parts: a header, a payload, and a signature.
- Header: Contains metadata about the token, such as the type and signing algorithm used.
- Payload: Contains the claims (data) about the user, roles, or other information.
- Signature: Used to verify the authenticity of the token and ensure that it hasn’t been tampered with.
The Process of JWT Authorization
The process of JWT-based authorization in an Angular web application can be broken down into the following steps:
- User Authentication: Users provide their credentials (e.g., username and password) to the server for authentication.
- Server Validation: The server validates the credentials and, upon successful validation, generates a JWT.
- JWT Issuance: The server signs the JWT with a secret key and sends it back to the client (Angular application).
- Client Storage: The Angular application stores the received JWT, usually in local storage or cookies.
- Subsequent Requests: For each subsequent API request, the Angular application includes the JWT in the request headers for authorization.
- JWT Verification: The server verifies the authenticity of the JWT, ensuring it is valid and unaltered.
- Access Control: The server decodes the JWT and extracts user information to determine if the user is authorized to access the requested resource.
Example Implementation in Angular
Now, let’s dive into a practical example of implementing JWT-based authorization in an Angular web application. We’ll assume you have the latest version of Angular CLI installed.
Step 1: Create a New Angular Project
Open your terminal and run the following command to create a new Angular project:
ng new jwt-authorization-example
cd jwt-authorization-example
Step 2: Install Dependencies
We will need jsonwebtoken
library to decode the JWT on the client-side. Install it using npm:
npm install jsonwebtoken --save
Step 3: Create Services for Authentication and JWT Handling
Create an auth.service.ts
file to handle user authentication and JWT-related functions:
// auth.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
import * as jwt_decode from 'jsonwebtoken';
@Injectable({
providedIn: 'root',
})
export class AuthService {
private apiUrl = 'http://your-api-url/auth'; // Replace with your API URL
constructor(private http: HttpClient) {}
login(username: string, password: string): Observable<any> {
return this.http
.post<any>(`${this.apiUrl}/login`, { username, password })
.pipe(
tap((response) => {
if (response && response.token) {
localStorage.setItem('jwt_token', response.token);
}
})
);
}
logout(): void {
localStorage.removeItem('jwt_token');
}
getToken(): string {
return localStorage.getItem('jwt_token');
}
getDecodedToken(): any {
const token = this.getToken();
return jwt_decode(token);
}
isLoggedIn(): boolean {
const token = this.getToken();
return !!token;
}
}
Step 4: Create the LoginComponent
Generate a new component using the Angular CLI:
ng generate component login
Modify the login.component.ts
file to include the login functionality:
// login.component.ts
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { AuthService } from '../auth.service';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css'],
})
export class LoginComponent {
username = '';
password = '';
constructor(private authService: AuthService, private router: Router) {}
onSubmit(): void {
this.authService.login(this.username, this.password).subscribe(
() => {
this.router.navigate(['/dashboard']); // Redirect to the dashboard after successful login
},
(error) => {
console.error(error);
// Handle error (e.g., display a message to the user)
}
);
}
}
Step 5: Create the DashboardComponent
Generate another component using the Angular CLI:
ng generate component dashboard
Modify the dashboard.component.ts
file to include the authorization logic:
// dashboard.component.ts
import { Component } from '@angular/core';
import { AuthService } from '../auth.service';
@Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.css'],
})
export class DashboardComponent {
user: any;
constructor(private authService: AuthService) {
this.user = authService.getDecodedToken();
}
onLogout(): void {
this.authService.logout();
}
}
Step 6: Create the Routes
Update the app-routing.module.ts
file to define the routes and protect the dashboard route:
// app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { LoginComponent } from './login/login.component';
import { DashboardComponent } from './dashboard/dashboard.component';
import { AuthGuard } from './auth.guard';
const routes: Routes = [
{ path: 'login', component: LoginComponent },
{ path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard] },
{ path: '', redirectTo: '/login', pathMatch: 'full' },
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
})
export class AppRoutingModule {}
Step 7: Create the AuthGuard
Generate an AuthGuard service using the Angular CLI:
ng generate guard auth
Modify the auth.guard.ts
file to handle route protection:
// auth.guard.ts
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 authService: AuthService, private router: Router) {}
canActivate(): boolean {
if (this.authService.isLoggedIn()) {
return true;
} else {
this.router.navigate(['/login']);
return false;
}
}
}
Conclusion
In this blog, we have explored the implementation of JSON Web Tokens (JWT) for authorization in an Angular web application. JWTs provide a secure and efficient way of handling user authentication and authorization, enhancing the security and scalability of your web applications. By following the examples and steps above, you can create a robust JWT-based authorization system for your Angular applications.
However, it’s essential to stay updated with the latest security best practices and consider additional security measures to safeguard your application against potential threats. Always remember to keep your secret keys secure, use HTTPS to encrypt data during transit, and implement proper token management.
With JWT-based authorization in place, you can confidently build secure and user-friendly web applications while ensuring seamless user experiences. Happy coding!
Finally, for more such posts, please follow our LinkedIn page- FrontEnd Competency.