Path: blob/main/extensions/copilot/src/shared-fetch-utils/common/middleware/authBlockedMiddleware.ts
13401 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { FetchBlockedError, type FetchMiddleware } from '../fetchTypes';67export class AuthBlockedError extends FetchBlockedError {8constructor(retryAfterMs: number) {9super(`Auth token blocked for ${Math.round(retryAfterMs / 1000)}s after 401/403`, retryAfterMs);10}11}1213/**14* After a `401` or `403` response, blocks the current auth token for15* {@link blockDurationMs} (default 1 hour). Subsequent requests with16* the same `Authorization` header are rejected immediately with an17* {@link AuthBlockedError}. If the token changes (e.g. the user18* re-authenticates) the block is cleared automatically.19*/20export function authBlockedMiddleware(21blockDurationMs: number = 60 * 60 * 1000,22): FetchMiddleware {23let blockedToken: string | undefined;24let blockedUntil = 0;2526return (next) => async (request) => {27const currentToken = request.headers['Authorization'] ?? request.headers['authorization'];2829// Token changed → clear block30if (currentToken !== blockedToken) {31blockedToken = undefined;32blockedUntil = 0;33}3435// Still blocked?36if (currentToken && currentToken === blockedToken && Date.now() < blockedUntil) {37throw new AuthBlockedError(blockedUntil - Date.now());38}3940const response = await next(request);4142if ((response.status === 401 || response.status === 403) && currentToken) {43blockedToken = currentToken;44blockedUntil = Date.now() + blockDurationMs;45throw new AuthBlockedError(blockDurationMs);46}4748return response;49};50}515253