UNPKG

@microsoft/mgt

Version:
224 lines • 9.75 kB
/** * ------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. * See License in the project root for license information. * ------------------------------------------------------------------------------------------- */ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { UserAgentApplication } from 'msal'; import { LoginType, ProviderState } from './IProvider'; import { MsalProvider } from './MsalProvider'; /** * Enables authentication of Single page apps inside of a Microsoft Teams tab * * @export * @class TeamsProvider * @extends {MsalProvider} */ export class TeamsProvider extends MsalProvider { constructor(config) { super({ clientId: config.clientId, loginType: LoginType.Redirect, options: config.msalOptions, scopes: config.scopes }); const teams = TeamsProvider.microsoftTeamsLib || microsoftTeams; this._authPopupUrl = config.authPopupUrl; teams.initialize(); } /** * Gets whether the Teams provider can be used in the current context * (Whether the app is running in Microsoft Teams) * * @readonly * @static * @memberof TeamsProvider */ static get isAvailable() { if (window.parent === window.self && window.nativeInterface) { // In Teams mobile client return true; } else if (window.name === 'embedded-page-container' || window.name === 'extension-tab-frame') { // In Teams web/desktop client return true; } else { return false; } } /** * Handle all authentication redirects in the authentication page and authenticates the user * * @static * @returns * @memberof TeamsProvider */ static handleAuth() { return __awaiter(this, void 0, void 0, function* () { // we are in popup world now - authenticate and handle it const teams = TeamsProvider.microsoftTeamsLib || microsoftTeams; if (!teams) { // tslint:disable-next-line: no-console console.error('Make sure you have referenced the Microsoft Teams sdk before using the TeamsProvider'); return; } teams.initialize(); // msal checks for the window.opener.msal to check if this is a popup authentication // and gets a false positive since teams opens a popup for the authentication. // in reality, we are doing a redirect authentication and need to act as if this is the // window initiating the authentication if (window.opener) { window.opener.msal = null; } const url = new URL(window.location.href); const paramsString = sessionStorage.getItem(this._sessionStorageParametersKey); let authParams; if (paramsString) { authParams = JSON.parse(paramsString); } else { authParams = {}; } if (!authParams.clientId) { authParams.clientId = url.searchParams.get('clientId'); authParams.scopes = url.searchParams.get('scopes'); authParams.loginHint = url.searchParams.get('loginHint'); sessionStorage.setItem(this._sessionStorageParametersKey, JSON.stringify(authParams)); } if (!authParams.clientId) { teams.authentication.notifyFailure('no clientId provided'); return; } const scopes = authParams.scopes ? authParams.scopes.split(',') : null; const provider = new MsalProvider({ clientId: authParams.clientId, options: { auth: { clientId: authParams.clientId, redirectUri: url.protocol + '//' + url.host + url.pathname }, system: { loadFrameTimeout: 10000 } }, scopes }); if (UserAgentApplication.prototype.urlContainsHash(window.location.hash)) { // the page should redirect again return; } const handleProviderState = () => __awaiter(this, void 0, void 0, function* () { // how do we handle when user can't sign in // change to promise and return status if (provider.state === ProviderState.SignedOut) { provider.login({ loginHint: authParams.loginHint, scopes: scopes || provider.scopes }); } else if (provider.state === ProviderState.SignedIn) { try { const accessToken = yield provider.getAccessTokenForScopes(...provider.scopes); sessionStorage.removeItem(this._sessionStorageParametersKey); teams.authentication.notifySuccess(accessToken); } catch (e) { sessionStorage.removeItem(this._sessionStorageParametersKey); teams.authentication.notifyFailure(e); } } }); provider.onStateChanged(handleProviderState); handleProviderState(); }); } /** * Opens the teams authentication popup to the authentication page * * @returns {Promise<void>} * @memberof TeamsProvider */ login() { return __awaiter(this, void 0, void 0, function* () { this.setState(ProviderState.Loading); const teams = TeamsProvider.microsoftTeamsLib || microsoftTeams; return new Promise((resolve, reject) => { teams.getContext(context => { this.teamsContext = context; const url = new URL(this._authPopupUrl, new URL(window.location.href)); url.searchParams.append('clientId', this.clientId); if (context.loginHint) { url.searchParams.append('loginHint', context.loginHint); } if (this.scopes) { url.searchParams.append('scopes', this.scopes.join(',')); } teams.authentication.authenticate({ failureCallback: reason => { this.setState(ProviderState.SignedOut); reject(); }, successCallback: result => { this.setState(ProviderState.SignedIn); resolve(); }, url: url.href }); }); }); }); } /** * Returns an access token that can be used for making calls to the Microsoft Graph * * @param {AuthenticationProviderOptions} options * @returns {Promise<string>} * @memberof TeamsProvider */ getAccessToken(options) { return __awaiter(this, void 0, void 0, function* () { if (!this.teamsContext) { const teams = TeamsProvider.microsoftTeamsLib || microsoftTeams; this.teamsContext = yield teams.getContext(); } const scopes = options ? options.scopes || this.scopes : this.scopes; const accessTokenRequest = { scopes }; if (this.teamsContext && this.teamsContext.loginHint) { accessTokenRequest.loginHint = this.teamsContext.loginHint; } const currentParent = window.parent; if (document.referrer.startsWith('https://teams.microsoft.com/')) { window.parent = window; } try { const response = yield this._userAgentApplication.acquireTokenSilent(accessTokenRequest); window.parent = currentParent; return response.accessToken; } catch (e) { window.parent = currentParent; if (this.requiresInteraction(e)) { // nothing we can do now until we can do incremental consent return null; } else { throw e; } } }); } } TeamsProvider._sessionStorageParametersKey = 'msg-teamsprovider-auth-parameters'; //# sourceMappingURL=TeamsProvider.js.map