How to Implement Authentication With JWT in Angular SPAs
Implementing authentication in Single Page Applications (SPAs) is crucial for securing user data and providing a seamless user experience. JSON Web Tokens (JWT) have become a popular method for handling authentication in modern web applications, especially within Angular frameworks. This article will guide you through the process of implementing JWT authentication in Angular SPAs.
What is JWT?
JSON Web Tokens (JWT) are an open standard for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs are commonly used in authentication scenarios where you need to ensure that the user making a request is indeed the authenticated user.
Setting Up Your Angular Application
First, ensure you have an Angular application set up. If you don't have an existing project, create a new one using Angular CLI:
ng new jwt-authentication-app
Installing Required Dependencies
To handle HTTP requests and JWT storage, you need to install a few packages:
npm install @auth0/angular-jwt
This library helps with intercepting HTTP requests to attach the JWT token to them.
Creating the Authentication Service
Next, create a service to manage authentication functions, including login and logout operations:
ng generate service auth
In the `auth.service.ts` file, add methods for logging in, logging out, and checking if the user is authenticated:
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Router } from '@angular/router';
import { BehaviorSubject } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class AuthService {
private token: string | null = null;
private loggedInSubject: BehaviorSubject = new BehaviorSubject(false);
constructor(private http: HttpClient, private router: Router) {}
login(username: string, password: string) {
return this.http.post<{ token: string }>('/api/login', { username, password }).subscribe(
(response) => {
this.token = response.token;
localStorage.setItem('jwt_token', this.token);
this.loggedInSubject.next(true);
this.router.navigate(['/dashboard']);
}
);
}
logout() {
this.token = null;
localStorage.removeItem('jwt_token');
this.loggedInSubject.next(false);
this.router.navigate(['/login']);
}
isLoggedIn(): boolean {
return this.token !== null;
}
}
Setting Up Interceptor for Adding JWT to HTTP Requests
To automatically attach the JWT token to the Authorization header of HTTP requests, create an HTTP interceptor:
ng generate interceptor auth
Edit the `auth.interceptor.ts` file as follows:
import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
intercept(request: HttpRequest, next: HttpHandler): Observable> {
const token = localStorage.getItem('jwt_token');
if (token) {
request = request.clone({
setHeaders: {
Authorization: `Bearer ${token}`,
},
});
}
return next.handle(request);
}
}
Configuring the App Module
Don’t forget to register the interceptor in your app module. Edit `app.module.ts`:
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { AuthInterceptor } from './auth.interceptor';
@NgModule({
declarations: [...],
imports: [
HttpClientModule,
...
],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: AuthInterceptor,
multi: true,
},
],
bootstrap: [AppComponent],
})
export class AppModule {}
Creating Login and Logout Components
Now, create components for logging in and out:
ng generate component login
ng generate component dashboard
In the login component, add methods to handle login logic using the `AuthService`:
import { Component } from '@angular/core