UNPKG

@dvsa/appdev-api-common

Version:

Utils library for common API functionality

93 lines (92 loc) 3.48 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ClientCredentials = void 0; const node_querystring_1 = require("node:querystring"); const jose_1 = require("jose"); class ClientCredentials { tokenUrl; clientId; clientSecret; scope; resource; debugMode; static accessToken; static grantType = "client_credentials"; /** * Create a new instance of the ClientCredentials class * @param tokenUrl - The URL to fetch the access token from * @param clientId - The client id * @param clientSecret - The client secret * @param scope - The scope of the access token * @param debugMode - Whether to log debug messages */ constructor(tokenUrl, clientId, clientSecret, scope, resource, debugMode = false) { this.tokenUrl = tokenUrl; this.clientId = clientId; this.clientSecret = clientSecret; this.scope = scope; this.resource = resource; this.debugMode = debugMode; } /** * Helper method to perform the client credentials flow and return the access token * This method will check for the existence of the token and if it is expired, it will fetch a new one * @returns {Promise<string>} - The access token */ async getAccessToken() { if (!ClientCredentials.accessToken || this.isAccessTokenExpired()) { const { access_token } = await this.fetchClientCredentials(); if (this.debugMode) console.log("[DEBUG] New access token fetched:", access_token); ClientCredentials.accessToken = access_token; } else if (this.debugMode) { console.log("[DEBUG] Using existing access token:", ClientCredentials.accessToken); } return ClientCredentials.accessToken; } /** * Fetch the client credentials from the token URL * @returns {Promise<ClientCredentialsResponse>} - The response from the token URL * @private */ async fetchClientCredentials() { const response = await fetch(this.tokenUrl, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: (0, node_querystring_1.stringify)({ grant_type: ClientCredentials.grantType, client_id: this.clientId, client_secret: this.clientSecret, scope: this.scope, resource: this.resource, }), }); if (!response.ok) { console.error("Error fetching client credentials", response); throw new Error("Failed to fetch client credentials"); } return (await response.json()); } /** * Check if the access token is expired * @returns {boolean} - Whether the access token is expired * @private */ isAccessTokenExpired() { try { const decodedAccessToken = (0, jose_1.decodeJwt)(ClientCredentials.accessToken); const currentTime = new Date().getTime() / 1000; // Check if exp exists before comparing as it can be undefined if (!decodedAccessToken?.exp) { return true; } return currentTime > decodedAccessToken.exp; } catch (err) { console.error("Error decoding access token:", err); return true; } } } exports.ClientCredentials = ClientCredentials;