JWT Authentication in Angular
Introduction
In this lesson, we will explore JSON Web Token (JWT) authentication in Angular applications. JWT is a compact, URL-safe means of representing claims to be transferred between two parties. This lesson focuses on implementing JWT for secure API authentication in front-end applications.
What is JWT?
JWT is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed.
- Header: Contains metadata about the token, including type (JWT) and signing algorithm (e.g., HMAC SHA256).
- Payload: Contains the claims (information) being transmitted.
- Signature: Created by taking the encoded header, encoded payload, a secret, and the algorithm specified in the header.
How JWT Works
The typical flow of JWT authentication involves the following steps:
graph TD;
A[User Login] --> B[Server Validates Credentials];
B -->|Valid| C[Server Sends JWT];
B -->|Invalid| D[Error Message];
C --> E[User Accesses Protected Resources];
E --> F[Client Sends JWT in Authorization Header];
F --> G[Server Verifies JWT];
G -->|Valid| H[Access Granted];
G -->|Invalid| I[Access Denied];
Implementing JWT in Angular
To implement JWT in an Angular application, follow these steps:
- Set up a new Angular project (if not already created).
- Install necessary dependencies:
- Create a service to handle authentication:
- Use the AuthService in your component to handle login:
- Send the JWT in HTTP requests to protected routes:
npm install @auth0/angular-jwt
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class AuthService {
private apiUrl = 'https://example.com/api'; // Replace with your API URL
constructor(private http: HttpClient) {}
login(credentials: any): Observable {
return this.http.post(`${this.apiUrl}/login`, credentials)
.pipe(tap((response: any) => {
localStorage.setItem('token', response.token);
}));
}
}
import { Component } from '@angular/core';
import { AuthService } from './auth.service';
@Component({
selector: 'app-login',
templateUrl: './login.component.html'
})
export class LoginComponent {
constructor(private authService: AuthService) {}
onSubmit(form: any) {
this.authService.login(form.value).subscribe(response => {
console.log('Login successful!', response);
}, error => {
console.error('Login failed', error);
});
}
}
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable()
export class TokenInterceptor implements HttpInterceptor {
intercept(req: HttpRequest, next: HttpHandler): Observable> {
const token = localStorage.getItem('token');
if (token) {
const cloned = req.clone({
headers: req.headers.set('Authorization', `Bearer ${token}`)
});
return next.handle(cloned);
} else {
return next.handle(req);
}
}
}
Best Practices
- Always use HTTPS to protect JWTs in transit.
- Store JWTs securely (e.g., in HttpOnly cookies or secure storage).
- Implement token expiration and refresh mechanisms.
- Validate JWTs on the server side on every request.
- Use short-lived tokens and rotate them frequently.
FAQ
What is the difference between JWT and session-based authentication?
JWT is stateless, meaning the server does not store session information, while session-based authentication requires the server to maintain session data.
How do I handle token expiration?
Implement a refresh token mechanism to obtain a new token once the current one expires, or redirect users to the login page.
Can JWTs be stored in localStorage?
Yes, but it's recommended to use HttpOnly cookies for better security against XSS attacks.