"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.OboTokenProvider = void 0;
var tslib_1 = require("tslib");
var AadConstants_1 = tslib_1.__importDefault(require("../../AadConstants"));
var sp_diagnostics_1 = require("@microsoft/sp-diagnostics");
var SPHttpClient_1 = tslib_1.__importDefault(require("../../../spHttpClient/SPHttpClient"));
var AadErrorHandler_1 = require("../../AadErrorHandler");
var sp_core_library_1 = require("@microsoft/sp-core-library");
/**
 * Class that wraps the ADAL's authentication class
 * @internal
 */
var OboTokenProvider = /** @class */ (function () {
    function OboTokenProvider(authContext, tokenParameters, oboFirstPartyTokenCallback) {
        var _this = this;
        this._exchange1PTokenFor3P = function (firstPartyToken) {
            var urlToCall = _this._serverRelativeUrl + "/_api/Microsoft.SharePoint.Internal" +
                (".ClientSideComponent.Token.AcquireOBOToken?resource='" + _this._authContext.config.clientId + "'") +
                ("&clientId='" + AadConstants_1.default.PRE_AUTHORIZED_APP_PRINCIPAL_ID + "'");
            var requestInfo = {
                headers: {
                    'X-HTTP-Method': 'GET',
                    'OData-Version': '3.0',
                    OBOToken: firstPartyToken,
                    ClientId: AadConstants_1.default.PRE_AUTHORIZED_APP_PRINCIPAL_ID,
                    Resource: _this._authContext.config.clientId
                }
            };
            return _this._spHttpClient
                .get(urlToCall, SPHttpClient_1.default.configurations.v1, requestInfo)
                .then(function (response) {
                return response.ok ? response.json() : Promise.reject(response.json());
            })
                .then(function (json) {
                return JSON.parse(json.value).AccessToken;
            })
                .catch(function () {
                // If the request failed, clear this cache to retry
                _this._oboFirstPartyTokenRequest = undefined;
            });
        };
        this.servicePrincipalId = authContext.config.clientId;
        this._patchAdalAuthContext(authContext);
        this._authContext = authContext;
        this._serverRelativeUrl = tokenParameters.serverRelativeUrl;
        this._spHttpClient = tokenParameters.spHttpClient;
        this._oboFirstPartyTokenCallback = oboFirstPartyTokenCallback;
    }
    OboTokenProvider.prototype.getToken = function (resourceEndpoint, useCachedToken) {
        if (useCachedToken === void 0) { useCachedToken = true; }
        var acquireAccessTokenQosMonitor = new sp_diagnostics_1._QosMonitor('OboTokenProvider.GetToken');
        return this._getAccessToken(resourceEndpoint, useCachedToken)
            .then(function (token) {
            acquireAccessTokenQosMonitor.writeSuccess();
            return token;
        })
            .catch(function (e) {
            acquireAccessTokenQosMonitor.writeUnexpectedFailure('TokenAcquisitionFailure', e);
            throw e;
        });
    };
    OboTokenProvider.prototype._getAccessToken = function (resourceEndpoint, useCachedToken) {
        var cachedAccessToken = this._tryGetCachedAccessToken(resourceEndpoint);
        if (useCachedToken && cachedAccessToken) {
            return Promise.resolve(cachedAccessToken);
        }
        else {
            return this._fetchAccessToken(resourceEndpoint);
        }
    };
    /**
     * Returns an access token if a valid cached token exists
     */
    OboTokenProvider.prototype._tryGetCachedAccessToken = function (resourceEndpoint) {
        var cachedToken;
        try {
            cachedToken = this._authContext.getCachedToken(resourceEndpoint);
        }
        catch (e) {
            sp_diagnostics_1._TraceLogger.logError(OboTokenProvider._logSource, e);
        }
        return cachedToken;
    };
    /**
     * See the following link for details about handling conditional access policies.
     * https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-conditional-access-developer
     */
    OboTokenProvider.prototype._fetchAccessToken = function (resourceEndpoint) {
        var acquireAccessTokenQosMonitor = new sp_diagnostics_1._QosMonitor('OboTokenProvider.FetchAccessToken');
        // Attempt to fetch a new access token
        return this._fetchAccessTokenSilent(resourceEndpoint)
            .then(function (token) {
            acquireAccessTokenQosMonitor.writeSuccess();
            return token;
        })
            .catch(function (e) {
            if (e.message &&
                AadErrorHandler_1.AadErrorHandler._doesAadErrorCodeExist(e.message, AadConstants_1.default.EXPECTED_AAD_ERRORS)) {
                acquireAccessTokenQosMonitor.writeExpectedFailure('TokenAcquisitionFailure', e);
            }
            else {
                acquireAccessTokenQosMonitor.writeUnexpectedFailure('TokenAcquisitionFailure', e);
            }
            throw e;
        });
    };
    OboTokenProvider.prototype._getOboAuthToken = function (claims) {
        var _this = this;
        if (this._oboFirstPartyTokenCallback) {
            return this._oboFirstPartyTokenCallback(claims).then(function (firstPartyToken) {
                if (_this._authContext.config.clientId === AadConstants_1.default.PRE_AUTHORIZED_APP_PRINCIPAL_ID) {
                    return Promise.resolve(firstPartyToken);
                }
                else {
                    if (!_this._oboFirstPartyTokenRequest || claims) {
                        _this._oboFirstPartyTokenRequest = _this._exchange1PTokenFor3P(firstPartyToken);
                    }
                    return _this._oboFirstPartyTokenRequest;
                }
            });
        }
        else {
            return Promise.resolve(undefined);
        }
    };
    /**
     * Wraps the ADAL.js callback code with a promise.
     */
    OboTokenProvider.prototype._fetchAccessTokenSilent = function (resourceEndpoint, claims) {
        var _this = this;
        return this._getOboAuthToken(claims).then(function (oboAuthToken) {
            var urlToCall = _this._serverRelativeUrl + "/_api/Microsoft.SharePoint.Internal" +
                (".ClientSideComponent.Token.AcquireOBOToken?resource='" + resourceEndpoint + "'") +
                ("&clientId='" + _this._authContext.config.clientId + "'");
            var requestInfo = {
                headers: {
                    'X-HTTP-Method': 'GET',
                    'OData-Version': '3.0'
                }
            };
            if (oboAuthToken) {
                // tslint:disable-next-line:no-string-literal
                requestInfo.headers['OBOToken'] = oboAuthToken;
            }
            if (!sp_core_library_1._SPKillSwitch.isActivated(OboTokenProvider.useHeadersKillSwitchGuid, '1/9/2020', 'Use headers for requesting tokens')) {
                requestInfo.headers = tslib_1.__assign(tslib_1.__assign({}, requestInfo.headers), { ClientId: _this._authContext.config.clientId, Resource: resourceEndpoint });
            }
            return _this._spHttpClient
                .get(urlToCall, SPHttpClient_1.default.configurations.v1, requestInfo)
                .then(function (response) {
                if (response.ok) {
                    return response.json();
                }
                else {
                    if (response.status === 401) {
                        // Authenticate header will look like this:
                        // `Bearer realm="7fe4c4f2-31c2-4651-bdfd-b7692b373e02",client_id="00000003-0000-0ff1-ce00-000000000000",trusted_issuers="D3776938-3DBA-481F-A652-4BEDFCAB7CD8@*,https://sts.windows-ppe.net/*/,00000003-0000-0ff1-ce00-000000000000@90140122-8516-11e1-8eff-49304924019b",authorization_uri="https://login.windows-ppe.net/common/oauth2/authorize",error="insufficient_claims",claims="eyJhY2Nlc3NfdG9rZW4iOnsiY2Fwb2xpZHMiOnsiZXNzZW50aWFsIjp0cnVlLCJ2YWx1ZXMiOlsiNGE0YzkwOWItYzdiNi00MWQxLWE3MzQtZTA2MzRiNTJjOGU1Il19fX0="`;
                        var authenticateHeader = response.headers.get('WWW-Authenticate');
                        if (!claims && authenticateHeader) {
                            var requiredClaims = authenticateHeader
                                .split(',')
                                .map(function (nameValue) {
                                var equalIndex = nameValue.indexOf('=');
                                return [nameValue.substr(0, equalIndex), nameValue.substr(equalIndex + 1)];
                            })
                                .filter(function (nameValueArray) { return nameValueArray[0] === 'claims'; })[0][1]
                                // Claims is base 64 encoded and includes quotes, this strips out the quotes (which is not a base 64 encoded value so no worries of changing the data)
                                .replace(/"/g, '');
                            return _this._fetchAccessTokenSilent(resourceEndpoint, [requiredClaims]);
                        }
                    }
                    return Promise.reject(response.json());
                }
            })
                .then(function (json) {
                if (typeof json === 'string') {
                    // If this is the response from a recursive call to _fetchAccessTokenSilent we just want to return
                    return json;
                }
                else {
                    return JSON.parse(json.value).AccessToken;
                }
            });
        });
    };
    /**
     * Adal creates an iframe without the sandbox attribute.
     * Adal assumes it's being used as a singleton but this will not work for our scenario.
     */
    OboTokenProvider.prototype._patchAdalAuthContext = function (authContext) {
        Object.getPrototypeOf(authContext)._singletonInstance = undefined;
    };
    OboTokenProvider._logSource = sp_diagnostics_1._LogSource.create('OBOTokenProvider');
    OboTokenProvider.useHeadersKillSwitchGuid = sp_core_library_1.Guid.parse('6f64a6ed-dc35-422c-a368-539dd03f9b9b');
    return OboTokenProvider;
}());
exports.OboTokenProvider = OboTokenProvider;
//# sourceMappingURL=OboTokenProvider.js.map