From 42f77714645258419949f72cc51f215268dd2709 Mon Sep 17 00:00:00 2001 From: mattgeim Date: Mon, 2 Jun 2025 13:46:21 -0700 Subject: [PATCH 01/13] Update package.json --- Samples/auth/Office-Add-in-SSO-NAA/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Samples/auth/Office-Add-in-SSO-NAA/package.json b/Samples/auth/Office-Add-in-SSO-NAA/package.json index 8fba2a6bf..016019c73 100644 --- a/Samples/auth/Office-Add-in-SSO-NAA/package.json +++ b/Samples/auth/Office-Add-in-SSO-NAA/package.json @@ -28,7 +28,7 @@ "watch": "webpack --mode development --watch" }, "dependencies": { - "@azure/msal-browser": "^3.24.0", + "@azure/msal-browser": "^4.12.0", "core-js": "^3.37.1", "regenerator-runtime": "^0.14.1" }, From 063f44ee4014d66888753924ed5fc77741bfaa97 Mon Sep 17 00:00:00 2001 From: mattgeim Date: Mon, 2 Jun 2025 13:47:10 -0700 Subject: [PATCH 02/13] Update authConfig.ts --- .../src/taskpane/authConfig.ts | 167 ++++++++++++++---- 1 file changed, 132 insertions(+), 35 deletions(-) diff --git a/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/authConfig.ts b/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/authConfig.ts index e455c42a7..2358df712 100644 --- a/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/authConfig.ts +++ b/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/authConfig.ts @@ -3,71 +3,168 @@ /* This file provides MSAL auth configuration to get access token through nested app authentication. */ -/* global console */ +/* global Office, console, document*/ -import { PublicClientNext, type IPublicClientApplication } from "@azure/msal-browser"; +import { + BrowserAuthError, + createNestablePublicClientApplication, + type IPublicClientApplication, +} from "@azure/msal-browser"; +import { msalConfig } from "./msalconfig"; +import { createLocalUrl } from "./util"; +import { getTokenRequest } from "./msalcommon"; -export { AccountManager }; - -const applicationId = "Enter_the_Application_Id_Here"; - -const msalConfig = { - auth: { - clientId: applicationId, - authority: "https://login.microsoftonline.com/common", - supportsNestedAppAuth: true, - }, +export type AuthDialogResult = { + accessToken?: string; + error?: string; }; +type DialogEventMessage = { message: string; origin: string | undefined }; +type DialogEventError = { error: number }; +type DialogEventArg = DialogEventMessage | DialogEventError; + // Encapsulate functions for getting user account and token information. -class AccountManager { - pca: IPublicClientApplication | undefined = undefined; +export class AccountManager { + private pca: IPublicClientApplication | undefined = undefined; + private _dialogApiResult: Promise | null = null; + private _usingFallbackDialog = false; + + private getSignOutButton() { + return document.getElementById("signOutButton"); + } + + private setSignOutButtonVisibility(isVisible: boolean) { + const signOutButton = this.getSignOutButton(); + if (signOutButton) { + signOutButton.style.visibility = isVisible ? "visible" : "hidden"; + } + } + + private isNestedAppAuthSupported() { + return Office.context.requirements.isSetSupported("NestedAppAuth", "1.1"); + } // Initialize MSAL public client application. async initialize() { - this.pca = await PublicClientNext.createPublicClientApplication(msalConfig); + // Make sure office.js is initialized + await Office.onReady(); + + // If auth is not working, enable debug logging to help diagnose. + this.pca = await createNestablePublicClientApplication(msalConfig); + + // If Office does not support Nested App Auth provide a sign-out button since the user selects account + if (!this.isNestedAppAuthSupported() && this.pca.getActiveAccount()) { + this.setSignOutButtonVisibility(true); + } + this.getSignOutButton()?.addEventListener("click", () => this.signOut()); } - async ssoGetToken(scopes: string[]) { - const userAccount = await this.ssoGetUserIdentity(scopes); - return userAccount.accessToken; + private async signOut() { + if (this._usingFallbackDialog) { + await this.signOutWithDialogApi(); + } else { + await this.pca?.logoutPopup(); + } + + this.setSignOutButtonVisibility(false); } /** - * Uses MSAL and nested app authentication to get the user account from Office SSO. - * This demonstrates how to work with user identity from the token. * - * @returns The user account data (identity). + * @param scopes the minimum scopes needed. + * @returns An access token. */ - async ssoGetUserIdentity(scopes: string[]) { + async ssoGetAccessToken(scopes: string[]) { + if (this._dialogApiResult) { + return this._dialogApiResult; + } + if (this.pca === undefined) { throw new Error("AccountManager is not initialized!"); } - // Specify minimum scopes needed for the access token. - const tokenRequest = { - scopes: scopes - }; - try { console.log("Trying to acquire token silently..."); - const userAccount = await this.pca.acquireTokenSilent(tokenRequest); + const authResult = await this.pca.acquireTokenSilent(getTokenRequest(scopes, false)); console.log("Acquired token silently."); - return userAccount; + return authResult.accessToken; } catch (error) { - console.log(`Unable to acquire token silently: ${error}`); + console.warn(`Unable to acquire token silently: ${error}`); } // Acquire token silent failure. Send an interactive request via popup. try { console.log("Trying to acquire token interactively..."); - const userAccount = await this.pca.acquireTokenPopup(tokenRequest); + const selectAccount = this.pca.getActiveAccount() ? false : true; + const authResult = await this.pca.acquireTokenPopup(getTokenRequest(scopes, selectAccount)); console.log("Acquired token interactively."); - return userAccount; + if (selectAccount) { + this.pca.setActiveAccount(authResult.account); + } + if (!this.isNestedAppAuthSupported()) { + this.setSignOutButtonVisibility(true); + } + return authResult.accessToken; } catch (popupError) { - // Acquire token interactive failure. - console.log(`Unable to acquire token interactively: ${popupError}`); - throw new Error(`Unable to acquire access token: ${popupError}`); + // Optional fallback if about:blank popup should not be shown + if (popupError instanceof BrowserAuthError && popupError.errorCode === "popup_window_error") { + const accessToken = await this.getTokenWithDialogApi(); + return accessToken; + } else { + // Acquire token interactive failure. + console.error(`Unable to acquire token interactively: ${popupError}`); + throw new Error(`Unable to acquire access token: ${popupError}`); + } } } + + /** + * Gets an access token by using the Office dialog API to handle authentication. Used for fallback scenario. + * @returns The access token. + */ + async getTokenWithDialogApi(): Promise { + this._dialogApiResult = new Promise((resolve, reject) => { + Office.context.ui.displayDialogAsync(createLocalUrl(`dialog.html`), { height: 60, width: 30 }, (result) => { + result.value.addEventHandler(Office.EventType.DialogEventReceived, (arg: DialogEventArg) => { + const errorArg = arg as DialogEventError; + if (errorArg.error == 12006) { + this._dialogApiResult = null; + reject("Dialog closed"); + } + }); + result.value.addEventHandler(Office.EventType.DialogMessageReceived, (arg: DialogEventArg) => { + const messageArg = arg as DialogEventMessage; + const parsedMessage = JSON.parse(messageArg.message); + result.value.close(); + + if (parsedMessage.error) { + reject(parsedMessage.error); + this._dialogApiResult = null; + } else { + resolve(parsedMessage.accessToken); + this.setSignOutButtonVisibility(true); + this._usingFallbackDialog = true; + } + }); + }); + }); + return this._dialogApiResult; + } + + signOutWithDialogApi(): Promise { + return new Promise((resolve) => { + Office.context.ui.displayDialogAsync( + createLocalUrl(`dialog.html?logout=1`), + { height: 60, width: 30 }, + (result) => { + result.value.addEventHandler(Office.EventType.DialogMessageReceived, () => { + this.setSignOutButtonVisibility(false); + this._dialogApiResult = null; + resolve(); + result.value.close(); + }); + } + ); + }); + } } From 66c4c20b8d03a331601f26a22d43add7f81a36ab Mon Sep 17 00:00:00 2001 From: mattgeim Date: Mon, 2 Jun 2025 13:48:46 -0700 Subject: [PATCH 03/13] Create msalconfig.ts --- .../src/taskpane/msalconfig.ts | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/msalconfig.ts diff --git a/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/msalconfig.ts b/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/msalconfig.ts new file mode 100644 index 000000000..add72a0f1 --- /dev/null +++ b/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/msalconfig.ts @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +// This file provides the default MSAL configuration for the add-in project. + +import { LogLevel } from "@azure/msal-browser"; +import { createLocalUrl } from "./util"; + +/* global console */ + +export const clientId = "Enter your Application ID here"; // Replace with your actual Application ID +export const msalConfig = { + auth: { + clientId, + redirectUri: createLocalUrl("auth.html"), + postLogoutRedirectUri: createLocalUrl("auth.html"), + }, + cache: { + cacheLocation: "localStorage", + }, + system: { + loggerOptions: { + logLevel: LogLevel.Verbose, + loggerCallback: (level: LogLevel, message: string) => { + switch (level) { + case LogLevel.Error: + console.error(message); + return; + case LogLevel.Info: + console.info(message); + return; + case LogLevel.Verbose: + console.debug(message); + return; + case LogLevel.Warning: + console.warn(message); + return; + } + }, + piiLoggingEnabled: true, + }, + }, +}; + +// Default scopes to use in the fallback dialog. +export const defaultScopes = ["user.read", "files.read"]; From 3f7d1b3d625cb20711620026fdd651d4dde53e02 Mon Sep 17 00:00:00 2001 From: mattgeim Date: Mon, 2 Jun 2025 13:51:19 -0700 Subject: [PATCH 04/13] Update taskpane.ts --- .../Office-Add-in-SSO-NAA/src/taskpane/taskpane.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/taskpane.ts b/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/taskpane.ts index 92774609c..953d78f04 100644 --- a/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/taskpane.ts +++ b/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/taskpane.ts @@ -46,19 +46,19 @@ Office.onReady((info) => { async function getUserData() { try { const userDataElement = document.getElementById("userData"); - const userAccount = await accountManager.ssoGetUserIdentity(["user.read"]); - const idTokenClaims = userAccount.idTokenClaims as { name?: string; preferred_username?: string }; - - console.log(userAccount); + const accessToken = await accountManager.ssoGetAccessToken(["User.Read"]); + const response: { displayName: string; mail: string } = await makeGraphRequest(accessToken, "/me", ""); + + console.log(response); if (userDataElement) { userDataElement.style.visibility = "visible"; } if (userName) { - userName.innerText = idTokenClaims.name ?? ""; + userName.innerText = response.displayName ?? ""; } if (userEmail) { - userEmail.innerText = idTokenClaims.preferred_username ?? ""; + userEmail.innerText = response.mail ?? ""; } } catch (error) { console.error(error); @@ -80,7 +80,7 @@ async function getUserFiles() { } async function getFileNames(count = 10) { - const accessToken = await accountManager.ssoGetToken(["Files.Read"]); + const accessToken = await accountManager.ssoGetAccessToken(["Files.Read"]); const response: { value: { name: string }[] } = await makeGraphRequest( accessToken, "/me/drive/root/children", From 5df851f98c41d649bad2906daa32aad7d7a175b2 Mon Sep 17 00:00:00 2001 From: mattgeim Date: Mon, 2 Jun 2025 13:52:14 -0700 Subject: [PATCH 05/13] Create util.ts --- .../auth/Office-Add-in-SSO-NAA/src/taskpane/util.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/util.ts diff --git a/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/util.ts b/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/util.ts new file mode 100644 index 000000000..e777e142b --- /dev/null +++ b/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/util.ts @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +/* global window */ + +/** + * Constructs a local URL for the web page for the given path. + * @param path The path to construct a local URL for. + * @returns + */ +export function createLocalUrl(path: string) { + return `${window.location.origin}/${path}`; +} From 19233d9191d6a68d01800d32227eb9517195acda Mon Sep 17 00:00:00 2001 From: mattgeim Date: Tue, 3 Jun 2025 12:47:33 -0700 Subject: [PATCH 06/13] Create msalcommon.ts --- .../src/taskpane/msalcommon.ts | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/msalcommon.ts diff --git a/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/msalcommon.ts b/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/msalcommon.ts new file mode 100644 index 000000000..9cd2fc9b2 --- /dev/null +++ b/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/msalcommon.ts @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +// This file provides common MSAL functions for use in the add-in project. + +import { + createNestablePublicClientApplication, + type IPublicClientApplication, + type RedirectRequest, +} from "@azure/msal-browser"; +import { msalConfig } from "./msalconfig"; + +/** + * Gets a token request for a given account context. + * @param accountContext The account context to get the token request for. + * @returns The token request. + */ +export function getTokenRequest(scopes: string[], selectAccount: boolean, redirectUri?: string): RedirectRequest { + let additionalProperties: Partial = {}; + if (selectAccount) { + additionalProperties = { prompt: "select_account" }; + } + if (redirectUri) { + additionalProperties.redirectUri = redirectUri; + } + return { scopes, ...additionalProperties }; +} + +let _publicClientApp: IPublicClientApplication; + +/** + * Returns the existing public client application. Returns a new public client application if it did not exist. + * @returns The nested public client application. + */ +export async function ensurePublicClient() { + if (!_publicClientApp) { + _publicClientApp = await createNestablePublicClientApplication(msalConfig); + } + return _publicClientApp; +} From be6780482c055838a36764e18119d8de8254411b Mon Sep 17 00:00:00 2001 From: mattgeim Date: Tue, 3 Jun 2025 12:56:00 -0700 Subject: [PATCH 07/13] Update taskpane.html added sign out --- .../auth/Office-Add-in-SSO-NAA/src/taskpane/taskpane.html | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/taskpane.html b/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/taskpane.html index 156344fdc..6bcd138ec 100644 --- a/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/taskpane.html +++ b/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/taskpane.html @@ -49,6 +49,11 @@

SSO with nested app authentication

Get user files Gets the first 10 items from the user's OneDrive and inserts them in the document. +

From 09417fcd878800d832ee25af4b1cde93560303ae Mon Sep 17 00:00:00 2001 From: mattgeim Date: Tue, 3 Jun 2025 15:36:09 -0700 Subject: [PATCH 08/13] Create auth.html --- .../src/taskpane/fallback/auth.html | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/fallback/auth.html diff --git a/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/fallback/auth.html b/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/fallback/auth.html new file mode 100644 index 000000000..eb556cc62 --- /dev/null +++ b/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/fallback/auth.html @@ -0,0 +1,13 @@ + + + + + + + + + + Auth Page + + + From c74a3c85976820155c7803104537099202275f66 Mon Sep 17 00:00:00 2001 From: mattgeim Date: Tue, 3 Jun 2025 15:43:34 -0700 Subject: [PATCH 09/13] adding fallback files --- .../src/taskpane/fallback/dialog.html | 17 +++++ .../taskpane/fallback/fallbackauthdialog.ts | 76 +++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/fallback/dialog.html create mode 100644 Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/fallback/fallbackauthdialog.ts diff --git a/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/fallback/dialog.html b/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/fallback/dialog.html new file mode 100644 index 000000000..52eeb38a2 --- /dev/null +++ b/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/fallback/dialog.html @@ -0,0 +1,17 @@ + + + + + + + + + + Dialog + + + + + + + diff --git a/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/fallback/fallbackauthdialog.ts b/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/fallback/fallbackauthdialog.ts new file mode 100644 index 000000000..57109eb75 --- /dev/null +++ b/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/fallback/fallbackauthdialog.ts @@ -0,0 +1,76 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +/* This file handls MSAL auth for the fallback dialog page. */ + +/* global Office, window, URLSearchParams */ + +import { + AuthenticationResult, + createStandardPublicClientApplication, + IPublicClientApplication, +} from "@azure/msal-browser"; +import { getTokenRequest } from "../msalcommon"; +import { createLocalUrl } from "../util"; +import { defaultScopes, msalConfig } from "../msalconfig"; +import type { AuthDialogResult } from "../authConfig"; + +// read querystring parameter +function getQueryParameter(param: string) { + const params = new URLSearchParams(window.location.search); + return params.get(param); +} + +async function sendDialogMessage(message: string) { + await Office.onReady(); + Office.context.ui.messageParent(message); +} +async function returnResult(publicClientApp: IPublicClientApplication, authResult: AuthenticationResult) { + publicClientApp.setActiveAccount(authResult.account); + + const authDialogResult: AuthDialogResult = { + accessToken: authResult.accessToken, + }; + + sendDialogMessage(JSON.stringify(authDialogResult)); +} + +export async function initializeMsal() { + // Use standard Public Client instead of nested because this is a fallback path when nested app authentication isn't available. + const publicClientApp = await createStandardPublicClientApplication(msalConfig); + try { + if (getQueryParameter("logout") === "1") { + await publicClientApp.logoutRedirect({ postLogoutRedirectUri: createLocalUrl("dialog.html?close=1") }); + return; + } else if (getQueryParameter("close") === "1") { + sendDialogMessage("close"); + return; + } + const result = await publicClientApp.handleRedirectPromise(); + + if (result) { + return returnResult(publicClientApp, result); + } + } catch (ex: any) { + const authDialogResult: AuthDialogResult = { + error: ex.name, + }; + sendDialogMessage(JSON.stringify(authDialogResult)); + return; + } + + try { + if (publicClientApp.getActiveAccount()) { + const result = await publicClientApp.acquireTokenSilent(getTokenRequest(defaultScopes, false)); + if (result) { + return returnResult(publicClientApp, result); + } + } + } catch { + /* empty */ + } + + publicClientApp.acquireTokenRedirect(getTokenRequest(defaultScopes, true, createLocalUrl("dialog.html"))); +} + +initializeMsal(); From d8998fcf44688d07d0de9499015bb81f9221f857 Mon Sep 17 00:00:00 2001 From: mattgeim Date: Wed, 4 Jun 2025 13:49:27 -0700 Subject: [PATCH 10/13] Update README.md --- Samples/auth/Office-Add-in-SSO-NAA/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Samples/auth/Office-Add-in-SSO-NAA/README.md b/Samples/auth/Office-Add-in-SSO-NAA/README.md index 47ca61eb5..91c8de5ac 100644 --- a/Samples/auth/Office-Add-in-SSO-NAA/README.md +++ b/Samples/auth/Office-Add-in-SSO-NAA/README.md @@ -63,7 +63,7 @@ For more information on how to register your application, see [Register an appli 1. Clone or download this repository. 1. From the command line, or a terminal window, go to the root folder of this sample at `/samples/auth/Office-Add-in-SSO-NAA`. -1. Open the `src/taskpane/authConfig.ts` file. +1. Open the `src/taskpane/msal.ts` file. 1. Replace the placeholder "Enter_the_Application_Id_Here" with the Application ID that you copied. 1. Save the file. From 079b04878d360041ed3ba8d385c66b35f5a1998e Mon Sep 17 00:00:00 2001 From: mattgeim Date: Wed, 4 Jun 2025 13:51:20 -0700 Subject: [PATCH 11/13] Update README.md --- Samples/auth/Office-Add-in-SSO-NAA/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Samples/auth/Office-Add-in-SSO-NAA/README.md b/Samples/auth/Office-Add-in-SSO-NAA/README.md index 91c8de5ac..83f925994 100644 --- a/Samples/auth/Office-Add-in-SSO-NAA/README.md +++ b/Samples/auth/Office-Add-in-SSO-NAA/README.md @@ -63,7 +63,7 @@ For more information on how to register your application, see [Register an appli 1. Clone or download this repository. 1. From the command line, or a terminal window, go to the root folder of this sample at `/samples/auth/Office-Add-in-SSO-NAA`. -1. Open the `src/taskpane/msal.ts` file. +1. Open the `src/taskpane/msalconfig.ts` file. 1. Replace the placeholder "Enter_the_Application_Id_Here" with the Application ID that you copied. 1. Save the file. From 310feee6ac82c20ebfd92638a79d1ee407fca657 Mon Sep 17 00:00:00 2001 From: David Chesnut Date: Thu, 5 Jun 2025 13:43:55 -0700 Subject: [PATCH 12/13] Updates from testing --- Samples/auth/Office-Add-in-SSO-NAA/README.md | 8 ++- .../Office-Add-in-SSO-NAA/package-lock.json | 49 ++++++++++++++----- .../auth/Office-Add-in-SSO-NAA/package.json | 2 +- .../src/taskpane/authConfig.ts | 1 + .../taskpane/fallback/fallbackauthdialog.ts | 2 +- .../src/taskpane/msalconfig.ts | 2 +- .../src/taskpane/taskpane.html | 2 +- .../Office-Add-in-SSO-NAA/webpack.config.js | 11 +++++ 8 files changed, 60 insertions(+), 17 deletions(-) diff --git a/Samples/auth/Office-Add-in-SSO-NAA/README.md b/Samples/auth/Office-Add-in-SSO-NAA/README.md index 47ca61eb5..849f0028f 100644 --- a/Samples/auth/Office-Add-in-SSO-NAA/README.md +++ b/Samples/auth/Office-Add-in-SSO-NAA/README.md @@ -56,6 +56,11 @@ For a list of supported hosts, see [NAA supported accounts and hosts](https://le - Select **Register**. 1. On the **Office-Add-in-SSO-NAA** page, copy and save the value for the **Application (client) ID**. You'll use it in the next section. +1. Under **Manage** select **Authentication**. +1. In the **Single-page application** pane, select **Add URI**. +1. Enter the value `https://localhost:3000/auth.html` and select **Save**. This redirect handles the fallback scenario when browser auth is used from add-in. +1. In the **Single-page application** pane, select **Add URI**. +1. Enter the value `https://localhost:3000/dialog.html` and select **Save**. This redirect handles the fallback scenario when the Office dialog API is used. For more information on how to register your application, see [Register an application with the Microsoft Identity Platform](https://learn.microsoft.com/graph/auth-register-app-v2). @@ -105,8 +110,7 @@ For more information on debugging with VS Code, see [Debugging](https://code.vis The `src/taskpane/authConfig.ts` file contains the MSAL code for configuring and using NAA. It contains a class named AccountManager which manages getting user account and token information. - The `initialize` function is called from Office.onReady to configure and initialize MSAL to use NAA. -- The `ssoGetToken` function gets an access token for the signed in user to call Microsoft Graph APIs. -- The `ssoGetUserIdentity` function gets the account information of the signed in user. This can be used to get user details such as name and email. +- The `ssoGetAccessToken` function gets an access token for the signed in user to call Microsoft Graph APIs. The `src/taskpane/document.ts` file contains code to write a list of file names, retrieved from Microsoft Graph, into the document. This works for Word, Excel, and PowerPoint documents. diff --git a/Samples/auth/Office-Add-in-SSO-NAA/package-lock.json b/Samples/auth/Office-Add-in-SSO-NAA/package-lock.json index 6048a33d4..9477e8377 100644 --- a/Samples/auth/Office-Add-in-SSO-NAA/package-lock.json +++ b/Samples/auth/Office-Add-in-SSO-NAA/package-lock.json @@ -9,7 +9,7 @@ "version": "0.0.1", "license": "MIT", "dependencies": { - "@azure/msal-browser": "^3.24.0", + "@azure/msal-browser": "^4.12.0", "core-js": "^3.37.1", "regenerator-runtime": "^0.14.1" }, @@ -497,6 +497,31 @@ "node": ">=18.0.0" } }, + "node_modules/@azure/identity/node_modules/@azure/msal-browser": { + "version": "3.28.1", + "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-3.28.1.tgz", + "integrity": "sha512-OHHEWMB5+Zrix8yKvLVzU3rKDFvh7SOzAzXfICD7YgUXLxfHpTPX2pzOotrri1kskwhHqIj4a5LvhZlIqE7C7g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@azure/msal-common": "14.16.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@azure/identity/node_modules/@azure/msal-common": { + "version": "14.16.0", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.16.0.tgz", + "integrity": "sha512-1KOZj9IpcDSwpNiQNjt0jDYZpQvNZay7QAEi/5DLubay40iGYtLzya/jbjRPLyOTZhEKyL1MzPuw2HqBCjceYA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/@azure/logger": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.1.2.tgz", @@ -511,20 +536,22 @@ } }, "node_modules/@azure/msal-browser": { - "version": "3.24.0", - "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-3.24.0.tgz", - "integrity": "sha512-JGNV9hTYAa7lsum9IMIibn2kKczAojNihGo1hi7pG0kNrcKej530Fl6jxwM05A44/6I079CSn6WxYxbVhKUmWg==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-4.13.0.tgz", + "integrity": "sha512-n2ySryLd+wHmm/0Y1mwFI4J9UXVCu2DeWKtoWNWLVcpvK2k0Ez1qIigKleUm2ZfTbfAXdue+V8htmFft0qgyGQ==", + "license": "MIT", "dependencies": { - "@azure/msal-common": "14.15.0" + "@azure/msal-common": "15.7.0" }, "engines": { "node": ">=0.8.0" } }, "node_modules/@azure/msal-browser/node_modules/@azure/msal-common": { - "version": "14.15.0", - "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.15.0.tgz", - "integrity": "sha512-ImAQHxmpMneJ/4S8BRFhjt1MZ3bppmpRPYYNyzeQPeFN288YKbb8TmmISQEbtfkQ1BPASvYZU5doIZOPBAqENQ==", + "version": "15.7.0", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-15.7.0.tgz", + "integrity": "sha512-m9M5hoFoxhe/HlXNVa4qBHekrX60CVPkWzsjhKQGuzw/OPOmurosKRPDIMn8fug/E1hHI5v33DvT1LVJfItjcg==", + "license": "MIT", "engines": { "node": ">=0.8.0" } @@ -12047,9 +12074,9 @@ } }, "node_modules/tar-fs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.2.tgz", - "integrity": "sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.3.tgz", + "integrity": "sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==", "dev": true, "license": "MIT", "optional": true, diff --git a/Samples/auth/Office-Add-in-SSO-NAA/package.json b/Samples/auth/Office-Add-in-SSO-NAA/package.json index 016019c73..9fea346d6 100644 --- a/Samples/auth/Office-Add-in-SSO-NAA/package.json +++ b/Samples/auth/Office-Add-in-SSO-NAA/package.json @@ -20,7 +20,7 @@ "prettier": "office-addin-lint prettier", "signin": "office-addin-dev-settings m365-account login", "signout": "office-addin-dev-settings m365-account logout", - "start": "office-addin-debugging start manifest.xml desktop --app word", + "start": "office-addin-debugging start manifest.xml desktop --app excel", "start:desktop": "office-addin-debugging start manifest.xml desktop", "start:web": "office-addin-debugging start manifest.xml web", "stop": "office-addin-debugging stop manifest.xml", diff --git a/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/authConfig.ts b/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/authConfig.ts index 2358df712..d126ac960 100644 --- a/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/authConfig.ts +++ b/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/authConfig.ts @@ -109,6 +109,7 @@ export class AccountManager { // Optional fallback if about:blank popup should not be shown if (popupError instanceof BrowserAuthError && popupError.errorCode === "popup_window_error") { const accessToken = await this.getTokenWithDialogApi(); + this.setSignOutButtonVisibility(true); return accessToken; } else { // Acquire token interactive failure. diff --git a/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/fallback/fallbackauthdialog.ts b/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/fallback/fallbackauthdialog.ts index 57109eb75..330ec6ecb 100644 --- a/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/fallback/fallbackauthdialog.ts +++ b/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/fallback/fallbackauthdialog.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -/* This file handls MSAL auth for the fallback dialog page. */ +/* This file handles MSAL auth for the fallback dialog page. */ /* global Office, window, URLSearchParams */ diff --git a/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/msalconfig.ts b/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/msalconfig.ts index add72a0f1..4bb93ec93 100644 --- a/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/msalconfig.ts +++ b/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/msalconfig.ts @@ -8,7 +8,7 @@ import { createLocalUrl } from "./util"; /* global console */ -export const clientId = "Enter your Application ID here"; // Replace with your actual Application ID +export const clientId = "Enter_the_Application_Id_Here"; // Replace with your actual Application ID export const msalConfig = { auth: { clientId, diff --git a/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/taskpane.html b/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/taskpane.html index 6bcd138ec..32023153e 100644 --- a/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/taskpane.html +++ b/Samples/auth/Office-Add-in-SSO-NAA/src/taskpane/taskpane.html @@ -49,7 +49,7 @@

SSO with nested app authentication

Get user files Gets the first 10 items from the user's OneDrive and inserts them in the document. -