@cognigy/rest-api-client
Version:
Cognigy REST-Client
246 lines • 11.2 kB
JavaScript
;
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