Storing authentication tokens securely in localStorage

Loading

Authentication tokens (such as JWTs) must be securely stored to prevent unauthorized access or token theft. While localStorage is a common option for storing tokens in AngularJS, it has security risks that should be mitigated.


1. Choosing the Right Storage Mechanism

There are multiple ways to store authentication tokens in AngularJS:

  • localStorage: Persistent storage across sessions (Risk: Vulnerable to XSS attacks)
  • sessionStorage: Similar to localStorage, but data is cleared when the tab is closed
  • Cookies (HttpOnly, Secure): More secure but requires server-side handling
  • Memory (AngularJS Service): Most secure against XSS but lost on page reload

For most web apps, localStorage with additional security measures is a practical approach.


2. Creating an Authentication Service to Manage Tokens

A dedicated AuthService can handle token storage, retrieval, and security measures.

a. Define AuthService

angular.module('myApp')
.service('AuthService', function ($window) {

var TOKEN_KEY = 'authToken';

// Save token securely
this.setToken = function (token) {
if (token) {
$window.localStorage.setItem(TOKEN_KEY, token);
}
};

// Retrieve token
this.getToken = function () {
return $window.localStorage.getItem(TOKEN_KEY);
};

// Remove token on logout
this.clearToken = function () {
$window.localStorage.removeItem(TOKEN_KEY);
};

// Check if user is authenticated
this.isAuthenticated = function () {
return !!this.getToken();
};
});
  • Stores the token in localStorage
  • Provides methods to set, get, and clear tokens
  • Checks if the user is authenticated based on token presence

3. Enhancing Security for Storing Tokens

Since localStorage is accessible via JavaScript, it is vulnerable to Cross-Site Scripting (XSS) attacks. Below are additional security measures to mitigate risks:

a. Store Tokens in HttpOnly Secure Cookies (Better Security)

A better approach is to store tokens in HttpOnly, Secure cookies from the backend. This prevents JavaScript access and mitigates XSS attacks.

  • The server should set cookies using: Set-Cookie: authToken=your_jwt_token; HttpOnly; Secure; SameSite=Strict
  • This way, the frontend does not have direct access to the token.

b. Encrypt Tokens Before Storing (Optional)

If using localStorage, encrypt the token to reduce direct exposure:

this.setToken = function (token) {
var encryptedToken = btoa(token); // Base64 encode (consider stronger encryption)
$window.localStorage.setItem(TOKEN_KEY, encryptedToken);
};

this.getToken = function () {
var token = $window.localStorage.getItem(TOKEN_KEY);
return token ? atob(token) : null; // Decode
};

c. Clear Tokens on Logout and Expiration

  • Always clear tokens on logout to prevent misuse.
  • Handle expired tokens using an interceptor to detect 401 Unauthorized responses.

4. Attaching Tokens Securely in API Requests

To ensure secure communication, attach the token in every API request using $httpInterceptor.

angular.module('myApp')
.factory('AuthInterceptor', function ($window, AuthService) {
return {
request: function (config) {
var token = AuthService.getToken();
if (token) {
config.headers.Authorization = 'Bearer ' + token;
}
return config;
}
};
})
.config(function ($httpProvider) {
$httpProvider.interceptors.push('AuthInterceptor');
});
  • Automatically attaches the token to outgoing API requests.
  • Ensures secure communication using the Authorization header.

5. Auto Logout on Token Expiration

Detect expired tokens and force logout:

angular.module('myApp')
.factory('AuthInterceptor', function ($q, AuthService, $location) {
return {
responseError: function (response) {
if (response.status === 401 || response.status === 403) {
AuthService.clearToken();
$location.path('/login'); // Redirect to login on authentication failure
}
return $q.reject(response);
}
};
});

Leave a Reply

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