@azure/communication-common
Version:
Common package for Azure Communication services.
152 lines (151 loc) • 5.76 kB
JavaScript
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var entraTokenCredential_exports = {};
__export(entraTokenCredential_exports, {
EntraTokenCredential: () => EntraTokenCredential
});
module.exports = __toCommonJS(entraTokenCredential_exports);
var import_core_client = require("@azure-rest/core-client");
var import_core_rest_pipeline = require("@azure/core-rest-pipeline");
const TeamsExtensionScopePrefixes = [
"https://auth.msft.communication.azure.com/",
"https://auth.msft.communication.azure.us/"
];
const CommunicationClientsScopePrefix = "https://communication.azure.com/clients/";
const ScopeValidationErrorMessage = `Scopes validation failed. Ensure all scopes start with one of ${[
...TeamsExtensionScopePrefixes,
CommunicationClientsScopePrefix
].join(", ")}.`;
const TeamsExtensionEndpoint = "/access/teamsExtension/:exchangeAccessToken";
const TeamsExtensionApiVersion = "2025-06-30";
const CommunicationClientsEndpoint = "/access/entra/:exchangeAccessToken";
const CommunicationClientsApiVersion = "2025-03-02-preview";
class EntraTokenCredential {
constructor(options) {
this.options = options;
this.client = (0, import_core_client.getClient)(options.resourceEndpoint);
this.httpClient = (0, import_core_rest_pipeline.createDefaultHttpClient)();
this.options = options;
this.options.scopes = this.options.scopes || [
"https://communication.azure.com/clients/.default"
];
this.isPending = this.getToken();
}
options;
isPending;
result = {
entraToken: void 0,
acsToken: { token: "", expiresOnTimestamp: 0 }
};
client;
httpClient;
async getToken(options) {
if (options?.abortSignal?.aborted) {
return { token: "", expiresOnTimestamp: 0 };
}
if (!this.isPending) {
this.isPending = this.getTokenInternal(options);
}
try {
await this.isPending;
} finally {
this.isPending = null;
}
return this.result.acsToken;
}
async getTokenInternal(options) {
const getTokenOptions = options?.abortSignal ? { abortSignal: options.abortSignal } : void 0;
const token = await this.options.tokenCredential.getToken(
this.options.scopes ? this.options.scopes : ["https://communication.azure.com/clients/.default"],
getTokenOptions
);
const currentDateTime = /* @__PURE__ */ new Date();
const tokenExpiresOn = new Date(this.result.acsToken.expiresOnTimestamp);
if (token === null) {
this.result = {
entraToken: void 0,
acsToken: { token: "", expiresOnTimestamp: 0 }
};
} else if (this.result.acsToken.token === "" || token.token !== this.result.entraToken || tokenExpiresOn < currentDateTime) {
const acsToken = await this.exchangeEntraToken(
this.options.resourceEndpoint,
token.token,
getTokenOptions
);
this.result = {
entraToken: token.token,
acsToken
};
}
return this.result.acsToken;
}
dispose() {
this.result = {
entraToken: void 0,
acsToken: { token: "", expiresOnTimestamp: 0 }
};
}
async exchangeEntraToken(resourceEndpoint, entraToken, options) {
const request = (0, import_core_rest_pipeline.createPipelineRequest)({
url: this.createRequestUri(resourceEndpoint),
method: "POST",
headers: (0, import_core_rest_pipeline.createHttpHeaders)({
Authorization: `Bearer ${entraToken}`,
"Content-Type": "application/json",
Accept: "application/json"
}),
abortSignal: options?.abortSignal,
body: JSON.stringify({})
});
const response = await this.client.pipeline.sendRequest(this.httpClient, request);
if (response.status !== 200 || !response.bodyAsText) {
throw new Error(
`Service request failed. Status: ${response.status}, Body: ${response.bodyAsText}`
);
}
const json = JSON.parse(response.bodyAsText);
return {
token: json.accessToken.token,
expiresOnTimestamp: Date.parse(json.accessToken.expiresOn)
};
}
createRequestUri(resourceEndpoint) {
const [endpoint, apiVersion] = this.determineEndpointAndApiVersion();
const requestUri = `${resourceEndpoint}${endpoint}?api-version=${apiVersion}`;
return requestUri;
}
determineEndpointAndApiVersion() {
if (!this.options.scopes || this.options.scopes.length === 0) {
throw new Error(ScopeValidationErrorMessage);
}
if (this.options.scopes.every(
(scope) => TeamsExtensionScopePrefixes.some((prefix) => scope.startsWith(prefix))
)) {
return [TeamsExtensionEndpoint, TeamsExtensionApiVersion];
}
if (this.options.scopes.every((scope) => scope.startsWith(CommunicationClientsScopePrefix))) {
return [CommunicationClientsEndpoint, CommunicationClientsApiVersion];
}
throw new Error(ScopeValidationErrorMessage);
}
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
EntraTokenCredential
});
//# sourceMappingURL=entraTokenCredential.js.map