LookAtMySuitBot/js/node_modules/@azure/msal-node/dist/client/PublicClientApplication.mjs

242 lines
12 KiB
JavaScript

/*! @azure/msal-node v2.5.1 2023-11-07 */
'use strict';
import { ApiId, LOOPBACK_SERVER_CONSTANTS, Constants as Constants$1 } from '../utils/Constants.mjs';
import { AuthError, OIDC_DEFAULT_SCOPES, ResponseMode, CodeChallengeMethodValues, ServerError, Constants } from '@azure/msal-common';
import { ClientApplication } from './ClientApplication.mjs';
import { NodeAuthError, NodeAuthErrorMessage } from '../error/NodeAuthError.mjs';
import { LoopbackClient } from '../network/LoopbackClient.mjs';
import { DeviceCodeClient } from './DeviceCodeClient.mjs';
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
/**
* This class is to be used to acquire tokens for public client applications (desktop, mobile). Public client applications
* are not trusted to safely store application secrets, and therefore can only request tokens in the name of an user.
* @public
*/
class PublicClientApplication extends ClientApplication {
/**
* Important attributes in the Configuration object for auth are:
* - clientID: the application ID of your application. You can obtain one by registering your application with our Application registration portal.
* - authority: the authority URL for your application.
*
* AAD authorities are of the form https://login.microsoftonline.com/\{Enter_the_Tenant_Info_Here\}.
* - If your application supports Accounts in one organizational directory, replace "Enter_the_Tenant_Info_Here" value with the Tenant Id or Tenant name (for example, contoso.microsoft.com).
* - If your application supports Accounts in any organizational directory, replace "Enter_the_Tenant_Info_Here" value with organizations.
* - If your application supports Accounts in any organizational directory and personal Microsoft accounts, replace "Enter_the_Tenant_Info_Here" value with common.
* - To restrict support to Personal Microsoft accounts only, replace "Enter_the_Tenant_Info_Here" value with consumers.
*
* Azure B2C authorities are of the form https://\{instance\}/\{tenant\}/\{policy\}. Each policy is considered
* its own authority. You will have to set the all of the knownAuthorities at the time of the client application
* construction.
*
* ADFS authorities are of the form https://\{instance\}/adfs.
*/
constructor(configuration) {
super(configuration);
if (this.config.broker.nativeBrokerPlugin) {
if (this.config.broker.nativeBrokerPlugin.isBrokerAvailable) {
this.nativeBrokerPlugin = this.config.broker.nativeBrokerPlugin;
this.nativeBrokerPlugin.setLogger(this.config.system.loggerOptions);
}
else {
this.logger.warning("NativeBroker implementation was provided but the broker is unavailable.");
}
}
}
/**
* Acquires a token from the authority using OAuth2.0 device code flow.
* This flow is designed for devices that do not have access to a browser or have input constraints.
* The authorization server issues a DeviceCode object with a verification code, an end-user code,
* and the end-user verification URI. The DeviceCode object is provided through a callback, and the end-user should be
* instructed to use another device to navigate to the verification URI to input credentials.
* Since the client cannot receive incoming requests, it polls the authorization server repeatedly
* until the end-user completes input of credentials.
*/
async acquireTokenByDeviceCode(request) {
this.logger.info("acquireTokenByDeviceCode called", request.correlationId);
const validRequest = Object.assign(request, await this.initializeBaseRequest(request));
const serverTelemetryManager = this.initializeServerTelemetryManager(ApiId.acquireTokenByDeviceCode, validRequest.correlationId);
try {
const deviceCodeConfig = await this.buildOauthClientConfiguration(validRequest.authority, validRequest.correlationId, serverTelemetryManager, undefined, request.azureCloudOptions);
const deviceCodeClient = new DeviceCodeClient(deviceCodeConfig);
this.logger.verbose("Device code client created", validRequest.correlationId);
return deviceCodeClient.acquireToken(validRequest);
}
catch (e) {
if (e instanceof AuthError) {
e.setCorrelationId(validRequest.correlationId);
}
serverTelemetryManager.cacheFailedRequest(e);
throw e;
}
}
/**
* Acquires a token interactively via the browser by requesting an authorization code then exchanging it for a token.
*/
async acquireTokenInteractive(request) {
const correlationId = request.correlationId || this.cryptoProvider.createNewGuid();
this.logger.trace("acquireTokenInteractive called", correlationId);
const { openBrowser, successTemplate, errorTemplate, windowHandle, loopbackClient: customLoopbackClient, ...remainingProperties } = request;
if (this.nativeBrokerPlugin) {
const brokerRequest = {
...remainingProperties,
clientId: this.config.auth.clientId,
scopes: request.scopes || OIDC_DEFAULT_SCOPES,
redirectUri: `${Constants$1.HTTP_PROTOCOL}${Constants$1.LOCALHOST}`,
authority: request.authority || this.config.auth.authority,
correlationId: correlationId,
extraParameters: {
...remainingProperties.extraQueryParameters,
...remainingProperties.tokenQueryParameters,
},
accountId: remainingProperties.account?.nativeAccountId,
};
return this.nativeBrokerPlugin.acquireTokenInteractive(brokerRequest, windowHandle);
}
const { verifier, challenge } = await this.cryptoProvider.generatePkceCodes();
const loopbackClient = customLoopbackClient || new LoopbackClient();
let authCodeResponse = {};
let authCodeListenerError = null;
try {
const authCodeListener = loopbackClient
.listenForAuthCode(successTemplate, errorTemplate)
.then((response) => {
authCodeResponse = response;
})
.catch((e) => {
// Store the promise instead of throwing so we can control when its thrown
authCodeListenerError = e;
});
// Wait for server to be listening
const redirectUri = await this.waitForRedirectUri(loopbackClient);
const validRequest = {
...remainingProperties,
correlationId: correlationId,
scopes: request.scopes || OIDC_DEFAULT_SCOPES,
redirectUri: redirectUri,
responseMode: ResponseMode.QUERY,
codeChallenge: challenge,
codeChallengeMethod: CodeChallengeMethodValues.S256,
};
const authCodeUrl = await this.getAuthCodeUrl(validRequest);
await openBrowser(authCodeUrl);
await authCodeListener;
if (authCodeListenerError) {
throw authCodeListenerError;
}
if (authCodeResponse.error) {
throw new ServerError(authCodeResponse.error, authCodeResponse.error_description, authCodeResponse.suberror);
}
else if (!authCodeResponse.code) {
throw NodeAuthError.createNoAuthCodeInResponseError();
}
const clientInfo = authCodeResponse.client_info;
const tokenRequest = {
code: authCodeResponse.code,
codeVerifier: verifier,
clientInfo: clientInfo || Constants.EMPTY_STRING,
...validRequest,
};
return await this.acquireTokenByCode(tokenRequest); // Await this so the server doesn't close prematurely
}
finally {
loopbackClient.closeServer();
}
}
/**
* Returns a token retrieved either from the cache or by exchanging the refresh token for a fresh access token. If brokering is enabled the token request will be serviced by the broker.
* @param request
* @returns
*/
async acquireTokenSilent(request) {
const correlationId = request.correlationId || this.cryptoProvider.createNewGuid();
this.logger.trace("acquireTokenSilent called", correlationId);
if (this.nativeBrokerPlugin) {
const brokerRequest = {
...request,
clientId: this.config.auth.clientId,
scopes: request.scopes || OIDC_DEFAULT_SCOPES,
redirectUri: `${Constants$1.HTTP_PROTOCOL}${Constants$1.LOCALHOST}`,
authority: request.authority || this.config.auth.authority,
correlationId: correlationId,
extraParameters: request.tokenQueryParameters,
accountId: request.account.nativeAccountId,
forceRefresh: request.forceRefresh || false,
};
return this.nativeBrokerPlugin.acquireTokenSilent(brokerRequest);
}
return super.acquireTokenSilent(request);
}
/**
* Removes cache artifacts associated with the given account
* @param request
* @returns
*/
async signOut(request) {
if (this.nativeBrokerPlugin && request.account.nativeAccountId) {
const signoutRequest = {
clientId: this.config.auth.clientId,
accountId: request.account.nativeAccountId,
correlationId: request.correlationId ||
this.cryptoProvider.createNewGuid(),
};
await this.nativeBrokerPlugin.signOut(signoutRequest);
}
await this.getTokenCache().removeAccount(request.account);
}
/**
* Returns all cached accounts for this application. If brokering is enabled this request will be serviced by the broker.
* @returns
*/
async getAllAccounts() {
if (this.nativeBrokerPlugin) {
const correlationId = this.cryptoProvider.createNewGuid();
return this.nativeBrokerPlugin.getAllAccounts(this.config.auth.clientId, correlationId);
}
return this.getTokenCache().getAllAccounts();
}
/**
* Attempts to retrieve the redirectUri from the loopback server. If the loopback server does not start listening for requests within the timeout this will throw.
* @param loopbackClient
* @returns
*/
async waitForRedirectUri(loopbackClient) {
return new Promise((resolve, reject) => {
let ticks = 0;
const id = setInterval(() => {
if (LOOPBACK_SERVER_CONSTANTS.TIMEOUT_MS /
LOOPBACK_SERVER_CONSTANTS.INTERVAL_MS <
ticks) {
clearInterval(id);
reject(NodeAuthError.createLoopbackServerTimeoutError());
return;
}
try {
const r = loopbackClient.getRedirectUri();
clearInterval(id);
resolve(r);
return;
}
catch (e) {
if (e instanceof AuthError &&
e.errorCode ===
NodeAuthErrorMessage.noLoopbackServerExists.code) {
// Loopback server is not listening yet
ticks++;
return;
}
clearInterval(id);
reject(e);
return;
}
}, LOOPBACK_SERVER_CONSTANTS.INTERVAL_MS);
});
}
}
export { PublicClientApplication };
//# sourceMappingURL=PublicClientApplication.mjs.map