@azure/msal-browser
Version:
Microsoft Authentication Library for js
296 lines (293 loc) • 16.8 kB
JavaScript
/*! @azure/msal-browser v2.28.1 2022-08-01 */
'use strict';
import { __extends, __awaiter, __generator, __assign } from '../_virtual/_tslib.js';
import { UrlString, Constants, AuthorizationCodeClient, PerformanceEvents, Authority, AuthorityFactory, ResponseMode, StringUtils, ProtocolUtils } from '@azure/msal-common';
import { BaseInteractionClient } from './BaseInteractionClient.js';
import { BrowserConstants } from '../utils/BrowserConstants.js';
import { version } from '../packageMetadata.js';
import { BrowserAuthError } from '../error/BrowserAuthError.js';
import { BrowserProtocolUtils } from '../utils/BrowserProtocolUtils.js';
import { BrowserUtils } from '../utils/BrowserUtils.js';
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
/**
* Defines the class structure and helper functions used by the "standard", non-brokered auth flows (popup, redirect, silent (RT), silent (iframe))
*/
var StandardInteractionClient = /** @class */ (function (_super) {
__extends(StandardInteractionClient, _super);
function StandardInteractionClient() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* Generates an auth code request tied to the url request.
* @param request
*/
StandardInteractionClient.prototype.initializeAuthorizationCodeRequest = function (request) {
return __awaiter(this, void 0, void 0, function () {
var generatedPkceParams, authCodeRequest;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
this.logger.verbose("initializeAuthorizationRequest called", request.correlationId);
return [4 /*yield*/, this.browserCrypto.generatePkceCodes()];
case 1:
generatedPkceParams = _a.sent();
authCodeRequest = __assign(__assign({}, request), { redirectUri: request.redirectUri, code: Constants.EMPTY_STRING, codeVerifier: generatedPkceParams.verifier });
request.codeChallenge = generatedPkceParams.challenge;
request.codeChallengeMethod = Constants.S256_CODE_CHALLENGE_METHOD;
return [2 /*return*/, authCodeRequest];
}
});
});
};
/**
* Initializer for the logout request.
* @param logoutRequest
*/
StandardInteractionClient.prototype.initializeLogoutRequest = function (logoutRequest) {
this.logger.verbose("initializeLogoutRequest called", logoutRequest === null || logoutRequest === void 0 ? void 0 : logoutRequest.correlationId);
var validLogoutRequest = __assign({ correlationId: this.correlationId || this.browserCrypto.createNewGuid() }, logoutRequest);
/**
* Set logout_hint to be login_hint from ID Token Claims if present
* and logoutHint attribute wasn't manually set in logout request
*/
if (logoutRequest) {
// If logoutHint isn't set and an account was passed in, try to extract logoutHint from ID Token Claims
if (!logoutRequest.logoutHint) {
if (logoutRequest.account) {
var logoutHint = this.getLogoutHintFromIdTokenClaims(logoutRequest.account);
if (logoutHint) {
this.logger.verbose("Setting logoutHint to login_hint ID Token Claim value for the account provided");
validLogoutRequest.logoutHint = logoutHint;
}
}
else {
this.logger.verbose("logoutHint was not set and account was not passed into logout request, logoutHint will not be set");
}
}
else {
this.logger.verbose("logoutHint has already been set in logoutRequest");
}
}
else {
this.logger.verbose("logoutHint will not be set since no logout request was configured");
}
/*
* Only set redirect uri if logout request isn't provided or the set uri isn't null.
* Otherwise, use passed uri, config, or current page.
*/
if (!logoutRequest || logoutRequest.postLogoutRedirectUri !== null) {
if (logoutRequest && logoutRequest.postLogoutRedirectUri) {
this.logger.verbose("Setting postLogoutRedirectUri to uri set on logout request", validLogoutRequest.correlationId);
validLogoutRequest.postLogoutRedirectUri = UrlString.getAbsoluteUrl(logoutRequest.postLogoutRedirectUri, BrowserUtils.getCurrentUri());
}
else if (this.config.auth.postLogoutRedirectUri === null) {
this.logger.verbose("postLogoutRedirectUri configured as null and no uri set on request, not passing post logout redirect", validLogoutRequest.correlationId);
}
else if (this.config.auth.postLogoutRedirectUri) {
this.logger.verbose("Setting postLogoutRedirectUri to configured uri", validLogoutRequest.correlationId);
validLogoutRequest.postLogoutRedirectUri = UrlString.getAbsoluteUrl(this.config.auth.postLogoutRedirectUri, BrowserUtils.getCurrentUri());
}
else {
this.logger.verbose("Setting postLogoutRedirectUri to current page", validLogoutRequest.correlationId);
validLogoutRequest.postLogoutRedirectUri = UrlString.getAbsoluteUrl(BrowserUtils.getCurrentUri(), BrowserUtils.getCurrentUri());
}
}
else {
this.logger.verbose("postLogoutRedirectUri passed as null, not setting post logout redirect uri", validLogoutRequest.correlationId);
}
return validLogoutRequest;
};
/**
* Parses login_hint ID Token Claim out of AccountInfo object to be used as
* logout_hint in end session request.
* @param account
*/
StandardInteractionClient.prototype.getLogoutHintFromIdTokenClaims = function (account) {
var idTokenClaims = account.idTokenClaims;
if (idTokenClaims) {
if (idTokenClaims.login_hint) {
return idTokenClaims.login_hint;
}
else {
this.logger.verbose("The ID Token Claims tied to the provided account do not contain a login_hint claim, logoutHint will not be added to logout request");
}
}
else {
this.logger.verbose("The provided account does not contain ID Token Claims, logoutHint will not be added to logout request");
}
return null;
};
/**
* Creates an Authorization Code Client with the given authority, or the default authority.
* @param serverTelemetryManager
* @param authorityUrl
*/
StandardInteractionClient.prototype.createAuthCodeClient = function (serverTelemetryManager, authorityUrl, requestAzureCloudOptions) {
return __awaiter(this, void 0, void 0, function () {
var clientConfig;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.getClientConfiguration(serverTelemetryManager, authorityUrl, requestAzureCloudOptions)];
case 1:
clientConfig = _a.sent();
return [2 /*return*/, new AuthorizationCodeClient(clientConfig)];
}
});
});
};
/**
* Creates a Client Configuration object with the given request authority, or the default authority.
* @param serverTelemetryManager
* @param requestAuthority
* @param requestCorrelationId
*/
StandardInteractionClient.prototype.getClientConfiguration = function (serverTelemetryManager, requestAuthority, requestAzureCloudOptions) {
return __awaiter(this, void 0, void 0, function () {
var discoveredAuthority;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
this.logger.verbose("getClientConfiguration called", this.correlationId);
return [4 /*yield*/, this.getDiscoveredAuthority(requestAuthority, requestAzureCloudOptions)];
case 1:
discoveredAuthority = _a.sent();
return [2 /*return*/, {
authOptions: {
clientId: this.config.auth.clientId,
authority: discoveredAuthority,
clientCapabilities: this.config.auth.clientCapabilities
},
systemOptions: {
tokenRenewalOffsetSeconds: this.config.system.tokenRenewalOffsetSeconds,
preventCorsPreflight: true
},
loggerOptions: {
loggerCallback: this.config.system.loggerOptions.loggerCallback,
piiLoggingEnabled: this.config.system.loggerOptions.piiLoggingEnabled,
logLevel: this.config.system.loggerOptions.logLevel,
correlationId: this.correlationId
},
cryptoInterface: this.browserCrypto,
networkInterface: this.networkClient,
storageInterface: this.browserStorage,
serverTelemetryManager: serverTelemetryManager,
libraryInfo: {
sku: BrowserConstants.MSAL_SKU,
version: version,
cpu: Constants.EMPTY_STRING,
os: Constants.EMPTY_STRING
},
telemetry: this.config.telemetry
}];
}
});
});
};
/**
* @param hash
* @param interactionType
*/
StandardInteractionClient.prototype.validateAndExtractStateFromHash = function (serverParams, interactionType, requestCorrelationId) {
this.logger.verbose("validateAndExtractStateFromHash called", requestCorrelationId);
if (!serverParams.state) {
throw BrowserAuthError.createHashDoesNotContainStateError();
}
var platformStateObj = BrowserProtocolUtils.extractBrowserRequestState(this.browserCrypto, serverParams.state);
if (!platformStateObj) {
throw BrowserAuthError.createUnableToParseStateError();
}
if (platformStateObj.interactionType !== interactionType) {
throw BrowserAuthError.createStateInteractionTypeMismatchError();
}
this.logger.verbose("Returning state from hash", requestCorrelationId);
return serverParams.state;
};
/**
* Used to get a discovered version of the default authority.
* @param requestAuthority
* @param requestCorrelationId
*/
StandardInteractionClient.prototype.getDiscoveredAuthority = function (requestAuthority, requestAzureCloudOptions) {
return __awaiter(this, void 0, void 0, function () {
var getAuthorityMeasurement, authorityOptions, userAuthority, builtAuthority;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
this.logger.verbose("getDiscoveredAuthority called", this.correlationId);
getAuthorityMeasurement = this.performanceClient.startMeasurement(PerformanceEvents.StandardInteractionClientGetDiscoveredAuthority, this.correlationId);
authorityOptions = {
protocolMode: this.config.auth.protocolMode,
knownAuthorities: this.config.auth.knownAuthorities,
cloudDiscoveryMetadata: this.config.auth.cloudDiscoveryMetadata,
authorityMetadata: this.config.auth.authorityMetadata,
skipAuthorityMetadataCache: this.config.auth.skipAuthorityMetadataCache
};
userAuthority = requestAuthority ? requestAuthority : this.config.auth.authority;
builtAuthority = Authority.generateAuthority(userAuthority, requestAzureCloudOptions || this.config.auth.azureCloudOptions);
this.logger.verbose("Creating discovered authority with configured authority", this.correlationId);
return [4 /*yield*/, AuthorityFactory.createDiscoveredInstance(builtAuthority, this.config.system.networkClient, this.browserStorage, authorityOptions)
.then(function (result) {
getAuthorityMeasurement.endMeasurement({
success: true
});
return result;
})
.catch(function (error) {
getAuthorityMeasurement.endMeasurement({
errorCode: error.errorCode,
subErrorCode: error.subError,
success: false
});
throw error;
})];
case 1: return [2 /*return*/, _a.sent()];
}
});
});
};
/**
* Helper to initialize required request parameters for interactive APIs and ssoSilent()
* @param request
* @param interactionType
*/
StandardInteractionClient.prototype.initializeAuthorizationRequest = function (request, interactionType) {
return __awaiter(this, void 0, void 0, function () {
var redirectUri, browserState, state, validatedRequest, _a, account, legacyLoginHint;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
this.logger.verbose("initializeAuthorizationRequest called", this.correlationId);
redirectUri = this.getRedirectUri(request.redirectUri);
browserState = {
interactionType: interactionType
};
state = ProtocolUtils.setRequestState(this.browserCrypto, (request && request.state) || Constants.EMPTY_STRING, browserState);
_a = [{}];
return [4 /*yield*/, this.initializeBaseRequest(request)];
case 1:
validatedRequest = __assign.apply(void 0, [__assign.apply(void 0, _a.concat([_b.sent()])), { redirectUri: redirectUri, state: state, nonce: request.nonce || this.browserCrypto.createNewGuid(), responseMode: ResponseMode.FRAGMENT }]);
account = request.account || this.browserStorage.getActiveAccount();
if (account) {
this.logger.verbose("Setting validated request account", this.correlationId);
this.logger.verbosePii("Setting validated request account: " + account.homeAccountId, this.correlationId);
validatedRequest.account = account;
}
// Check for ADAL/MSAL v1 SSO
if (StringUtils.isEmpty(validatedRequest.loginHint) && !account) {
legacyLoginHint = this.browserStorage.getLegacyLoginHint();
if (legacyLoginHint) {
validatedRequest.loginHint = legacyLoginHint;
}
}
return [2 /*return*/, validatedRequest];
}
});
});
};
return StandardInteractionClient;
}(BaseInteractionClient));
export { StandardInteractionClient };
//# sourceMappingURL=StandardInteractionClient.js.map