Hone logo
Hone
Problems

Angular Authentication Interceptor

In modern web applications, securing API endpoints is crucial. This challenge focuses on implementing an authentication interceptor in Angular to automatically attach authentication tokens to outgoing HTTP requests. This pattern simplifies token management and ensures that all protected API calls are authenticated without manual intervention in each service.

Problem Description

You are tasked with creating an HttpInterceptor in Angular that intercepts all outgoing HTTP requests. This interceptor should check if a user is authenticated and, if so, add an authorization header (e.g., Authorization: Bearer <token>) to the request before it is sent to the server.

Key Requirements:

  • Intercept Outgoing Requests: The interceptor must be able to capture and modify outgoing HttpRequest objects.
  • Check for Authentication: The interceptor needs a mechanism to determine if a user is currently authenticated. For this challenge, assume you have a simple AuthService with an isAuthenticated() method and a getToken() method.
  • Add Authorization Header: If the user is authenticated, append an Authorization header. The header value should be Bearer followed by the authentication token obtained from the AuthService.
  • Handle Unauthenticated Requests: If the user is not authenticated, the request should proceed without the Authorization header.
  • Continue the Request Chain: The interceptor must pass the modified (or unmodified) request to the next interceptor in the chain or to the HttpClient itself.
  • Handle Errors Gracefully: If there's an issue retrieving the token or adding the header, the interceptor should not break the application.

Expected Behavior:

  • Requests to API endpoints requiring authentication will have the Authorization: Bearer <token> header.
  • Requests to public API endpoints will not have this header.
  • The application should function normally for both authenticated and unauthenticated users.

Edge Cases:

  • What happens if AuthService.getToken() returns null or undefined? The interceptor should handle this gracefully and not throw an error.
  • Consider requests that might already have an Authorization header. The interceptor should ideally append to or overwrite it as per specific application requirements. For this challenge, we'll assume it should add if not present or if the service indicates it's managed.

Examples

Example 1: Authenticated Request

// AuthService (mock)
class AuthService {
  isAuthenticated(): boolean { return true; }
  getToken(): string | null { return 'my-secret-token'; }
}

// An outgoing GET request to '/api/user/profile'
// The AuthService.isAuthenticated() returns true, and AuthService.getToken() returns 'my-secret-token'.

// Expected modified request sent to the server:
// Method: GET
// URL: /api/user/profile
// Headers:
//   Authorization: Bearer my-secret-token
//   Content-Type: application/json (or other default headers)

Explanation: Since the user is authenticated, the interceptor retrieves the token 'my-secret-token' and adds it to the request headers as Authorization: Bearer my-secret-token.

Example 2: Unauthenticated Request

// AuthService (mock)
class AuthService {
  isAuthenticated(): boolean { return false; }
  getToken(): string | null { return null; } // Or could be undefined
}

// An outgoing GET request to '/api/products'
// The AuthService.isAuthenticated() returns false.

// Expected request sent to the server:
// Method: GET
// URL: /api/products
// Headers:
//   Content-Type: application/json (or other default headers)
//   (No Authorization header is present)

Explanation: The user is not authenticated, so the interceptor does not add an Authorization header to the request.

Example 3: Edge Case - Token is null

// AuthService (mock)
class AuthService {
  isAuthenticated(): boolean { return true; } // User *thinks* they are authenticated
  getToken(): string | null { return null; }   // But token is missing
}

// An outgoing POST request to '/api/items'
// The AuthService.isAuthenticated() returns true, but AuthService.getToken() returns null.

// Expected request sent to the server:
// Method: POST
// URL: /api/items
// Headers:
//   Content-Type: application/json (or other default headers)
//   (No Authorization header is present, to avoid sending 'Bearer null')

Explanation: Even though isAuthenticated() returns true, getToken() returns null. The interceptor should detect this and not add an invalid Authorization header (like Bearer null). The request proceeds without the header.

Constraints

  • The interceptor must be implemented in TypeScript.
  • You will need to leverage Angular's HttpInterceptor interface.
  • Assume the existence of an AuthService with isAuthenticated() and getToken() methods. You do not need to implement the AuthService itself; you can mock it for testing purposes.
  • The interceptor should not introduce significant performance overhead.

Notes

  • Remember to register your interceptor in your Angular module.
  • Consider how your interceptor will handle different HTTP methods (GET, POST, PUT, DELETE, etc.). The logic should be consistent.
  • The AuthService is a simplification. In a real application, this service might interact with localStorage, sessionStorage, cookies, or a state management solution.
  • Think about how to clone the original request when modifying it. The HttpRequest object is immutable.
Loading editor...
typescript