import { HttpError, HttpRequestOptions } from "@cognite/sdk-core"; import { BasicHttpClient } from "@cognite/sdk-core"; import { bearerTokenString, getTokenWithCogniteClient, RefreshMethod, WellsAuthFlowType, } from "./clientAuthUtils"; export default class HttpClientWithIntercept extends BasicHttpClient { private authenticatingWithToken = false; private refreshTokenMethod?: RefreshMethod; private authFlow?: WellsAuthFlowType; public set setReauthenticateMethod(method: RefreshMethod) { this.refreshTokenMethod = method; } public async refreshToken(originalErrorStatus: number): Promise { if (!(this.refreshTokenMethod && this.authFlow)) { throw new HttpError( originalErrorStatus, { error: { message: "Token is invalid, and no reauthentication method has been set for this client", }, }, {} ); } return await this.refreshTokenMethod(this.authFlow); } public set setAuthFlow(flow: WellsAuthFlowType) { this.authFlow = flow; } constructor(baseUrl: string) { super(baseUrl); } public set setIfUsingLoginToken(bool: boolean) { this.authenticatingWithToken = bool; } public get usesTokenLogin() { return this.authenticatingWithToken; } private updateHeaderWithNewToken(token: string) { this.setDefaultHeader("Authorization", bearerTokenString(token)); } /** * Basic HTTP method for GET * * @param path The URL path * @param options Request options, optional * */ public asyncGet = (path: string, options?: HttpRequestOptions) => { return this.get(path, options).catch(async (err) => { // if unauthorized unathorized 401 or forbbiden 403 occurs, try again with a new header if ((err.status === 401 || err.status === 403) && this.usesTokenLogin) { // update with new bearer token const newToken = await this.refreshToken(err.status); this.updateHeaderWithNewToken(newToken); // try again return this.get(path, options); } // rethrow throw err; }); }; /** * Basic HTTP method for PUT * * @param path The URL path * @param options Request options, optional * */ public asyncPut = (path: string, options?: HttpRequestOptions) => { return this.put(path, options).catch(async (err) => { // if unauthorized unathorized 401 or forbbiden 403 occurs, try again with a new header if ( (err.status === 401 || err.status === 403) && this.usesTokenLogin && this.authFlow != undefined ) { // update with new bearer token const newToken = await getTokenWithCogniteClient(this.authFlow); if (newToken == null && newToken == undefined) { throw new HttpError( 403, "Could not regenerate a new Bearer Token", {} ); } this.updateHeaderWithNewToken(newToken); // try again return this.put(path, options); } // rethrow throw err; }); }; /** * Basic HTTP method for POST * * @param path The URL path * @param options Request options, optional * */ public asyncPost = (path: string, options?: HttpRequestOptions) => { return this.post(path, options).catch(async (err) => { // if unauthorized unathorized 401 or forbbiden 403 occurs, try again with a new header if ( (err.status === 401 || err.status === 403) && this.usesTokenLogin && this.authFlow != undefined ) { // update with new bearer token const newToken = await getTokenWithCogniteClient(this.authFlow); if (newToken == null && newToken == undefined) { throw new HttpError( 403, "Could not regenerate a new Bearer Token", {} ); } this.updateHeaderWithNewToken(newToken); // try again return this.post(path, options); } // rethrow throw err; }); }; /** * Basic HTTP method for DELETE * * @param path The URL path * @param options Request options, optional */ public asyncDelete = ( path: string, options?: HttpRequestOptions ) => { return this.delete(path, options).catch(async (err) => { // if unauthorized unathorized 401 or forbbiden 403 occurs, try again with a new header if ( (err.status === 401 || err.status === 403) && this.usesTokenLogin && this.authFlow != undefined ) { // update with new bearer token const newToken = await getTokenWithCogniteClient(this.authFlow); if (newToken == null && newToken == undefined) { throw new HttpError( 403, "Could not regenerate a new Bearer Token", {} ); } this.updateHeaderWithNewToken(newToken); // try again return this.delete(path, options); } // rethrow throw err; }); }; /** * Basic HTTP method for PATCH * * @param path The URL path * @param options Request options, optional */ public asyncPatch = (path: string, options?: HttpRequestOptions) => { return this.patch(path, options).catch(async (err) => { // if unauthorized unathorized 401 or forbbiden 403 occurs, try again with a new header if ( (err.status === 401 || err.status === 403) && this.usesTokenLogin && this.authFlow != undefined ) { // update with new bearer token const newToken = await getTokenWithCogniteClient(this.authFlow); if (newToken == null && newToken == undefined) { throw new HttpError( 403, "Could not regenerate a new Bearer Token", {} ); } this.updateHeaderWithNewToken(newToken); // try again return this.patch(path, options); } // rethrow throw err; }); }; }