@bitrix24/b24jssdk
Version:
Bitrix24 REST API JavaScript SDK
212 lines (209 loc) • 7.23 kB
JavaScript
/**
* @package @bitrix24/b24jssdk
* @version 1.0.1
* @copyright (c) 2026 Bitrix24
* @license MIT
* @see https://github.com/bitrix24/b24jssdk
* @see https://bitrix24.github.io/b24jssdk/
*/
import axios, { AxiosError } from 'axios';
import { RefreshTokenError } from './refresh-token-error.mjs';
import { Type } from '../tools/type.mjs';
import { EnumAppStatus } from '../types/b24-helper.mjs';
import { ApiVersion } from '../types/b24.mjs';
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
class AuthOAuthManager {
static {
__name(this, "AuthOAuthManager");
}
#clientAxios;
#callbackRefreshAuth = null;
#customRefreshAuth = null;
#authOptions;
#oAuthSecret;
#authExpires = 0;
#authExpiresIn = 0;
#domain;
#b24TargetRest;
#b24Target;
#b24TargetRestWithPath;
#oAuthTarget;
// 'https://oauth.bitrix.info'
#isAdmin = null;
constructor(b24OAuthParams, oAuthSecret) {
this.#authOptions = Object.assign({}, b24OAuthParams);
this.#oAuthSecret = Object.freeze(Object.assign({}, oAuthSecret));
this.#domain = this.#authOptions.domain.replaceAll("https://", "").replaceAll("http://", "").replace(/:(80|443)$/, "");
this.#b24TargetRest = this.#authOptions.clientEndpoint;
this.#b24Target = this.#b24TargetRest.replace("/rest/", "");
this.#oAuthTarget = this.#authOptions.serverEndpoint.replace("/rest/", "");
this.#authExpires = this.#authOptions.expires * 1e3;
this.#authExpiresIn = this.#authOptions.expiresIn;
this.#clientAxios = axios.create({
baseURL: this.#oAuthTarget,
headers: {
"Content-Type": "application/json"
}
});
this.#b24TargetRestWithPath = /* @__PURE__ */ new Map();
this.#b24TargetRestWithPath.set(ApiVersion.v2, `${this.#b24TargetRest}`);
this.#b24TargetRestWithPath.set(ApiVersion.v3, `${this.#b24TargetRest}/api`);
}
/**
* Returns authorization data
* @see Http.#prepareParams
*/
getAuthData() {
return this.#authExpires > Date.now() ? {
access_token: this.#authOptions.accessToken,
refresh_token: this.#authOptions.refreshToken,
expires: this.#authExpires / 1e3,
expires_in: this.#authExpiresIn,
domain: this.#domain,
member_id: this.#authOptions.memberId
} : false;
}
// region RefreshAuth ////
/**
* Updates authorization data
*/
async refreshAuth() {
try {
let payload = void 0;
if (this.#customRefreshAuth) {
payload = await this.#customRefreshAuth();
} else {
const response = await this.#clientAxios.get(
"/oauth/token/",
{
params: {
grant_type: "refresh_token",
client_id: this.#oAuthSecret.clientId,
client_secret: this.#oAuthSecret.clientSecret,
refresh_token: this.#authOptions.refreshToken
}
}
);
if (response.data.error) {
throw new Error(`Token update error: ${response.data.error}`);
}
if (response.status !== 200) {
throw new Error(`Token update error status code: ${response.status}`);
}
payload = response.data;
}
if (!payload) {
throw new Error("Unable to obtain authorization update data");
}
this.#authOptions.accessToken = payload.access_token;
this.#authOptions.refreshToken = payload.refresh_token;
this.#authOptions.expires = Number.parseInt(payload.expires || "0");
this.#authOptions.expiresIn = Number.parseInt(payload.expires_in || "3600");
this.#authOptions.clientEndpoint = payload.client_endpoint;
this.#authOptions.serverEndpoint = payload.server_endpoint;
this.#authOptions.scope = payload.scope;
this.#authOptions.status = Object.values(EnumAppStatus).find((value) => value === payload.status) || EnumAppStatus.Free;
this.#authExpires = this.#authOptions.expires * 1e3;
const authData = this.getAuthData();
if (this.#callbackRefreshAuth) {
await this.#callbackRefreshAuth({ authData, b24OAuthParams: this.#authOptions });
}
return authData;
} catch (error) {
if (error instanceof AxiosError) {
const answerError = {
code: error?.code || 0,
description: error?.message || ""
};
if (error.response && error.response.data && !Type.isUndefined(error.response.data.error)) {
const responseData = error.response.data;
if (responseData.error && typeof responseData.error === "object" && "code" in responseData.error) {
answerError.code = responseData.error.code;
answerError.description = responseData.error.message;
if (responseData.error.validation) {
responseData.error.validation.forEach((row) => {
answerError.description += `${row?.message || JSON.stringify(row)}`;
});
}
} else if (responseData.error && typeof responseData.error === "string") {
answerError.code = responseData.error;
answerError.description = responseData?.error_description ?? answerError.description;
}
}
throw new RefreshTokenError({
code: String(answerError.code),
description: answerError.description,
status: error.response?.status || 0
});
} else if (error instanceof Error) {
throw error;
}
throw new Error(
`Strange error: ${error instanceof Error ? error.message : error}`,
{ cause: error }
);
}
}
setCallbackRefreshAuth(cb) {
this.#callbackRefreshAuth = cb;
}
removeCallbackRefreshAuth() {
this.#callbackRefreshAuth = null;
}
setCustomRefreshAuth(cb) {
this.#customRefreshAuth = cb;
}
removeCustomRefreshAuth() {
this.#customRefreshAuth = null;
}
// endregion ////
getUniq(prefix) {
return [prefix, this.#authOptions.memberId || ""].join("_");
}
/**
* @inheritDoc
*/
getTargetOrigin() {
return `${this.#b24Target}`;
}
/**
* @inheritDoc
*/
getTargetOriginWithPath() {
return this.#b24TargetRestWithPath;
}
/**
* Determines whether the current user has administrator rights
*/
get isAdmin() {
if (null === this.#isAdmin) {
throw new Error("isAdmin not init. You need call B24OAuth::initIsAdmin().");
}
return this.#isAdmin;
}
async initIsAdmin(http, requestId) {
this.#isAdmin = false;
if (http.apiVersion === ApiVersion.v3) {
const response2 = await http.call("profile", {}, requestId);
if (!response2.isSuccess) {
throw new Error(response2.getErrorMessages().join(";"));
}
const data2 = response2.getData().result;
if (data2.profile?.admin) {
this.#isAdmin = true;
}
return;
}
const response = await http.call("profile", {}, requestId);
if (!response.isSuccess) {
throw new Error(response.getErrorMessages().join(";"));
}
const data = response.getData().result;
if (data?.ADMIN) {
this.#isAdmin = true;
}
}
}
export { AuthOAuthManager };
//# sourceMappingURL=auth.mjs.map