"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DeferredAadTokenProvider = void 0;
var tslib_1 = require("tslib");
var sp_core_library_1 = require("@microsoft/sp-core-library");
var sp_diagnostics_1 = require("@microsoft/sp-diagnostics");
var strings = tslib_1.__importStar(require("../../../SPHttpStrings.resx"));
var AadConstants_1 = tslib_1.__importDefault(require("../../AadConstants"));
var AadKillSwitches_1 = require("../../AadKillSwitches");
/**
 * This class allows a developer to obtain OAuth2 tokens from Azure AD.
 *
 * OAuth2 tokens are used to authenticate the user from the SharePoint page
 * to other services such as PowerBI, Sway, Exchange, Yammer, etc.
 *
 * @privateRemarks
 * AadTokenProvider is replacing the /_api.SP.OAuth.Token/Acquire endpoint
 * for authentication with ADAL.js. At some point in the near future, when Azure AD v2.0
 * can support the same scenarios as the original version, we will switch to MSAL.
 *
 * @public
 * @sealed
 */
var DeferredAadTokenProvider = /** @class */ (function () {
    /**
     * @internal
     */
    function DeferredAadTokenProvider(tokenAcquisitionEvent, beforeRedirectEvent, configuration, oboConfiguration, oboFirstPartyTokenCallback) {
        sp_core_library_1.Validate.isNonemptyString(configuration.aadInstanceUrl, 'aadInstanceUrl');
        sp_core_library_1.Validate.isNonemptyString(configuration.aadTenantId, 'aadTenantId');
        sp_core_library_1.Validate.isNonemptyString(configuration.redirectUri, 'redirectUri');
        sp_core_library_1.Validate.isNonemptyString(configuration.servicePrincipalId, 'servicePrincipalId');
        this._defaultConfiguration = configuration;
        this._oboConfiguration = oboConfiguration;
        this._oboFirstPartyTokenCallback = oboFirstPartyTokenCallback;
        this._tokenAcquisitionEvent = tokenAcquisitionEvent;
        this.onBeforeRedirectEvent = beforeRedirectEvent;
    }
    /**
     * Fetches the AAD OAuth2 token for a resource if the user that's currently logged in has
     * access to that resource.
     *
     * The OAuth2 token should not be cached by the caller since it is already cached by the method
     * itself.
     *
     * @param resourceEndpoint - the resource for which the token should be obtained
     * @param useCachedToken - Allows the developer to specify if cached tokens should be returned.
     * An example of a resourceEndpoint would be https://graph.microsoft.com
     * @returns A promise that will be fullfiled with the token or that will reject
     *          with an error message
     */
    DeferredAadTokenProvider.prototype.getToken = function (resourceEndpoint, useCachedToken) {
        var _this = this;
        if (useCachedToken === void 0) { useCachedToken = true; }
        if (this._defaultConfiguration.servicePrincipalId === sp_core_library_1.Guid.empty.toString()) {
            return Promise.reject(new Error(strings.servicePrincipalNotAvaliableError));
        }
        if (!sp_core_library_1._SPKillSwitch.isActivated(DeferredAadTokenProvider.msalTrialRunKillSwitchGuid, '09/11/19', 'Run MSAL for only 1/10th of all requests') &&
            Math.floor(Math.random() * 10) === 0) {
            this._getMsalTokenProvider(this._defaultConfiguration)
                .then(function (tokenProvider) { return _this._getToken(tokenProvider, resourceEndpoint, useCachedToken); })
                .catch(function (e) {
                /* ignore failures as the function already does logging */
            });
        }
        return this._getTokenInternal(resourceEndpoint, this._defaultConfiguration, useCachedToken);
    };
    /**
     * Fetches the AAD OAuth2 token data for a resource if the user that's currently logged in has
     * access to that resource.
     *
     * Only supports MSAL at the moment
     *
     * @internal
     */
    DeferredAadTokenProvider.prototype._getTokenData = function (resourceEndpoint, useCachedToken, skipLogging) {
        if (useCachedToken === void 0) { useCachedToken = true; }
        if (skipLogging === void 0) { skipLogging = false; }
        if (this._defaultConfiguration.servicePrincipalId === sp_core_library_1.Guid.empty.toString()) {
            return Promise.reject(new Error(strings.servicePrincipalNotAvaliableError));
        }
        if (this._shouldUseMsalTokenProvider()) {
            return this._getMsalTokenProvider(this._defaultConfiguration).then(function (tokenProvider) {
                return tokenProvider.getTokenData(resourceEndpoint, useCachedToken, skipLogging);
            });
        }
        else {
            var errorString = 'Getting token response not supported for the current token provider';
            throw new Error(errorString);
        }
    };
    /**
     * Fetches the AAD OAuth2 token for a resource if the user that's currently logged in has
     * access to that resource.
     *
     * The OAuth2 token should not be cached by the caller since it is already cached by the method
     * itself.
     *
     * @param resourceEndpoint - the resource for which the token should be obtained
     * @param useCachedToken - Allows the developer to specify if cached tokens should be returned.
     * An example of a resourceEndpoint would be https://graph.microsoft.com
     * @returns A promise that will be fullfiled with the token or that will reject
     *          with an error message
     *
     * @internal
     */
    DeferredAadTokenProvider.prototype._getTokenInternal = function (resourceEndpoint, configuration, useCachedToken) {
        var _this = this;
        if (useCachedToken === void 0) { useCachedToken = true; }
        var acquireTokenQosMonitor = new sp_diagnostics_1._QosMonitor('AadTokenProvider.GetAppTokenTimePerf');
        var getTokenPromise;
        var tokenProviderConfig = configuration || this._defaultConfiguration;
        if (this._shouldUseOboTokenExchange() && this._oboConfiguration) {
            // OBO Token Exchange is only supported for 3rd Parties. Using the default configuration will
            // prevent this code path from running for 1st party requests
            getTokenPromise = this._getOboTokenProvider(sp_core_library_1._SPFlight.isEnabled(60254) /* Support 1st party OBO */
                ? tokenProviderConfig
                : this._defaultConfiguration, this._oboConfiguration, this._oboFirstPartyTokenCallback).then(function (tokenProvider) { return _this._getToken(tokenProvider, resourceEndpoint, useCachedToken); });
        }
        else if (this._shouldUseMsalTokenProvider()) {
            getTokenPromise = this._getMsalTokenProvider(tokenProviderConfig).then(function (tokenProvider) {
                return _this._getToken(tokenProvider, resourceEndpoint, useCachedToken);
            });
        }
        else if (sp_core_library_1._SPFlight.isEnabled(1476) /* Implicit Token Provider */) {
            getTokenPromise = this._getImplicitTokenProvider(tokenProviderConfig).then(function (tokenProvider) {
                return _this._getToken(tokenProvider, resourceEndpoint, useCachedToken);
            });
        }
        else {
            getTokenPromise = this._getAdalTokenProvider(tokenProviderConfig).then(function (authContext) {
                return authContext.getToken(resourceEndpoint, useCachedToken);
            });
        }
        return getTokenPromise
            .then(function (token) {
            if (AadKillSwitches_1.AadKillSwitches.isLogAadAdditionalTelemetryEnabled()) {
                var isInternal = tokenProviderConfig.servicePrincipalId === AadConstants_1.default.PRE_AUTHORIZED_APP_PRINCIPAL_ID;
                var extraData = {
                    isInternal: isInternal
                };
                // We can only log the endpoint if first party to avoid privacy issues
                if (isInternal) {
                    extraData.name = resourceEndpoint;
                }
                acquireTokenQosMonitor.writeSuccess(extraData);
            }
            return token;
        })
            .catch(function (error) {
            if (AadKillSwitches_1.AadKillSwitches.isLogAadAdditionalTelemetryEnabled()) {
                acquireTokenQosMonitor.writeUnexpectedFailure();
            }
            throw error;
        });
    };
    DeferredAadTokenProvider.prototype._getToken = function (tokenProvider, resourceEndpoint, useCachedToken) {
        return tokenProvider.getToken(resourceEndpoint, useCachedToken);
    };
    Object.defineProperty(DeferredAadTokenProvider.prototype, "tokenAcquisitionEvent", {
        /**
         * Notifies the developer when Token Acquisition requires user action.
         * @eventproperty
         */
        get: function () {
            return this._tokenAcquisitionEvent;
        },
        enumerable: false,
        configurable: true
    });
    /**
     * Check for determining if the MSAL API should be used in the current environment.
     */
    DeferredAadTokenProvider.prototype._shouldUseMsalTokenProvider = function () {
        return !!sp_core_library_1.Guid.tryParse(this._defaultConfiguration.aadSessionId);
    };
    DeferredAadTokenProvider.prototype._getAdalAuthContextManager = function (configuration) {
        if (!this._authContextManager) {
            this._authContextManager = Promise.resolve().then(function () { return tslib_1.__importStar(require('../adalAuthContextManager/AdalAuthContextManager' /* webpackChunkName: 'adalauthcontext' */)); }).then(function (adalAuthContextManagerModule) { return new adalAuthContextManagerModule.AdalAuthContextManager(); });
        }
        return this._authContextManager;
    };
    DeferredAadTokenProvider.prototype._getAdalTokenProvider = function (configuration) {
        return this._getAdalAuthContextManager(configuration).then(function (adalAuthContextManager) {
            return adalAuthContextManager.getAdalTokenProvider(configuration);
        });
    };
    DeferredAadTokenProvider.prototype._getMsalTokenProvider = function (configuration) {
        var _this = this;
        return Promise.resolve().then(function () { return tslib_1.__importStar(require('../msalImplicit/MsalTokenProvider' /* webpackChunkName: 'msalImplicit' */)); }).then(function (msalTokenProviderModule) {
            if (_this._isFirstParty(configuration.servicePrincipalId)) {
                if (!_this._firstPartyMsalTokenProvider) {
                    _this._firstPartyMsalTokenProvider = new msalTokenProviderModule.MsalTokenProvider(configuration);
                }
                return _this._firstPartyMsalTokenProvider;
            }
            else {
                if (!_this._thirdPartyMsalTokenProvider) {
                    _this._thirdPartyMsalTokenProvider = new msalTokenProviderModule.MsalTokenProvider(configuration);
                }
                return _this._thirdPartyMsalTokenProvider;
            }
        });
    };
    DeferredAadTokenProvider.prototype._getImplicitTokenProvider = function (configuration) {
        var _this = this;
        return Promise.resolve().then(function () { return tslib_1.__importStar(require('../implicitTokenProvider/ImplicitFlowTokenProvider' /* webpackChunkName: 'spoImplicit' */)); }).then(function (implicitTokenProviderModule) {
            if (_this._isFirstParty(configuration.servicePrincipalId)) {
                if (!_this._firstPartyImplicitTokenProvider) {
                    _this._firstPartyImplicitTokenProvider = new implicitTokenProviderModule.ImplicitFlowTokenProvider(configuration);
                }
                return _this._firstPartyImplicitTokenProvider;
            }
            else {
                if (!_this._thirdPartyImplicitTokenProvider) {
                    _this._thirdPartyImplicitTokenProvider = new implicitTokenProviderModule.ImplicitFlowTokenProvider(configuration);
                }
                return _this._thirdPartyImplicitTokenProvider;
            }
        });
    };
    DeferredAadTokenProvider.prototype._getOboTokenProvider = function (configuration, oboConfiguration, oboFirstPartyTokenCallback) {
        var _this = this;
        return this._getAdalAuthContextManager(configuration).then(function (adalAuthContextManager) {
            if (!_this._thirdPartyOboTokenProvider) {
                _this._thirdPartyOboTokenProvider = adalAuthContextManager.getOboTokenProvider(configuration, oboConfiguration, oboFirstPartyTokenCallback);
            }
            return _this._thirdPartyOboTokenProvider;
        });
    };
    DeferredAadTokenProvider.prototype._isFirstParty = function (clientId) {
        return clientId === AadConstants_1.default.PRE_AUTHORIZED_APP_PRINCIPAL_ID;
    };
    /**
     * Check for determining if the OBO Token Exchange API should be used in the current environment.
     */
    DeferredAadTokenProvider.prototype._shouldUseOboTokenExchange = function () {
        return !!this._oboConfiguration;
    };
    DeferredAadTokenProvider.msalTrialRunKillSwitchGuid = sp_core_library_1.Guid.parse('fa0b23a7-7b4e-4fbe-b635-bbed397c3ef5');
    return DeferredAadTokenProvider;
}());
exports.DeferredAadTokenProvider = DeferredAadTokenProvider;
//# sourceMappingURL=DeferredAadTokenProvider.js.map