Implementing authentication using JWT and $httpInterceptor

Loading

JSON Web Token (JWT) authentication is widely used for securing web applications. In AngularJS, we can implement JWT-based authentication using $httpInterceptor to attach tokens to API requests and handle responses efficiently.


1. What is JWT Authentication?

JWT authentication is a token-based authentication mechanism where:

  1. The client sends credentials (username/password) to the server.
  2. The server validates credentials and returns a JWT token.
  3. The client stores the token (usually in localStorage or sessionStorage).
  4. The client sends this token with each request.
  5. The server verifies the token and responds with the requested data.

2. Setting Up the AngularJS Application

Step 1: Define AngularJS Module

First, create an AngularJS module for authentication.

var app = angular.module('myApp', []);

3. Creating the Authentication Service

The authentication service will handle:

  • Logging in
  • Storing the token
  • Checking authentication status
  • Logging out

Step 2: Create AuthService

app.factory('AuthService', function($http, $window) {
var authService = {};

// Login Function
authService.login = function(credentials) {
return $http.post('/api/login', credentials).then(function(response) {
$window.localStorage.setItem('token', response.data.token);
return response.data;
});
};

// Check if user is authenticated
authService.isAuthenticated = function() {
return !!$window.localStorage.getItem('token');
};

// Logout Function
authService.logout = function() {
$window.localStorage.removeItem('token');
};

return authService;
});

Explanation:

  • login(credentials): Sends credentials to the server and stores the token.
  • isAuthenticated(): Checks if a token exists.
  • logout(): Removes the token from local storage.

4. Using $httpInterceptor to Attach JWT Token to Requests

Interceptors help modify API requests by automatically attaching the JWT token.

Step 3: Create AuthInterceptor

app.factory('AuthInterceptor', function($window) {
return {
request: function(config) {
var token = $window.localStorage.getItem('token');
if (token) {
config.headers.Authorization = 'Bearer ' + token;
}
return config;
},
responseError: function(response) {
if (response.status === 401) {
$window.localStorage.removeItem('token'); // Remove invalid token
alert('Unauthorized! Please log in again.');
}
return response;
}
};
});

Explanation:

  • The request method adds an Authorization header to all outgoing requests.
  • The responseError method handles 401 Unauthorized errors by clearing the token and alerting the user.

5. Registering $httpInterceptor in AngularJS

After creating the interceptor, we must register it in our app.

Step 4: Configure Interceptor

app.config(function($httpProvider) {
$httpProvider.interceptors.push('AuthInterceptor');
});

This ensures all HTTP requests pass through the AuthInterceptor before reaching the server.


6. Creating Login and Logout Functionality

Now, let’s create a controller that handles user authentication.

Step 5: Create LoginController

app.controller('LoginController', function($scope, AuthService, $window) {
$scope.credentials = {};
$scope.isLoggedIn = AuthService.isAuthenticated();

$scope.login = function() {
AuthService.login($scope.credentials).then(function(response) {
$scope.isLoggedIn = true;
alert("Login Successful!");
}).catch(function(error) {
alert("Login Failed!");
});
};

$scope.logout = function() {
AuthService.logout();
$scope.isLoggedIn = false;
alert("Logged out!");
};
});

Explanation:

  • login(): Calls AuthService.login(), updates authentication status, and shows an alert.
  • logout(): Calls AuthService.logout() and clears authentication state.

7. Creating the Login Form

Step 6: Add Login Form in index.html

<!DOCTYPE html>
<html ng-app="myApp">
<head>
<title>JWT Authentication</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="LoginController">

<div ng-if="!isLoggedIn">
<h2>Login</h2>
<input type="text" ng-model="credentials.username" placeholder="Username">
<input type="password" ng-model="credentials.password" placeholder="Password">
<button ng-click="login()">Login</button>
</div>

<div ng-if="isLoggedIn">
<h2>Welcome!</h2>
<button ng-click="logout()">Logout</button>
</div>

</body>
</html>

What happens here?

  • If the user is not logged in, they see a login form.
  • If they are logged in, they see a logout button.

8. Server-Side Authentication (Node.js & Express Example)

To complete the flow, we need a backend to validate credentials and issue JWTs.

Example Server Code (Node.js + Express + JWT)

const express = require('express');
const jwt = require('jsonwebtoken');
const bodyParser = require('body-parser');

const app = express();
const SECRET_KEY = 'your_secret_key';

app.use(bodyParser.json());

const users = [{ username: 'admin', password: 'password123' }];

// Login Route
app.post('/api/login', (req, res) => {
const { username, password } = req.body;
const user = users.find(u => u.username === username && u.password === password);

if (!user) {
return res.status(401).json({ message: 'Invalid credentials' });
}

const token = jwt.sign({ username }, SECRET_KEY, { expiresIn: '1h' });
res.json({ token });
});

// Protected Route
app.get('/api/protected', (req, res) => {
const token = req.headers.authorization?.split(' ')[1];

if (!token) {
return res.status(401).json({ message: 'Unauthorized' });
}

try {
const decoded = jwt.verify(token, SECRET_KEY);
res.json({ message: 'Access granted', user: decoded });
} catch (error) {
res.status(403).json({ message: 'Invalid token' });
}
});

app.listen(3000, () => console.log('Server running on port 3000'));

Explanation:

  • The /api/login route validates credentials and returns a JWT.
  • The /api/protected route checks for a valid token before allowing access.

9. Testing Authentication Flow

  1. Start the backend server (node server.js).
  2. Open the AngularJS frontend in a browser.
  3. Enter username & password (admin / password123).
  4. Click “Login” → A token is stored, and the UI updates.
  5. Click “Logout” → The token is cleared.

Leave a Reply

Your email address will not be published. Required fields are marked *