Open tiwarigaurav opened 1 year ago
@exextoc Please let me know if you need more details in investigating our issue. We anticipate quick response and resolution to above.
Which Outlook Client are you using? Outlook on Windows/ New Outlook on Windows/Outlook Web / Outlook Mac / Outlook iOS/Andriod?
I am using Outlook desktop app on Windows.
Some other things I have tried so far:
What I did is tried to get the acquireTokenSilent in the app.ts file after the login popup (see below).
const dialogLoginUrl: string = location.protocol + '//' + location.hostname + (location.port ? ':' + location.port : '') + '/login.html';
await Office.context.ui.displayDialogAsync(
dialogLoginUrl,
{height: 40, width: 30},
(result) => {
if (result.status === Office.AsyncResultStatus.Failed) {
}
else {
loginDialog = result.value;
loginDialog.addEventHandler(Office.EventType.DialogMessageReceived, this.processLoginMessage);
}
}
);
processLoginMessage = async (args: { message: string; origin: string; }) => {
let messageFromDialog = JSON.parse(args.message);
if (messageFromDialog.status === 'success') {
loginDialog.close();
console.log(messageFromDialog.result.accessToken);
let msalInstance: PublicClientApplication = new PublicClientApplication({
auth: {
authority: "https://login.microsoftonline.com/organizations/",
clientId: "26431e25-8afe-44de-8ff3-43c6e89e8d86",
navigateToLoginRequestUrl: false
},
cache: {
cacheLocation: "localStorage",
storeAuthStateInCookie: true,
},
});
const authParamsSharePoint = {
account: messageFromDialog.result.account,
scopes: ["https://tenant_name.sharepoint.com/.default"]
};
// I get an error here
let spResp = await msalInstance.acquireTokenSilent(authParamsSharePoint);
console.log(spResp);
}
else {
// Something went wrong with authentication or the authorization of the web application.
loginDialog.close();
}
}
Using the above I get the following error:
Exception has occurred: ClientAuthError: token_refresh_required: Cannot return token from cache because it must be refreshed. This may be due to one of the following reasons: forceRefresh parameter is set to true, claims have been requested, there is no cached access token or it is expired.
Note: that I need to initiate a new instance of the PublicClientApplication as we cannot share the context or variables between the login popup and the app as per Microsoft documentation:
The Office dialog API, specifically the displayDialogAsync method is a completely separate browser instance from the task pane, meaning:
- It has its own runtime environment and window object and global variables.
- There is no shared execution environment with the task pane.
- It does not share the same session storage (the Window.sessionStorage property) as the task pane.
@exextoc - any updates for us on this issue?
You can use the Office.SessionData: https://learn.microsoft.com/en-us/javascript/api/outlook/office.sessiondata?view=outlook-js-preview Or the messageParent method from the displayDialog: https://learn.microsoft.com/en-us/javascript/api/outlook/office.sessiondata?view=outlook-js-preview
You can also alter the lifetime of the token: https://learn.microsoft.com/en-us/azure/active-directory/develop/configurable-token-lifetimes
Hi @zhngx1 - This does not help or address the issue. I am already using messageParent to pass the access token back to the task pane - there is no problems with this. The issue is that when the access token expires and we need to get another one the user will need to click the login button again to trigger the "displayDialogAsync" popup since the "acquireTokenSilent" does not work.
If the issue is with "acquireTokenSilent" API not working, then this is not the correct place for reporting the issue since this is not part of the Office-js API for Outlook.
@zhngx1 - this is not an issue with "acquireTokenSilent" API, it is an issue with Office-JS.
Office JS, for some reason, not sharing the session/local storage between the "displayDialogAsync" popup and the Task Pane so the "acquireTokenSilent" fails.
@tiwarigaurav You can try to use the single sign-on with MSAL.js. Here is the link: https://learn.microsoft.com/en-us/azure/active-directory/develop/msal-js-sso
@zhngx1 - Not sure if you read the document and my previous comment. The document talks about using the browser cache (session/local storage) to access the msal instance in order to do the SSO.
Office JS does NOT allow us to share the (cache) session/local storage between the "displayDialogAsync" popup and the Task Pane. So the example that you referenced in the link above does NOT work.
Have you looked at the SSO quick start documentation at: https://learn.microsoft.com/en-us/office/dev/add-ins/quickstarts/sso-quickstart. That add-in project generated by 'yo office' uses the office.js dialog where needed and is able to do the silent auth otherwise. It sounds similar to what you are trying to, except slightly different auth configuration.
Hi @millerds
Thanks for sharing this. I tried your suggestion however it results in the same issue - let me explain what I did:
Going back to my original issue and conclusion - it seems that the browser cache is not shared between the TaskPane and the displayDialogAsync popup.
@tiwarigaurav
- it seems that the browser cache is not shared between the TaskPane and the displayDialogAsync popup. This is by design. Cache is not shared between dialog and taskpane.
@tiwarigaurav I'm not sure I follow everything you said . . .
dialogFallback function is already being called from sso-helper.ts . . . but only in the case where there was a problem trying to call the middle tier with existing information.
You should be able to use your own AAD app rather than the one our tooling sets up, but that requires other changes in the code to make sure the right app is called . . . and that the app is setup correctly (I personally get confused each time I go through this).
You'll see that in the dialogFallback function acquireTokenSilent is used and does work in Outlook Desktop . . . it's only used once it's known that auth has happened (we have an account id).
Some more information about office dialog and auth can be found at (not sure if you see this one yet) https://learn.microsoft.com/en-us/office/dev/add-ins/develop/auth-with-office-dialog-api which notes some caching boundaries. between the dialog and the taskpane (different "browser instances").
@millerds - I'll try and explain.
Since Office Web Add-In's are supposed to be compatible across browsers and across platforms we cannot rely on SSO (SSO does not work in Safari and other exceptions). So we need the dialogFallback function. For this reason, in my testing I removed the SSO part and directly call the dialogFallback function from sso-helper file.
If you add break points to the dialogFallback function you will see that the acquireTokenSilent never hits and always ends up in the else branch acquireTokenSilent.
Note I am using Outlook Desktop app on Win 10 machine
Thank you @tiwarigaurav for bringing this up. I will verify this and get back to you.
Thanks for reporting this issue regarding acquireTokenSilent never hits in the SSO template. It has been put on our backlog. We unfortunately have no timelines to share at this point.
Internal tracking id: Office: 8583385
I am developing an Outlook Web Add-In using
Yeoman generator-office Office.Js REACT framework azure/msal-browser version 2.32.2
As per Microsoft/Office Add-In/MSAL team's best practice - I am performing a popup auth in the office dialogue using the office SDK, and then perform loginRedirect inside that popup. In my App.tsx file I have the following code to do the popup:
In my login.ts file I have the following code:
Using the above setup I can get the Graph Access Token just fine and everything works.
How can I get access token for multiple resources using the msalInstance.acquireTokenSilent(scope) within the app.ts file?
What I have been able to do so far is to call msalInstance.acquireTokenSilent(sharepointScopes) in the login.ts file and get the SharePoint Access Token too. However this is not ideal in a production environment as the access token expires in 1 hour, so the user will again need to click a button to initiate the popup to get another token.
The main idea is to use the login popup once to initiate the msalinstance and for any subsequent scopes/resources (or when the initial access token expires) use the acquireTokenSilent method - so that the user does not need to click the login button again to get another token.
What I have seen is - if I can get the msal instance back from the popup to the react app then I can reuse it to call "acquireTokenSilent" - which will solve the issue.