Initial
This commit is contained in:
60
node_modules/@azure/msal-common/src/network/INetworkModule.ts
generated
vendored
Normal file
60
node_modules/@azure/msal-common/src/network/INetworkModule.ts
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
import {
|
||||
ClientAuthErrorCodes,
|
||||
createClientAuthError,
|
||||
} from "../error/ClientAuthError.js";
|
||||
import { NetworkResponse } from "./NetworkResponse.js";
|
||||
|
||||
/**
|
||||
* Options allowed by network request APIs.
|
||||
*/
|
||||
export type NetworkRequestOptions = {
|
||||
headers?: Record<string, string>;
|
||||
body?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Client network interface to send backend requests.
|
||||
* @interface
|
||||
*/
|
||||
export interface INetworkModule {
|
||||
/**
|
||||
* Interface function for async network "GET" requests. Based on the Fetch standard: https://fetch.spec.whatwg.org/
|
||||
* @param url
|
||||
* @param requestParams
|
||||
* @param enableCaching
|
||||
*/
|
||||
sendGetRequestAsync<T>(
|
||||
url: string,
|
||||
options?: NetworkRequestOptions,
|
||||
timeout?: number
|
||||
): Promise<NetworkResponse<T>>;
|
||||
|
||||
/**
|
||||
* Interface function for async network "POST" requests. Based on the Fetch standard: https://fetch.spec.whatwg.org/
|
||||
* @param url
|
||||
* @param requestParams
|
||||
* @param enableCaching
|
||||
*/
|
||||
sendPostRequestAsync<T>(
|
||||
url: string,
|
||||
options?: NetworkRequestOptions
|
||||
): Promise<NetworkResponse<T>>;
|
||||
}
|
||||
|
||||
export const StubbedNetworkModule: INetworkModule = {
|
||||
sendGetRequestAsync: () => {
|
||||
return Promise.reject(
|
||||
createClientAuthError(ClientAuthErrorCodes.methodNotImplemented)
|
||||
);
|
||||
},
|
||||
sendPostRequestAsync: () => {
|
||||
return Promise.reject(
|
||||
createClientAuthError(ClientAuthErrorCodes.methodNotImplemented)
|
||||
);
|
||||
},
|
||||
};
|
||||
10
node_modules/@azure/msal-common/src/network/NetworkResponse.ts
generated
vendored
Normal file
10
node_modules/@azure/msal-common/src/network/NetworkResponse.ts
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
export type NetworkResponse<T> = {
|
||||
headers: Record<string, string>;
|
||||
body: T;
|
||||
status: number;
|
||||
};
|
||||
47
node_modules/@azure/msal-common/src/network/RequestThumbprint.ts
generated
vendored
Normal file
47
node_modules/@azure/msal-common/src/network/RequestThumbprint.ts
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
import { ShrOptions } from "../crypto/SignedHttpRequest.js";
|
||||
import { BaseAuthRequest } from "../request/BaseAuthRequest.js";
|
||||
import { AuthenticationScheme } from "../utils/Constants.js";
|
||||
|
||||
/**
|
||||
* Type representing a unique request thumbprint.
|
||||
*/
|
||||
export type RequestThumbprint = {
|
||||
clientId: string;
|
||||
authority: string;
|
||||
scopes: Array<string>;
|
||||
homeAccountIdentifier?: string;
|
||||
claims?: string;
|
||||
authenticationScheme?: AuthenticationScheme;
|
||||
resourceRequestMethod?: string;
|
||||
resourceRequestUri?: string;
|
||||
shrClaims?: string;
|
||||
sshKid?: string;
|
||||
shrOptions?: ShrOptions;
|
||||
embeddedClientId?: string;
|
||||
};
|
||||
|
||||
export function getRequestThumbprint(
|
||||
clientId: string,
|
||||
request: BaseAuthRequest,
|
||||
homeAccountId?: string
|
||||
): RequestThumbprint {
|
||||
return {
|
||||
clientId: clientId,
|
||||
authority: request.authority,
|
||||
scopes: request.scopes,
|
||||
homeAccountIdentifier: homeAccountId,
|
||||
claims: request.claims,
|
||||
authenticationScheme: request.authenticationScheme,
|
||||
resourceRequestMethod: request.resourceRequestMethod,
|
||||
resourceRequestUri: request.resourceRequestUri,
|
||||
shrClaims: request.shrClaims,
|
||||
sshKid: request.sshKid,
|
||||
embeddedClientId:
|
||||
request.embeddedClientId || request.tokenBodyParameters?.clientId,
|
||||
};
|
||||
}
|
||||
154
node_modules/@azure/msal-common/src/network/ThrottlingUtils.ts
generated
vendored
Normal file
154
node_modules/@azure/msal-common/src/network/ThrottlingUtils.ts
generated
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
import { NetworkResponse } from "./NetworkResponse.js";
|
||||
import { ServerAuthorizationTokenResponse } from "../response/ServerAuthorizationTokenResponse.js";
|
||||
import {
|
||||
HeaderNames,
|
||||
ThrottlingConstants,
|
||||
Constants,
|
||||
} from "../utils/Constants.js";
|
||||
import { CacheManager } from "../cache/CacheManager.js";
|
||||
import { ServerError } from "../error/ServerError.js";
|
||||
import {
|
||||
getRequestThumbprint,
|
||||
RequestThumbprint,
|
||||
} from "./RequestThumbprint.js";
|
||||
import { ThrottlingEntity } from "../cache/entities/ThrottlingEntity.js";
|
||||
import { BaseAuthRequest } from "../request/BaseAuthRequest.js";
|
||||
|
||||
/** @internal */
|
||||
export class ThrottlingUtils {
|
||||
/**
|
||||
* Prepares a RequestThumbprint to be stored as a key.
|
||||
* @param thumbprint
|
||||
*/
|
||||
static generateThrottlingStorageKey(thumbprint: RequestThumbprint): string {
|
||||
return `${ThrottlingConstants.THROTTLING_PREFIX}.${JSON.stringify(
|
||||
thumbprint
|
||||
)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs necessary throttling checks before a network request.
|
||||
* @param cacheManager
|
||||
* @param thumbprint
|
||||
*/
|
||||
static preProcess(
|
||||
cacheManager: CacheManager,
|
||||
thumbprint: RequestThumbprint,
|
||||
correlationId: string
|
||||
): void {
|
||||
const key = ThrottlingUtils.generateThrottlingStorageKey(thumbprint);
|
||||
const value = cacheManager.getThrottlingCache(key);
|
||||
|
||||
if (value) {
|
||||
if (value.throttleTime < Date.now()) {
|
||||
cacheManager.removeItem(key, correlationId);
|
||||
return;
|
||||
}
|
||||
throw new ServerError(
|
||||
value.errorCodes?.join(" ") || Constants.EMPTY_STRING,
|
||||
value.errorMessage,
|
||||
value.subError
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs necessary throttling checks after a network request.
|
||||
* @param cacheManager
|
||||
* @param thumbprint
|
||||
* @param response
|
||||
*/
|
||||
static postProcess(
|
||||
cacheManager: CacheManager,
|
||||
thumbprint: RequestThumbprint,
|
||||
response: NetworkResponse<ServerAuthorizationTokenResponse>,
|
||||
correlationId: string
|
||||
): void {
|
||||
if (
|
||||
ThrottlingUtils.checkResponseStatus(response) ||
|
||||
ThrottlingUtils.checkResponseForRetryAfter(response)
|
||||
) {
|
||||
const thumbprintValue: ThrottlingEntity = {
|
||||
throttleTime: ThrottlingUtils.calculateThrottleTime(
|
||||
parseInt(response.headers[HeaderNames.RETRY_AFTER])
|
||||
),
|
||||
error: response.body.error,
|
||||
errorCodes: response.body.error_codes,
|
||||
errorMessage: response.body.error_description,
|
||||
subError: response.body.suberror,
|
||||
};
|
||||
cacheManager.setThrottlingCache(
|
||||
ThrottlingUtils.generateThrottlingStorageKey(thumbprint),
|
||||
thumbprintValue,
|
||||
correlationId
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks a NetworkResponse object's status codes against 429 or 5xx
|
||||
* @param response
|
||||
*/
|
||||
static checkResponseStatus(
|
||||
response: NetworkResponse<ServerAuthorizationTokenResponse>
|
||||
): boolean {
|
||||
return (
|
||||
response.status === 429 ||
|
||||
(response.status >= 500 && response.status < 600)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks a NetworkResponse object's RetryAfter header
|
||||
* @param response
|
||||
*/
|
||||
static checkResponseForRetryAfter(
|
||||
response: NetworkResponse<ServerAuthorizationTokenResponse>
|
||||
): boolean {
|
||||
if (response.headers) {
|
||||
return (
|
||||
response.headers.hasOwnProperty(HeaderNames.RETRY_AFTER) &&
|
||||
(response.status < 200 || response.status >= 300)
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the Unix-time value for a throttle to expire given throttleTime in seconds.
|
||||
* @param throttleTime
|
||||
*/
|
||||
static calculateThrottleTime(throttleTime: number): number {
|
||||
const time = throttleTime <= 0 ? 0 : throttleTime;
|
||||
|
||||
const currentSeconds = Date.now() / 1000;
|
||||
return Math.floor(
|
||||
Math.min(
|
||||
currentSeconds +
|
||||
(time || ThrottlingConstants.DEFAULT_THROTTLE_TIME_SECONDS),
|
||||
currentSeconds +
|
||||
ThrottlingConstants.DEFAULT_MAX_THROTTLE_TIME_SECONDS
|
||||
) * 1000
|
||||
);
|
||||
}
|
||||
|
||||
static removeThrottle(
|
||||
cacheManager: CacheManager,
|
||||
clientId: string,
|
||||
request: BaseAuthRequest,
|
||||
homeAccountIdentifier?: string
|
||||
): void {
|
||||
const thumbprint = getRequestThumbprint(
|
||||
clientId,
|
||||
request,
|
||||
homeAccountIdentifier
|
||||
);
|
||||
const key = this.generateThrottlingStorageKey(thumbprint);
|
||||
cacheManager.removeItem(key, request.correlationId);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user