UNPKG

@cognigy/rest-api-client

Version:

Cognigy REST-Client

246 lines 11.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.OAuth2Authentication = void 0; /* Custom Modules */ const OAuth2Error_1 = require("./OAuth2Error"); const HttpStatusCode_1 = require("../../shared/helper/HttpStatusCode"); const IOAuth2ErrorResponse_1 = require("./IOAuth2ErrorResponse"); const expiryBuffer = 8; exports.OAuth2Authentication = function (credentials, self) { if (!(this instanceof exports.OAuth2Authentication)) { return new exports.OAuth2Authentication(credentials, self); } else { self.refreshTokenSingleton = null; self.credentials = { type: credentials.type, clientId: credentials.clientId, clientSecret: credentials.clientSecret }; self.tokenData = {}; const refreshTokenGrant = async (data) => { const { clientId, clientSecret, refreshToken } = data; const formFields = { grant_type: "refresh_token", refresh_token: refreshToken, client_id: clientId, client_secret: clientSecret }; return await request(formFields, { maxRetries: Infinity, retryDelay: () => 3000, withCredentials: true }); }; const request = async (formFields, options) => { const payload = new URLSearchParams(formFields).toString(); const httpAdapter = self.getHttpAdapter(); let url; if (isAuthorizationRequest(formFields)) { url = "/auth/oauth2/authorize"; } else { url = "/auth/oauth2/token"; } const requestData = Object.assign({ headers: { "Content-Type": "application/x-www-form-urlencoded" }, method: "POST", url, data: payload }, options); //@ts-ignore - organisationId if (formFields.organisationId) { //@ts-ignore - organisationId requestData.headers["organisation-id"] = formFields.organisationId; //@ts-ignore - organisationId delete formFields.organisationId; requestData.data = new URLSearchParams(formFields).toString(); } const response = await httpAdapter.request(requestData, self); if (response.status === HttpStatusCode_1.HttpStatusCode.OK) { const result = response.data; result.expires_at = Date.now() + (result.expires_in - expiryBuffer) * 1000; return result; } if (typeof response.data.error === "string") { const error = response.data.error; if (IOAuth2ErrorResponse_1.OAuth2Errors.includes(error.error)) { throw new OAuth2Error_1.OAuth2Error(); } } }; const isAccessTokenExpired = (tokenData) => { var _a; return Date.now() > ((_a = tokenData.expires_at) !== null && _a !== void 0 ? _a : 0); }; const OAuth2Authentication = function () { }; OAuth2Authentication.prototype.getAuthenticationHeaders = async () => { const headers = {}; if ((self === null || self === void 0 ? void 0 : self.credentials.type) === "OAuth2") { await getToken(); headers["Authorization"] = `${self.tokenData.token_type} ${self.tokenData.access_token}`; } return headers; }; OAuth2Authentication.prototype.login = async (parameters) => { const { clientId, clientSecret } = self.credentials; switch (parameters.type) { // Password Grant is deprecated in OAuth2, but still supported // for api and e2e tests case "password": { const { username, password, rememberMe, organisationId } = parameters; const formFields = { grant_type: "password", username: username, password: password, client_id: clientId, client_secret: clientSecret, rememberMe, organisationId }; self.tokenData = await request(formFields, { maxRetries: 0 }); } break; case "refreshToken": { // The refresh token from the parameters is to support older token granted via Password Grant flow // TODO - remove this in future once PKCE fully takes over const { refreshToken } = parameters; const credentials = self.credentials; const result = await refreshTokenGrant({ clientId: credentials.clientId, clientSecret: credentials.clientSecret, refreshToken }); self.tokenData = Object.assign(Object.assign(Object.assign({}, self.tokenData), { refresh_token: refreshToken }), result); } break; case "authorizationCode": { const { code, redirectUri, codeVerifier, rememberMe } = parameters; const formFields = { grant_type: "authorization_code", client_id: clientId, client_secret: clientSecret, code, redirect_uri: redirectUri, rememberMe, code_verifier: codeVerifier }; self.tokenData = await request(formFields, { maxRetries: 0, withCredentials: true }); } break; case "clientCredentials": { const { scope } = parameters; const formFields = { grant_type: "client_credentials", scope: scope, client_id: clientId, client_secret: clientSecret }; self.tokenData = await request(formFields, { maxRetries: 0 }); } break; } }; OAuth2Authentication.prototype.getAuthorizationCode = async (parameters) => { const { username, password, redirectUri, state, organisationId, codeChallenge, codeChallengeMethod } = parameters; const { clientId } = self.credentials; const formFields = { response_type: "code", username: username, password: password, client_id: clientId, state, organisationId, code_challenge: codeChallenge, code_challenge_method: codeChallengeMethod }; if (redirectUri) { formFields.redirect_uri = redirectUri; } const code = await request(formFields, { maxRetries: 0 }); return code; }; const getToken = async () => { if ((self === null || self === void 0 ? void 0 : self.credentials.type) === "OAuth2") { if (self.refreshTokenSingleton !== null) { await self.refreshTokenSingleton; } /* * Check if AccessToken is still valid and if not trigger an refresh token grant flow */ if (isAccessTokenExpired(self.tokenData)) { const credentials = self.credentials; if (self.refreshTokenSingleton === null) { self.refreshTokenSingleton = new Promise((resolve, reject) => { refreshTokenGrant({ clientId: credentials.clientId, clientSecret: credentials.clientSecret, refreshToken: self.tokenData.refresh_token }) .then((result) => { self.tokenData = Object.assign(Object.assign({}, self.tokenData), result); self.refreshTokenSingleton = null; resolve(); }) .catch((reason) => { self.refreshTokenSingleton = null; self.tokenData = {}; reject(reason); }); }); await self.refreshTokenSingleton; } } } return self.tokenData; }; const isAuthorizationRequest = (value) => (value === null || value === void 0 ? void 0 : value.response_type) === "code"; OAuth2Authentication.prototype.getAccessToken = async () => { const token = await getToken(); return token.access_token; }; OAuth2Authentication.prototype.getRefreshToken = () => { var _a; return (_a = self.tokenData) === null || _a === void 0 ? void 0 : _a.refresh_token; }; OAuth2Authentication.prototype.isLoggedIn = async () => { var _a; return !!((_a = self.tokenData) === null || _a === void 0 ? void 0 : _a.refresh_token); }; OAuth2Authentication.prototype.logout = async () => { if ((self === null || self === void 0 ? void 0 : self.credentials.type) === "OAuth2") { const httpAdapter = self.getHttpAdapter(); const requestData = { method: "POST", url: "/auth/oauth2/revoke", data: { token: self.tokenData.refresh_token }, maxRetries: 3, withCredentials: true, retryDelay: () => 0 }; // reset tokenData to avoid multiple revoke calls self.tokenData = {}; await httpAdapter.request(requestData, self); } }; return new OAuth2Authentication(credentials, self); } }; exports.default = exports.OAuth2Authentication; //# sourceMappingURL=OAuth2Authentication.js.map